|
| 1 | +# 修复zsh上patchelf自动补全的错误 |
| 2 | + |
| 3 | +如果你使用zsh来作为你的主力shell的话,那你在使用patchelf的时候一定受到过这样的困扰: |
| 4 | +在尝试补全`--set-interpreter`后的参数时,按下tab就变成了 *_arguments:463: command not found: dynamic*; |
| 5 | +在尝试补全`--replace-needed`后的参数时,又变成了 *_arguments:463: command not found: LIB_ORIG*, |
| 6 | +这个问题已经存在了一年多,也困扰了我很久 |
| 7 | + |
| 8 | +直到有人就因为这个小事,不愿尝试zsh,那不是丢了西瓜捡芝麻,zsh这么好用的说... |
| 9 | + |
| 10 | +## 前情提要 |
| 11 | + |
| 12 | +早在21年,**@Y7n05h**[尝试为zsh增加补全支持](https://github.com/NixOS/patchelf/issues/310), |
| 13 | +但随着他不再使用patchelf,他也停止了补全脚本的编写 |
| 14 | + |
| 15 | +23年,**@Freed-Wu**接过了任务,完成了补全脚本并提交了PR,但是他的脚本并不完全正确, |
| 16 | +导致了zsh无法正确补全 |
| 17 | + |
| 18 | +## 修复 |
| 19 | + |
| 20 | +首先就是针对上面两个常用arg进行修复,我先尝试问了下ChatGPT, |
| 21 | +在[文件](https://github.com/NixOS/patchelf/blob/master/completions/zsh/_patchelf#L5)中, |
| 22 | +`INTERPRETER`是消息,`dynamic loader`是描述,而`_files`是命令,那为什么无法运行呢? |
| 23 | + |
| 24 | +查阅别人写的[zsh自动补全脚本入门](https://chuquan.me/2020/10/02/zsh-completion-tutorial/), |
| 25 | +发现多了一个参数,正确示例是`-OPT[DESCRIPTION]:MESSAGE:ACTION`,那么修复起来就很简单了, |
| 26 | +只要把多余的参数去掉,换上`_files`,就能正常运行了 |
| 27 | + |
| 28 | +## 增强 |
| 29 | + |
| 30 | +patchelf还可以`--print-needed`,那么是不是可以把打印出来的依赖,作为`--replace-needed`的补全呢? |
| 31 | +在ChatGPT的帮助下,这下可以在判断对象文件是elf的情况下,按tab补全它的依赖了 |
| 32 | + |
| 33 | +但是,ChatGPT给的是类似与bash与zsh脚本的混合,那既然都选了zsh了,就替换为zsh语法吧 |
| 34 | + |
| 35 | +跟着[别人的指引](https://github.com/goreliu/zshguide),我又把补全脚本完善了一遍, |
| 36 | +加速了条件的判断,也提高了对文件范围的判断, |
| 37 | +详细可见这个[commit](https://github.com/RocketMaDev/patchelf/commit/61a49b905c2eb329848349dc8c0eb6c5fa873aa7) |
| 38 | + |
| 39 | +## 安装使用 |
| 40 | + |
| 41 | +本文对应的PR: https://github.com/NixOS/patchelf/pull/552 |
| 42 | +1. `echo $fpath`列出补全文件搜索目录 |
| 43 | +2. 找到`_patchelf`文件所在位置(如在我这里是在`/usr/local/share/zsh/site-functions`中) |
| 44 | +3. 从我的仓库中下载`_patchelf`并替换你的`_patchelf` |
| 45 | +```sh |
| 46 | +curl -o /path/to/your/_patchelf https://raw.githubusercontent.com/RocketMaDev/patchelf/master/completions/zsh/_patchelf |
| 47 | +# 可能需要root |
| 48 | +# 或者手动复制并覆写 |
| 49 | +``` |
| 50 | +4. 执行`unfunction _patchelf && autoload -U _patchelf`或重启shell |
| 51 | +5. (可选)在Arch Linux上,只要更新patchelf,补全脚本就会被覆盖,因此可以写一个函数, |
| 52 | +放在`~/.zshrc`中,方便在patchelf更新的时候再次覆盖脚本 |
| 53 | +```zsh |
| 54 | +update_patchelf() { |
| 55 | + sudo curl -o /usr/share/zsh/site-functions/_patchelf "https://raw.githubusercontent.com/RocketMaDev/patchelf/master/completions/zsh/_patchelf" |
| 56 | + unfunction _patchelf && autoload -U _patchelf |
| 57 | +} |
| 58 | +``` |
| 59 | +推荐patch对象前置,例如`patchelf $ELF --replace-needed [TAB]`,这样方便补全, |
| 60 | +否则就需要先留个空位,然后写上要替换的so的路径,写上patch对象,再回过去补全 |
| 61 | + |
0 commit comments