zshで特定のコマンド名にとにかく補完関数を割り当てたい

partition で innodb とかを試してたのに、テストデータを大きく取りすぎて全然おわんないです。もうちょい小規模でやれば良かった。

ということで最近mysqlphpの話ばかりなので、たまにはzshのことでも。

補完関数のおさらい

自分のホームディレクトリとかにある ~/bin/aho.sh にちゃんと補完関数を書きたくなったときは、

#compdef aho.sh

_aho.sh() {
    local curcontext="$curcontext" state line expl ret=1

    _arguments -C -s \
        '(-v --version)'{-v,--version}'[show version]' \
        '(-h --hoge)'{-h,--hoge}'[set hoge]:set hoge:(foo bar)' \
        '(-f --fuga)'{-f,--fuga}'[set fuga]:set fuga:->fuga' \
        && ret=0

    case "$state" in
    fuga)   
        choise=(nurupo damepo) 
        _wanted fuga expl 'fuga' compadd -a choise && ret=0
        ;;
    esac    

    return ret
}

みたいなのを _aho.sh ってファイル名にして自分の fpath に突っ込んであげれば補完が効くようになります。なんとなく関数名にドットが入るのが不安ですが、数字とかでも動いてるようです。

fpath を ~/.zshrc.d/func/ とすれば、上の _aho.sh は func ディレクトリの下に置いてあげて、 .zshrc はこんな感じ。

fpath=(~/.zshrc.d/func $fpath) 
autoload -U compinit
compinit -u

これで実行しようとしてるコマンド名からうまいこと _aho.sh というファイルを探し、 _aho.sh という関数を呼び出してくれる。

まあここまではよくある話ですね。

だと思っていたんですけど!

なんかうまくいかないんですよね、これが。で、どうもセキュリティの都合だかよくわかんないけど、なんかの条件をみたす実行ファイルは自動で補完関数をロードしてくれないみたい。上の例だとうまくいくんだけど。

で、その条件が何なのかはもうちょい zsh の補完の仕組みを理解しないといけなそうなので今回は挫折。かわりに、次のようなのを .zshrc とかに書けば「とにかくこの関数を使え!」と指示できることがわかった。ちなみに、いわゆるパス ($path) が通ってなくても OK です。

compdef _aho.sh aho.sh

補完関数の定義ファイルの先頭で書いていた #compdef (補完関数の"タグ"と呼ぶらしい) を、ヒントとして渡すのではなく、直接叩いてしまう感じなんだと思います。

さらには

compdef _aho.sh -p "aho*.sh"

とやってあげると、 aho1.sh とか aho2.sh とかを、同じ補完関数でまとめて面倒を見てあげることができました。

どうもこのへん、バージョンによって微妙な違いがあるようです。手元の環境の

で試したけどいまいちナゾが多い。

zshの話はネット上を探すと新旧いろんな情報が入り乱れていて、なにが今の流儀なのかさっぱりわかんないです。どっかでバージョン固定して誰かまとめてくれないかなー。