今回はzshの誇る機能の花形とも言える補完機能について紹介しよう。zshの補完は強大で、
補完の有効化
初期化ファイル、
autoload -U compinit && compinit
補完に関するキー割り当てはいくつもあるが、
- Tab (C-i) -
expand-or-complete
補完の実行。 - ESC C-d (または行末のみ C-d) -
list-choices
(delete-char-or-list
)
マッチする候補の一覧表示。
ちなみに、
- C-x* -
expand-word
カーソル位置に含まれる単語をシェルの展開規則によってその場で展開。 - C-xg -
list-expand
カーソル位置に含まれる単語がどのように展開されるかを一覧表示。
Tabによる補完とESC C-dによる候補表示を使いながら標準装備されているきめ細やかな補完を確認してみよう。ただし、autolist
によってTab補完時、zshrc
をロードした状態を前提としている部分がある。
1.ファイル名補完
他のシェルにもある最も基本的なファイル名補完は、
% cd /usTab % cd /usr/ (/us で始まるファイル名に) % cd /u/l/a/coTab % cd /usr/local/apache/conf/ (/ の前に * を補ったパターンで補完)
このように、*
があると見なして補完することで、~/.emacs
などで (partial-completion-mode t)
している場合)
tcshで `set complete=enhance
' している場合も同様の部分補完ができる。tcshではピリオド、
zstyle ':completion:*' matcher-list 'm:{a-zA-Z}={A-Za-z} r:|[-_.]=**'
これは、*
を補ったかのように補完してみる」
% ls -F extra/ httpd.conf magic mime.types original/ % less m.tTab % less mime.types
タイプ数削減の大きな味方だ。ところが、
% ls
highperformance-std.conf magic
highperformance.conf mime.types
httpd-std.conf ssl-std.conf
httpd.conf ssl.conf
このようなファイルがある場合にhttpd.
を編集しようと以下のように補完すると期待どおりにいかない。
% vi httpd.Tab % vi httpd-std.conf
これは、httpd.
' までタイプすればファイル名が一意に定まると思ってそこまでしっかり打ったのに、Tabを押したら想定外の httpd-std.
が出てがっかり、zstyle
例を以下のように変更する。
zstyle ':completion:*' matcher-list '' 'm:{a-zA-Z}={A-Za-z} r:|[-_.]=**'
中央付近に足した ''
がそれで、''
)'m:{a-zA-Z}={A-Za-z} r:|[-_.]=**'
という規則適用でやれ、
もうひとつ例を欲張っておこう。
zstyle ':completion:*' matcher-list '' 'm:{a-z}={A-Z}' '+m:{A-Z}={a-z}'
これは、
- まず入力された文字そのままで補完してみて
- それでマッチするものがなければ、
小文字を大文字に変えつつ補完してみて - それでもマッチするものがなければ、
大文字を小文字に変えるルールを追加 (` +
')して補完してみよ
以上文字の種別を変えて補完を試みる設定を示したが、
2.変数補完
コマンドラインでシェル変数や環境変数を入力しようとしている場所では変数名を補完する。通常、
% MATab Completing parameter MACHTYPE MAILCHECK MAILDIR MAILPATH MANPATH % MANTab % MANPATH=
また、$VARIABLE
という形式だけでなく、${HOME}
あるいは$HOME:h
のような形もよく利用する。zshではこれらも目の前に展開することなく正しく補完できる。
(ホームディレクトリの親ディレクトリにアクセスする例) % ls ${HOTab Completing parameter HOME HOST % ls ${HOMTab % ls ${HOME}/ ($HOME値がパス名なので自動的に / が補われる) (続けて : を入力する) % ls ${HOME: (}/ が自動的に消えるので h}/ を入力) % ls ${HOME:h}/Tab Completing files .... ($HOME/../ にあるファイル(ディレクトリ)一覧が表示される)
3.ユーザ名・ホスト名補完
SSHのように引数にユーザ名やホスト名を必要とする引数位置では、
% ssh yTab Completing remote host name yankee yourpc.example.com Completing login name yas yukita yuuji
sshコマンドでは、
ssh remotehost
ssh username@remotehost
そのため `ssh y
' とだけ入力した y
はホスト名、~/.ssh/
ファイルから自動的に取得され、
候補とするユーザ名、
zstyle ':completion:*' users-hosts \
user1@{host1,host2} {user2,user3}@{host3,host4}
この記述は、
上記の設定で補完を行なうと以下のようになる。
% ssh Tab Completing remote host name host1 host2 host3 host4 Completing login name user1 user2 % ssh uTab % ssh user % ssh user1Tab % ssh user1@ % ssh user1@Tab % ssh user1@host % ssh user1@hostTab Completing remote host name host1 host2
なお、users
、hosts
スタイルを設定する。
(ユーザ名のみの場合の補完単語設定)
zstyle ':completion:*' users user1 user2 user3 user4 ...
(ホスト名のみの場合の補完単語設定)
zstyle ':completion:*' hosts host1 host2 host3 host4 ...
4.プロセス・ジョブ補完
kill
コマンドのように、
% jobs [1] suspended sudo -H -s [2] - suspended emacs -nw [3] + suspended $EDITOR .zshrc % ps PID TTY STAT TIME COMMAND 356 ttyp0 Is+ 0:00.07 -zsh 1844 ttyp2 O+ 0:00.00 ps 25114 ttyp2 Ss 0:00.23 -zsh 26716 ttyp2 T 0:00.01 vim .zshrc 28066 ttyp2 T 0:00.52 emacs -nw (emcws) (上記のようなプロセス起動状況と仮定) % kill Tab Completing process ID 356 ttyp0 Is+ 0:00.07 -zsh 25114 ttyp2 Ss+ 0:00.23 -zsh 26411 ttyp2 S+ 0:00.00 -zsh 26716 ttyp2 T 0:00.01 vim .zshrc 27519 ttyp2 O+ 0:00.00 ps 28066 ttyp2 T 0:00.52 emacs -nw (emcws) (psを裏で起動してkillできるPIDが提示される さらに % まで入れるとジョブが補完候補となる) % kill %Tab Completing job %1 -- sudo -H -s %2 -- emacs -nw %3 -- $EDITOR .zshrc
このように事前にps
コマンドなどを打たずとも、
しかし、ps
の結果がたくさん出てきたりすると、kill
でPIDを指定するときに番号を打ち間違ったりする危険性もある。
以下のようにプロセス指定の場所ではメニュー選択モード
に移行するようzstyle
指定を行なうと、
zstyle ':completion:*:processes' menu yes select=2
コマンドラインでもこれを設定してから実際に補完してみよう。
% kill Tab Completing process ID 356 ttyp0 Is+ 0:00.07 -zsh 1084 ttyp2 S+ 0:00.00 -zsh 9911 ttyp2 O+ 0:00.00 ps 25114 ttyp2 Ss+ 0:00.28 -zsh 26716 ttyp2 T 0:00.01 vim .zshrc 28066 ttyp2 T 0:00.52 emacs -nw (emcws) (1行目が反転表示される。 さらにもう一度Tabをタイプすると) % kill Tab Completing process ID 356 ttyp0 Is+ 0:00.07 -zsh 1084 ttyp2 S+ 0:00.00 -zsh 9911 ttyp2 O+ 0:00.00 ps 25114 ttyp2 Ss+ 0:00.28 -zsh 26716 ttyp2 T 0:00.01 vim .zshrc 28066 ttyp2 T 0:00.52 emacs -nw (emcws) (次の候補に進み2行目が反転表示される。 C-n、C-p でも下、上に移動できる。Returnで確定。 確定するとPIDの番号のみがコマンドラインに入る。)
このメニュー選択モードは、
zstyle ':completion:*:(processes|jobs)' menu yes select=2
指定した値の最後の select=2
は、
5.文脈追跡補完
これまで例示した典型的な補完語種別のほかにも、
([1]./configure や make は、その場のファイルを実際に解析して 引数として適切な補完候補を設定) % pwd /home/yuuji/make/apache/apache22/httpd-2.2.13 (Apache2.2 のソースのディレクトリ) % ./configure --Tab zsh: do you wish to see all 272 possibilities (273 lines)? y Completing no arguments Completing option --bindir -- user executables (EPREFIX/bin) --build -- configure for building on BUILD # (guessed) --cache-file -- cache test results in FILE (disabled) --config-cache -- alias for `--cache-file=config.cache' --datadir -- read-only architecture-independent # data (DAT --datarootdir -- read-only arch.-independent data root # (PREFI : : (以下省略)
([2] 処理対象ファイルに応じて補完候補を決定 - tarの場合) % tar jxpf hTab % tar jxpf httpd-2.2.13.tar.bz2 Tab (補完候補取得にアーカイブ内部を調べるのに少し時間がかかる) % tar jxpf httpd-2.2.13.tar.bz2 httpd-2.2.13/ (格納されているファイル名の共通プレフィクス(ディレクトリ)が出る 続けて Tab) % tar jxpf httpd-2.2.13.tar.bz2 httpd-2.2.13/tab Completing file from archive .deps LICENSE acinclude.m4 httpd.spec .gdbinit Makefile.in apachenw.mcp.zip include ABOUT_APACHE Makefile.win build libhttpd.dsp Apache.dsw NOTICE buildconf modules BuildAll.dsp NWGNUmakefile config.layout os BuildBin.dsp README configure server CHANGES README-win32.txt configure.in srclib INSTALL README.platforms docs support InstallBin.dsp ROADMAP emacs-style test LAYOUT VERSIONING httpd.dsp (格納されているファイル名一覧が出る) % tar jxpf httpd-2.2.13.tar.bz2 httpd-2.2.13/INtab % tar jxpf httpd-2.2.13.tar.bz2 httpd-2.2.13/INSTALL
([3] 第1引数にサブコマンドを要求するものの補完) linux# aptitude Tab autoclean -- erase old downloaded package files changelog -- view a package's changelog clean -- erase downloaded package files download -- download the .deb file for a package forbid-version -- forbid aptitude from upgrading to a specific package version forget-new -- forget what packages are "new" : : (以下省略) linux# aptitude INTab linux# aptitude install virTab ("vir"で始まるパッケージのうちインストールしていないものが候補となる) virsh virtualbox virt-goodies virtualbox-2.0 virt-manager virtualbox-2.2 virt-top virtualbox-ose virt-viewer virtualbox-ose-dbg virtaal virtualbox-ose-guest-source virtinst virtualbox-ose-guest-utils virtual-mobile-builder virtualbox-ose-source virtual-mysql-client virtualbox-source virtual-mysql-server viruskiller linux# aptitude remTab linux# aptitude remove linux# aptitude virTab linux# aptitude remove virtualbox-3.0 (aptitude remove の場合は、 "vir"で始まるパッケージのうちインストールしてあるものが候補となる. apt-get、yum や、BSD系の pkg_* なども知的補完が組み込まれている) % svn Tab Completing svn command add commit import mergeinfo proplist switch blame copy info mkdir propset unlock cat delete list move resolve update changelist diff lock propdel resolved checkout export log propedit revert cleanup help merge propget status (Subversionのサブコマンド一覧) % hg Tab add export locate qfinish qrestore showconfig addremove forget log qfold qsave status annotate glog manifest qgoto qselect strip archive grep merge qguard qseries tag backout heads outgoing qheader qtop tags bisect help parents qimport qunapplied tip branch identify paths qinit recover transplant branches import pull qnew remove unbundle bundle incoming push qnext rename update cat init qapplied qpop resolve verify clone kwdemo qclone qprev revert version commit kwexpand qcommit qpush rollback copy kwfiles qdelete qrefresh root diff kwshrink qdiff qrename serve (Mercurialの場合は ~/.hgrc でロードしている拡張モジュールによって サブコマンドが増えるがそれらを自動検出して補完候補としている)
現在普及しているコマンドはzshの補完関数が既に用意されていると思ってよいだろう。どのコマンドの補完に対応しているかをざっと見たい場合は、share/
ディレクトリにあるファイル一覧を眺めるか、compinit
で補完システムを有効化したzshが起動済みであれば、
% echo ${(F)${(uo@)_comps}}|less
($_comps の値を見やすく加工して出力)
もし、
補完方式の選択
主役となる補完キーTabに標準で割り当てられているのはexpand-or-complete
で、
インクリメンタル補完はユーザに確実に正しい単語を選ばせるためには有用だが、
メニュー補完は、menu-expand-or-complete
に変えるとよい。
この場合、Tabの連打で目的候補を通りすぎてしまった場合のために、reverse-menu-complete
も別のキーに割り当てておくとよい。たとえば以下のように設定しておくと、
bindkey '^i' menu-expand-or-complete
bindkey '^[^i' reverse-menu-complete
bindkey '^[i' expand-or-complete
また、expand-or-complete
とmenu-expand-or-complete
の両方を好きなキーに割り当てて使い分けることでより素早くより手軽に補完できる。
独自コマンド補完の作成
zsh標準で知的に補完されないもの、
ここでは、
準備
早速独自の補完関数を作成してみよう。その前に、
もしサンプルの では、 コマンドライン引数で様々なオプションを指定して利用する流儀のコマンドの引数補完を定義してみよう。ここでは架空のコマンドgizの補完定義を試みる。gizコマンドは以下のようなコマンドライン文法を取るものと仮定する。 架空の例なので、 このような形式のコマンドをコマンドライン入力するときに、 あるいは、 のようなカーソル位置で補完キー(Tab)を押したときの挙動を制御したい。 典型的なコマンドラインオプション・ 先に定義例を示すと、 コマンドラインでも上記のとおり入力すれば、 実際にコマンドラインのコマンド位置に その他、 gizの補完の挙動が分かったところで、 このコードの意味は以下のとおり。 この例のように 括弧内には除外したいものを空白区切りで複数書ける。 補完入力時の効果が確認できたら、 手順は以下のとおりに進める。 ここでは仮に、 このディレクトリに置いた関数定義ファイルを自動的に読み込むよう、 これで準備完了。 以上で、 では、 コマンドラインで 定義した関数でうまく補完できることが分かったら、 上述の の第3フィールド その他様々な補完形態を取り扱う関数が多数あり、 zshは標準で準備されている機能が豊富である。そしてそれらは同時にとことんカスタマイズ可能である。ちょっと感じた面倒を見逃さず調整して行くことで最高に気のきく、 もちろんあまりカスタマイズを意識しなくとも、
% zstyle ':completion:*' format '%BCompleting %d%b'
% zstyle ':completion:*' group-name ''
.zshrc
ファイルを利用している場合は既に入っているはずなので以下のようにして確認する。
% zstyle -L
例題
% giz
Usage: giz [ -fnqv ] [ -g grp ] [ -d {foo|bar|baz} ] file
Possible options are as follows:
-f Force overwrite
-n No exec, echo only
-q quiet
-v verbose
-g grp set group to grp
-d kwd set default keyword to kwd, which is one of:
foo, bar, baz
% giz
% giz -
_arguments
関数_arguments
関数である。_arguments
関数で補完できるようになるコマンドライン文法は幅広く非常に有用なのだが、_arguments
関数そのものの利用を完全に把握するためには膨大な事前知識を要する。そのためここでは典型的なコマンドライン文法を持つ、function _giz () {
_arguments -s : \
'-f[Force overwrite]' \
'-n[No exec]' \
'(-v)-q[Quiet]' \
'(-q)-v[Verbose]' \
'-g[Group]:group:_groups' \
'-d[Keyword]:keyword:(foo bar baz)' \
'1:file:_files'
}
_giz
関数が定義できすぐに利用できる。まずは実際に動かしこの関数定義による補完挙動を理解しよう。実際に機能させるには以下のようにcompdef
コマンドで補完定義を補完したいコマンドに割り当てる。
% compdef _giz giz
giz
を入力し、
% giz
(通常引数位置での補完候補)
% giz ESC C-d
Completing file
tetris.html z-1.html z-3.html z-5.html
tetris.png z-2.html z-4.html z-anecdote.html
(ハイフンの直後での補完候補)
% giz -ESC C-d
Completing option
-d -- Keyword
-f -- Force overwrite
-g -- Group
-n -- No exec
-q -- Quiet
-v -- Verbose
(-fオプション入力後の補完候補からは-fが消える)
% giz -fESC C-d
Completing option
-d -- Keyword
-g -- Group
-n -- No exec
-v -- Verbose
-q -- Quiet
(-gオプションを入れた後の補完候補)
% giz -f -g ESC C-d
Completing group
_httpd _sdpd daemon guest named operator staff utmp
_pflogd _timedc dbus kmem nobody polkit sys wheel
_proxy authpf dialer mail nogroup postfix tty wsrc
_rwhod bin games maildrop ntpd sshd users
(システムに存在するグループ一覧が出力される)
_arguments
関数の引数指定_arguments
関数への引数指定を紐解いていこう。 _arguments -s : \
'-f[Force overwrite]' \
'-n[No exec]' \
'(-v)-q[Quiet]' \
'(-q)-v[Verbose]' \
'-d[Keyword]:keyword:(foo bar baz)' \
'-g[Group]:group:_groups' \
'1:file:_files'
1行目:
-s
オプションは、-f
オプションと-n
オプションを同時に指定するのに-fn
と書け、-f
と入力したすぐ後ろの位置で他のオプション文字を補完するようにふるまう。:
は_arguments
関数自身へのオプションがここで終わることを明示する。2行目、
-f[Force overwrite]
の部分は、-f
があり、-n[No Exec]
も同様。4行目、
(-v)-q[Quiet]
の -q[Quiet]
の部分は2、-q
があり、(-v)
はこのオプションの補完を-v
オプションと排他的にすることの指示である。(-v)-q
と書いた場合、
-q
オプションが既にコマンドライン上にある場合、-v
オプションを補完候補から外す6行目:
-d[Keyword]:keyword:(foo bar baz)
の部分はコロンで区切られた3つのフィールドから成っている。最初の -d[Keyword]
は上記同様-d
オプションの補完登録である。第2フィールド以降の指定はそのオプションに対する引数があることを示し、(foo bar baz)
のように括弧内に空白区切りの単語を書いた場合は、
% giz -d ESC C-d
Completing keyword
bar baz foo
7行目:
'-g[Group]:group:_groups'
も6行目と同様の_groups
は補完関数の名前で、_groups
関数はその名前が示すとおり、8行目:
'1:file:_files'
は第1フィールドが自然数で始まっている。これはその位置での通常引数の補完方法を指定する。通常引数とはオプションやオプションへの引数を除いた引数で、
% rsync -a --delete -e 'ssh -4' remote:foo bar
'ssh -4'
までの部分はすべてオプションやオプションへの引数と考え、remote:foo
、bar
となる。_giz
関数の例の'1:file:_files'
の場合は通常の第1引数入力時には、file
' というメッセージを出し、_files
関数で補完入力させることを指示している。補完定義のオートロード化
fpath
に設定する~/script/
に決めたものとして説明する。
% mkdir -p ~/script/zsh
~/.zshrc
のcompinit呼出しより上の部分
に以下の記述を追加する。typeset -U fpath
fpath=($fpath ~/script/zsh)
fpath
はzshが利用する変数で、autoload -U compinit && compinit
」autoload
が関数のオートロードを宣言するものである。これと同じように独自定義したzsh関数もオートロード化できる。先の例に示した_giz
関数定義を含めた、_giz
というファイル名で作成し、~/script/
ディレクトリに置く。_giz
ファイル#compdef giz
function _giz () {
_arguments -s : \
'-f[Force overwrite]' \
'-n[No exec]' \
'(-v)-q[Quiet]' \
'(-q)-v[Verbose]' \
'-g[Group]:group:_groups' \
'-d[Keyword]:keyword:(foo bar baz)' \
'1:file:_files'
}
_giz
関数定義ファイルが、#compdef giz
' は、giz
コマンドの補完時に使われることを示す特殊記法である。
% exec zsh
"giz -"
まで入力した位置で補完が働くか確かめよう。
% giz -ESC C-d
Completing option
-d -- Keyword
-f -- Force overwrite
-g -- Group
-n -- No exec
-q -- Quiet
-v -- Verbose
関数作成の試行錯誤
fpath
変数に登録したディレクトリに定義ファイル~/script/
)
% unfunction _giz; autoload +X _giz
unfunction
は既存の関数定義を抹消する。autoload +X
は、様々な補完アクション
_giz
関数定義の7行目:-g[Group]:group:_groups
_groups
は補完候補としてグループ名を選ぶものであった。このようにzsh標準装備の関数で補完できるものがいくつかある。代表的なものを表に示しておく。
関数 補完される語の種別 _aliases
エイリアス _builtin
内部コマンド _groups
グループ _files
ファイル _functions
関数名 _gnu_
--help
オプションを受け付けるもの_hosts
ホスト名 _parameters
変数名 _precommand
time や eval のように引数にコマンドラインを伴うもの _users
ユーザ名 _user_
USER@HOSTの形式
その先へ