vim-jp の Slack で「zsh の PATH 環境変数に相対パスを含んでいる場合、補完ができないけど意図的か」という話題が出たので調べてみた。
補完できない様にしているのはこの変更
39104: do not hash relative paths in findcmd() · zsh-users/zsh@b312abc
https://github.com/zsh-users/zsh/commit/b312abc93b3b8eae8feb4a9884b22f519a137c7f
結構古い変更。この変更が行われた理由を追ってみた所、メーリングリストでこの会話が見つかった。
Running 'type' causes false positive hashed command completion
Zsh Mailing List Archive Messages sorted by: Reverse Date , Date , Thread , Author Running 'type' ca...
http://www.zsh.org/mla/workers/2016/msg01583.html
$ zsh -f
% cd $(mtemp -d)
% touch sudofoo; chmod +x $_
% ./sudo<TAB>
<becomes>
% ./sudofoo <^C>
% type -w ./sudo
./sudo: none
% ./sudo<TAB>
./sudo sudofoo*
That's wrong because ./sudo does not exist. However, it's hashed:
% print $commands[./sudo]
/usr/bin/./sudo
To confuse matters further, even though "./sudo" is hashed, a subsequent
'type -w ./sudo' will print "none", because the hash node lacks the
HASHED bit in its .flags and the PATH_DIRS option is unset by default.
「/usr/bin
対しては ./sudo
が存在する為、sudofoo
に対する ./sudo
からの補完候補に sudo
が出てきてしまう、これは混乱を生んでしまう」という物だった。これを回避する為に上記の変更で相対パスはハッシュしない様にしている。ちなみに bash や fish だと相対パスの中のコマンドも補完された。
相対パス上で sudofoo
の一部 sudo
が補完されてしまったとして困るのは、その相対パス内に危ないファイルを追加してしまった場合だろうと推測するが、そもそも相対パスを PATH に追加したい要件が僕には見つからなかった。おそらく自動的に
node_modules/.bin
内のコマンドを扱える様にしたいといった物だと思う。もし zsh でやりたい人は direnv を使って動的に PATH を追加するのが良いと思う。