親ディレクトリへの移動が楽になるコマンド Tarrasch/zsh-bd を自分で実装してちょっと拡張してみた。
動機
引数なしで bd
コマンドを実行したときに1つ上のディレクトリに移動したら楽なのになあっと思っていたら Github の issue にもう上がっていた。
Feature request: bd with no arguments should move up one directory #18
ただ、作者にエイリアス alias up='cd ../'
を登録すれば良いじゃんと言われしまっている…
やりたかったこと
- 引数無しで
bd
を実行したときに1つ上のディレクトリに移動 - 現在のディレクトリを移動対象から外す
- TAB補完で大文字・小文字を無視する
- TABを押したときに表示される親ディレクトリのリストを親→子の順で表示する
1−3については zsh-bd の issue でも提案されている。4は単純に好みの問題で、zsh-bd では子→親の順で表示される。
実装
zsh-bd のライセンスが不明なので自分で一から作ることにした。
ソースコードは Github に置いてあります(ryutok/zbd)。
概要
__zbd:count
は与えられた名前のディレクトリの位置を調べる関数。
__zbd:cd
は与えられた数だけ '../' を連結して cd
を実行する関数。
引数が与えられた場合、まず __zbd:count
でその名前の親ディレクトリがあるかを調べ、無かった場合には引数が数字なら直接 __zbd:cd
にその数を渡す。引数が与えられていない場合、 __zbd:cd
に1を渡して、1つ上のディレクトリに移動する。
TAB補完
Google 検索で最初に見つけた方法は、別記事(zsh-bd の Tab 補完で大文字・小文字を無視する)に書いたとおり、 compctl
でコマンドの補完関数を指定するときに -M <match_spec>
オプションで直接指定する方法。ただ、この方法だとユーザーごとに好みの <match_spec>
を指定することができない。
そこで、新しい補完システム(compdef
, compadd
) を用いることにした。これにより、.zshrc
内の設定 zstyle ':completion:*' matcher-list <match_spec>
が反映される。補完システムを定義しているコードは以下の通り。
function _zbd {
declare -a args
args=(
'-h[print help]'
'1:parents:__zbd:add_parents'
)
function __zbd:add_parents {
__zbd:get_parents
_wanted -V values expl 'parents' compadd $parents
}
_arguments $args
}
compdef _zbd zbd
最後の行 compdef
で zbd
コマンドに対する補完を定義する関数 _zbd
を指定している。関数 _zbd
では、配列 args
を定義して _arguments
に渡している。これにより、zbd
を実行する際、ハイフンの後ではオプションが補完され、それ以外の場合は __zbd:add_aprents
で生成される親ディレクトリが補完される。この書き方は mollifier/cd-gitroot を参考にした。
__zbd:get_aprents
は親ディレクトリのリストをグローバル変数 $parents
に格納する関数で、その親ディレクトリのリストを compadd
に渡すことで補完リストに追加している。ここで、 _wanted
を用いているのは、親ディレクトリのリストを親→子の順のまま補完リストに表示するためである。(参考:Custom zsh completion: custom sort?)