一个复杂的小 bug: cd 补全问题
如果你同时在使用 fnm,bash-completion, bash-it 的 aliases.completion.bash 这三个工具,你会遇到一个 BUG。
BUG 描述
使用 cd 按 Tab 补全路径时,每个路径都会额外加上一个空格。
比如 cd /<Tab>
然后选中 /usr,补全后变成 cd /usr <光标位置>
。但正常期望的应该是 cd /usr<光标位置>
。
复现问题
省略,懒得写。
排错关键
当同时使用 fnm, bash-completion, bash-it 的 aliases.completion.bash:
> complete -p cd
complete -F _comp_complete_minimal cd
> alias cd
alias cd='__fnmcd'
> complete -p __fnmcd
complete -F _comp_complete_minimal __fnmcd
当同时开启 bash-completion 和 bash-it 的 aliases.completion.bash,不使用 fnm:
> complete -p cd
complete -o nospace -F _comp_cmd_cd cd
> alias cd
-bash: alias: cd: not found
> complete -p __fnmcd
-bash: complete: __fnmcd: no completion specification
当同时开启 bash-completion 和 fnm,不使用 bash-it 的 aliases.completion.bash:
> complete -p cd
-bash: complete: cd: no completion specification
> alias cd
alias cd='__fnmcd'
> complete -p __fnmcd
-bash: complete: __fnmcd: no completion specification
当同时开启 bash-it 的 aliases.completion.bash 和 bash-completion, fnm,不使用 bash-completion:
> complete -p cd
-bash: complete: cd: no completion specification
> alias cd
alias cd='__fnmcd'
> complete -p __fnmcd
-bash: complete: __fnmcd: no completion specification
原因分析
根因不在 bash-completion 也不在 bash-it,而在于 fnm 的 --use_on_cd
参数。
fnm 的初始化这么写:eval "$(fnm env --use-on-cd --shell bash)"
然而在 fn use_on_cd
可以看到这段。
__fnmcd()
alias cd=__fnmcd
__fnm_use_if_file_found
_comp_complete_minimal
是 bash-completion 源码里定义的。
由于 alias cd='__fnmcd'
的存在,aliases.completion.bash 会把 cd 的补全函数用 __fnmcd 的补全函数代替。
而 aliases.completion.bash 也会给 __fnmcd 添加一个 complete -F _comp_complete_minimal __fnmcd
这就导致了 complete -F _comp_complete_minimal cd
。
解决办法
不要用 –use-on-cd 参数。这功能只是在 cd 目录时自动查找是否存在 .node-version 或 .nvmrc 文件,自动切换 node 版本用的。
eval "$(fnm env --shell bash)"