zshのzstyleでの補完時の挙動について
zshというシェルはデフォルトでも素晴らしいのですが、あまりに拡張性が高いので全ての機能を使いこなすのは逆に難しいと思います。
特にzstyleというコマンドの文脈に応じた補完候補への設定関数は、使用するとどうなるのかヘルプを見てもWeb上を見てもよく分かりません。
そんなわけでzstyleの挙動について調べてみました。
参考にしたサイト
http://www.gentei.org/~yuuji/rec/pc/zsh/zshcompsys.txt
http://wiki.fdiary.net/zsh/?ColoredCompletion
http://grml.org/zsh/zsh-lovers.html
http://www.dna.bio.keio.ac.jp/~yuji/zsh/zshrc.txt
http://q-eng.imat.eng.osaka-cu.ac.jp/~ippei/unix/zsh.html
準備
色の定義をしておくと後々楽だと思います。
補完キーはCtrl-iに設定しました。
以下を($HOME)/.zshrcに書いておきます(必要なのは色の設定だけなので、別に全部書く必要は無いです。)
自分はこんな感じにしています。(.zshrcの一部を抜粋)
#色の定義 local DEFAULT=$'%{^[[m%}'$ local RED=$'%{^[[1;31m%}'$ local GREEN=$'%{^[[1;32m%}'$ local YELLOW=$'%{^[[1;33m%}'$ local BLUE=$'%{^[[1;34m%}'$ local PURPLE=$'%{^[[1;35m%}'$ local LIGHT_BLUE=$'%{^[[1;36m%}'$ local WHITE=$'%{^[[1;37m%}'$ #補完に関するオプション setopt auto_param_slash # ディレクトリ名の補完で末尾の / を自動的に付加し、次の補完に備える setopt mark_dirs # ファイル名の展開でディレクトリにマッチした場合 末尾に / を付加 setopt list_types # 補完候補一覧でファイルの種別を識別マーク表示 (訳注:ls -F の記号) setopt auto_menu # 補完キー連打で順に補完候補を自動で補完 setopt auto_param_keys # カッコの対応などを自動的に補完 setopt interactive_comments # コマンドラインでも # 以降をコメントと見なす setopt magic_equal_subst # コマンドラインの引数で --prefix=/usr などの = 以降でも補完できる setopt complete_in_word # 語の途中でもカーソル位置で補完 setopt always_last_prompt # カーソル位置は保持したままファイル名一覧を順次その場で表示 setopt print_eight_bit #日本語ファイル名等8ビットを通す setopt extended_glob # 拡張グロブで補完(~とか^とか。例えばless *.txt~memo.txt ならmemo.txt 以外の *.txt にマッチ) setopt globdots # 明確なドットの指定なしで.から始まるファイルをマッチ bindkey "^I" menu-complete # 展開する前に補完候補を出させる(Ctrl-iで補完するようにする)
zstyleのフォーマットについて
これがまたすごくいい感じに意味不明なんですが、
zstyle ':completion:*:*:コマンド:*:タグ' スタイル
のような感じで定義していきます。
細かいことはとりあえずhttp://www.gentei.org/~yuuji/rec/pc/zsh/zshcompsys.txtを見ればちょっとだけ分かったような気になります。
ヘルプを読むためのヘルプが必要な時点で完全に理解するのはたぶん無理です!
書いて試してみれば割となんとかなるので、気にせず書いていきましょう。
zstyleをどんどん書いていく
補完候補を ←↓↑→ でも選択出来るようにする
zstyle ':completion:*:default' menu select=2
自分の場合はCtrl-iをゴリゴリ押すか、Ctrl-f,Ctrl-bでたまに横方向に移動させてます。
そしてCtrl-m(Enterと同じ)で決定させます。
補完関数の表示を過剰にする編
zstyle ':completion:*' verbose yes zstyle ':completion:*' completer _expand _complete _match _prefix _approximate _list _history zstyle ':completion:*:messages' format $YELLOW'%d'$DEFAULT zstyle ':completion:*:warnings' format $RED'No matches for:'$YELLOW' %d'$DEFAULT zstyle ':completion:*:descriptions' format $YELLOW'completing %B%d%b'$DEFAULT zstyle ':completion:*:corrections' format $YELLOW'%B%d '$RED'(errors: %e)%b'$DEFAULT zstyle ':completion:*:options' description 'yes' # グループ名に空文字列を指定すると,マッチ対象のタグ名がグループ名に使われる。 # したがって,すべての マッチ種別を別々に表示させたいなら以下のようにする zstyle ':completion:*' group-name ''
補完するときに、ただ補完候補を出すだけでなく、コマンドの文脈に応じて何の補完をするか表示してくれます。
2行目のCompleter(補完システム)は色々種類があって、
- _complete
- 普通の補完関数
- _approximate
- ミススペルを訂正した上で補完を行う。
- _match
- *などのグロブによってコマンドを補完できる(例えばvi* と打つとviとかvimとか補完候補が表示される)
- _expand
- グロブや変数の展開を行う。もともとあった展開と比べて、細かい制御が可能
- _history
- 履歴から補完を行う。_history_complete_wordから使われる
- _prefix
- カーソルの位置で補完を行う
などのような補完候補を表示できます。
この場合、_approximateコンプリータによってミススペルが修正されて補完されているのがわかりますね!
また、グロブによっての補完もできます。
この場合、通常のzshならばここで補完しようとすると全てのファイルが展開されてしまうのですが、
展開する前に補完する設定にしたので次のように表示されます
個人的にはこちらの挙動の方が好きです。(実はCtrl-dでも展開せずに補完できるけど、全てCtrl-iにやらせるのがポイント)
オブジェクトファイルとか中間ファイルとかはfileとして補完させない
zstyle ':completion:*:*files' ignored-patterns '*?.o' '*?~' '*\#'
補完してほしくないファイルを表示させないようにできるので便利
ディレクトリを切り替える時の色々な補完スタイル
#あらかじめcdpathを適当に設定しておく cdpath=(~ ~/myapp/gae/ ~/myapp/gae/google_appengine/demos/) # カレントディレクトリに候補がない場合のみ cdpath 上のディレクトリを候補に出す zstyle ':completion:*:cd:*' tag-order local-directories path-directories #cd は親ディレクトリからカレントディレクトリを選択しないので表示させないようにする (例: cd ../<TAB>): zstyle ':completion:*:cd:*' ignore-parents parent pwd #LS_COLORSを設定しておく export LS_COLORS='di=34:ln=35:so=32:pi=33:ex=31:bd=46;34:cd=43;34:su=41;30:sg=46;30:tw=42;30:ow=43;30' #ファイル補完候補に色を付ける zstyle ':completion:*' list-colors ${(s.:.)LS_COLORS}
例えばcdpathを設定しておいて、上のzstyleを適用させると
lsをしたところaから始まるディレクトリは無いみたいですが・・・
ここで補完キーを押すと
cdpath上のディレクトリを勝手に補完してくれます!
あと、cdしたらいちいちlsするのがめんどくさいので、
#cdを打ったら自動的にlsを打ってくれる関数 function cd(){ builtin cd $@ && ls; }
のようになります!
apt-getとかdpkgコマンドをキャッシュを使って速くする
zstyle ':completion:*' use-cache true
特にsudo apt-get updateがめちゃめちゃ速くなります!
セパレータを設定する
zstyle ':completion:*' list-separator '-->'
オプションとかを表示するときのセパレータを指定します。(デフォルトは'--'です。)
別に設定しなくてもいいですが、zshはここまでも設定できるということで!
例えば、ここで補完ボタンを押すと・・・
のようになります。
変数の添字を補完する
zstyle ':completion:*:*:-subscript-:*' tag-order indexes parameters
別に補完できなくてもいいんですが、そういう機能もあると紹介してみます。
こういう配列を定義しておいて、ここで補完ボタンを押すと・・・
のようになります。
zshの配列の添字は1から始まるのか!!!?
manの補完をセクション番号別に表示させる
zstyle ':completion:*:manuals' separate-sections true
一番どうでもいいかもしれない補完ですね!
manのセクション番号についてはhttp://www.linux.or.jp/JF/JFdocs/Man-Page-2.htmlに載っています。
これを適用すると・・・
のようになります。
最後に
まとめて紹介しすぎたので今回はこれで締めますが、
他にも色々とあるので、また別の機会に紹介します!