Bashの補完について に引き続き、 ZshのTabを押した時に出る補完の自作等について。
Zsh補完
compinit
Zshで補完を有効にするためにはまず、
autoload -U compinit
compinit
を実行する必要があります。
compinit
が色々設定をしたりする関数なんですが、
autoload
してから呼んであげる必要があります。
autoload
については以下のページが丁寧に説明されてて分かりやすいです。
有効にするために取り敢えずこれを.zshrcなんかに書いておきます。
ちなみに
zsh compinit: insecure directories, run compaudit for list.
Ignore insecure directories and continue [y] or abort compinit [n]?
みたいなWARNINGが出ることがありますが(特にCygwinで出る)、
簡単にこれを避けるためにはこの様なチェックを入れないようにcompinit -u
を使う事が一つあります。
もう少ししっかりやるには該当のディレクトリ (大概は/usr/local/share/zsh/site-functions)のパーミッションを変更
$ sudo chown -R root:root /usr/local/share/zsh/site-functions
$ sudo chmod -R 755 /usr/local/share/zsh/site-functions
してあげると治ることがあります。
zsh completion - zsh compinit: insecure directories - Stack Overflow
comopdef
あるコマンドに対して補完を出来るようにしてあげるには
$ compdef _comp_func cmd
とcompdef
コマンドを使います。
これでcmd
というコマンドに対する補完を_comp_func
で決めることになります。
Bashのcomplete
コマンドと違って
-F
とか使わず最初の引数に補完を決める関数を渡します。
その後に補完したいコマンドを与えます。 複数コマンドもその後に
$ compdef _func cmd1 cmd2 cmd3
と書いていけばまとめて同じ補完が指定できます。
補完補助関数
compadd
補完の指定は
compadd aaa bbb ccc
の様にcompadd
に補完したいものを引数として渡してあげればOK。
このコマンドに渡しただけ補完が増えるので 補完を指定する関数内で
compadd aaa bbb ccc
compadd ddd eee fff
とするとこれら6つ全てが補完に入ります。
Zshの補完の場合は、これで指定するだけで 途中まで書いた状態でのTabでの絞込など勝手にやってくれます。
補助関数
Zshのcompadd
はかなり高機能で、
補完の表示時にも全体の説明を加えたり、
補完の文字列毎に説明を載せたり
することが出来ます。
これらをcompadd
のオプションで指定して直接使うことも出来ますが、
Zshには色々と便利に補完を決めるための補助関数が用意されています
1。
これらの関数の中では最終的にcompadd
を使って
補完を決めています。
以下、いくつかよく使うものについて。
_files
引数を与えなければ現在のディレクトリのファイルやディレクトリを 補完するようになります。
-W <PATH>
でパスを指定してその中の物だけ、を指定することも出来ます。
_path_files
という関数もあって、_files
はこれの更なる
ラッパー関数みたいなもので、_path_files
から
-g <pattern>
(patternにマッチするものだけを補完)と
-/
(ディレクトリだけを補完)
のオプションを除いたものになっています。
-
_values
_values “description of completion” aaa bbb ccc
とすると、aaa bbb cccの補完を加えます。
最初のdescription…は全体の説明になります。
このdescriptionの部分を補完時に表示させるには 予め.zshrcとかで
zstyle ':completion:*' format '%B%d%b'
とかしておく必要が有ります。
zsytle
でZshの色々な表示設定が出来、ここでは
補完時の表示設定で、format
は全体の説明部分の表示設定になります。
%B
は太文字開始、%b
が太文字終了、
間の%d
が補完の関数で決められたdescription
の内容になります。
他にも%U
~%u
でアンダーラインを引いたり色々変更することも出来ます。
また、それぞれの補完の説明などを加えるには、
_values "description of completion" 'aaa[explain aaa]' 'bbb[explain bbb]'
みたいにすると[]
内がaaa
の説明として出ます(全体をクォートする必要あり)。
$ cmd <Tab>
description of completion
aaa -- explain aaa
bbb -- explain bbb
こんな感じ。
_arguments
主に-X
みたいなハイフン付きのオプションを解析するのに使います。
_arguments '-a' '--aaa'
とすると これらの補完が有効になります。
_values
の様に、-a[description of -a]
とすると説明が出ます。
また、{-a,--aaa}'[description of -a/--aaa]
とすると-a
と--aaa
を
同じ意味のオプションとしてまとめられます。
(この場合はクォートは{}の後から)。
_arguments
の書き方としてはいくつかありますが、その1つとして
'-a:messsage for -a:->aaa'
の様な書き方があります。
この書き方をすると、最初の-a
がオプション、:
で区切った次がメッセージ、最後がアクションになります。
メッセージは_valuesのdescriptionと同じように補完リストを表示する時に 上に表示されるメッセージです。(要らなければ空欄に。)
最後のアクションは-a
が書かれた次の引数の補完で、
単に文字列を与えたければ(aaa bbb ccc)
みたいに配列を与えればOK。
ここに関数を与えることも出来、
'-a:message for -a:a_func'
としておいて、
1 2 3 |
|
みたいな関数を用意してあげても同じことです。
さらに->
を使う書き方をすると-a
がある場合に、この部分でstate
という変数にaaa
を代入することになります。
_arguments
を設定する項目を書いた後、その後でこのstate
を使って色々場合分けが出来る様になる、とういこと。
1 2 3 4 5 6 7 |
|
みたいにすると、-a
と書いた次のところではa_1
、a_2
、a_3
が補完に使われます。
words, CURRENT
Zshの補完補助関数の中でも
BashのCOMP_WORDS
やCOMP_CWORD
に当たるものがあり、
それぞれwords
、CURRENT
という変数に入っています。
ただし、CURRENT
はコマンドの位置が0ではなく1になってるので、
COMP_CWORD
に比べて1つ大きな数字になります。
また、Zshは通常配列の番号が0ではなく1から始まります。
setopt ksharrays
とするとKshやBashの様に
0から始まる配列になりますが、この辺も注意が必要です。
配列をlocal
で使う時に直接local a=(...)
と書くとエラーが出るので
最初に宣言だけして後で代入する必要があるところも
ちょっとしたハマりどころ。
1 2 3 4 |
|
みたいな物をsource
してみると
$ test_cmd <Tab>
2 test_cmd
$ test_cmd aaa<Tab>
# This puts one space, as 'aaa' is completed.
$ test_cmd aaa <Tab>
3 aaa test_cmd
$ test_cmd aaa bbb <Tab>
4 aaa bbb test_cmd
$ test_cmd aaa <Tab> bbb
3 aaa bbb test_cmd
な感じでBashの時より1つ大きな数字が出ます。
zsh-completions
zsh-completions はZshの補完を拡張してくれる設定が入ったパッケージです。
上のGitHubのREADMEに従ってファイルを配置するか、 MacならHomebrewで
$ brew install zsh-completions
で/usr/local/share/zsh-completionsに 補完ファイルが入ります。
これを有効にするには
1 2 3 |
|
とします。
ここでfpath
は補完用のスクリプトファイルが入った
ディレクトリ群の配列で、
これに必要なディレクトリを加えたあと、
compinit
をすることで
~/.zcompdumpというファイルがアップデートされ、
このファイルに従って補完が行われる様になります。
Homebrewで色々インストールすると、 他のパッケージ内からのZsh補完用スクリプトは 上のzsh-completionsではなく、 /usr/local/share/zsh/zsh-site-functionsの方に入ります。
これらを有効にするためには
1 2 3 4 5 6 7 8 |
|
みたいにしてあげておけばOK。
MacのHomebrewでZsh補完のファイルをインストールするFormulaを作る
上にも書いたとおり、通常HomebrewでZsh補完ファイルをインストール しようとすると share/zsh/zsh-site-functionsなディレクトリにインストールされます。
なので、パッケージ内にshare/zsh/zsh-site-functions/_my_comp_file みたいなファイルを作り、補完関数の定義を書きます。 (この位置も名前も実用上は何でも良い。)
Bashの時同様、
1 2 3 4 5 6 |
|
みたいな感じに書いてあげればOK。
zsh_completion
はprefix
+”share/zsh/zsh-site-functions”
になります(prefix
は通常/usr/local/。
この辺も最近 Brew-file で色々アップデートしたのでBrew-fileのFormulaや補完関数も参考になるかも。