zshのコマンド補完設定 - 1補完設定に対して1ファイルを用意

zshを"最強のシェル"たらしめている機能を1つ挙げるとしたら、それは補完機能だろう。zshの場合、基本的に1つのコマンド補完に対して1つのファイルを作成することでこれを実現している。同じ補完内容である場合、1つの補完設定ファイルを複数のコマンドに対して適応することもできる。

どのような設定ファイルになっているのか、実際の補完設定ファイルを見るのが手っ取り早い。OSごとにインストール先は異なるだろうが、例えばFreeBSDなら/usr/local/share/zsh/4.3.2/functions/以下にごっそりインストールされている。何でも良いのだが、dateコマンドの補完設定ならばリスト1.1のようになっている。

リスト1.1 dateコマンドに対する補完設定
(zsh 4.3.2の配布物から引用)


#compdef date

local -a args

if _pick_variant gnu="Free Software Foundation" unix --version; then
  args=(
    '-d[output specified date]:time string'
    '-f[output dates specified in file]:file:_files'
    '-I-[iso-8601]:precision:(date hours minutes seconds)'
    '-r[reference]:file:_files'
    '-R[rfc-2822]'
    '-s[set]:time string'
    --
    '*=FILE*:file:_files'
    '*=DATEFILE*:date file:_files'
  )
else
  case "$OSTYPE" in
    solaris*)
      args=( '-a:adjustment' )
    ;;
    freebsd*)
      args=(
        '-n[only set time on current machine]'
        '-d:daylight saving time value'
        '-j[do not try to set date]'
        '-f:parsing format'
        '-r:seconds since epoch'
        '-t:minutes west of GMT'
        '-v:adjustment value'
      )
    ;;
    openbsd*)
      args=(
        '-n[only set time on current machine]'
        '-d:daylight saving time value'
        '-a[gradually skew]'
        '-r:seconds since epoch'
        '-t:minutes west of GMT'
      )
    ;;
  esac
fi
_arguments \
  '-u[display or set time in UTC]' \
  ':format or date' \
  $args[@]

ファイルの名前は「_」から始めることになっている。つまり、リスト1.1の場合は「_date」というファイルが作成されている。FreeBSDなら/usr/local/share/zsh/4.3.2/functions/Completion/Unix/_dateというファイルになっている。

zshのコマンド補完機能は強力だが、この設定が用意されていないコマンドに対してはコマンド補完は実行されない。つまり、そういったコマンドに対しては自分で補完設定を書く必要があるわけだ。

まずはコマンド補完設定ファイルを保存するディレクトリを作成し、設定を~/.zshrcに追加

コマンド補完設定ファイルは、fpath変数に設定されているディレクトリから自動的に読み込まれて処理される仕組みになっている。FreeBSDの場合なら/usr/local/share/zsh/4.3.2/functions/以下のディレクトリがごっそり指定されている。

つまり自分でコマンド補完設定を作成する場合、fpath変数に設定ファイルを保存するディレクトリを追加すればよい。例えばリスト2.1のような設定を~/.zshrcに追加して、あとはコマンド補完設定ファイルを/.zsh/functions/Completion/ディレクトリ以下に作成していけば、zsh起動時に自動的に読み込まれて処理されるわけだ。「autoload -U compinit; compinit」を実行したときに読み込まれるので、こいつを書くのを忘れないよう、注意が必要だ。

リスト2.1 ~/.zsh/functions/Completion/に補完設定ファイルを保存する


fpath=(~/.zsh/functions/Completion ${fpath})
autoload -U compinit
compinit

コマンド補完設定ファイルを保存するディレクトリを~/.zsh/functions/Completion/にしたことに特に意味はない。ベースシステムにインストールされているディレクトリ構造を模倣しているだけなので、このあたりはそれぞれ好みで書き換えるとよいだろう。

daemonコマンドの補完設定ファイルを作成

コマンド補完設定ファイルの記述方法だが、こいつはすでに大量の補完設定ファイルがあるのだから、それを参考にして作成していけばよい。まずは簡単なところから理解していこう。コマンド補完設定の数をこなしていくうちに、いずれはzsherウィザードになってしまうというMっ気たっぷりのウィニングロードのはじまりだ。

まずここでは最初に取り組むコマンドとして「daemon」を選ぶことにする。FreeBSDにはアプリケーションを端末の制御から外してデーモンのように実行するコマンドとしてdaemonコマンドが用意されている。これはなかなか便利なコマンドで、なかなか使える。しかしzshにはdaemonコマンドの補完設定がないので、とても不便である。補完があるのとないのとで、daemonコマンドの使い勝手はかなり変わってしまうので、最初に選ぶコマンドとしては妥当なところだろう。

daemonコマンドの動きを説明しておこう。「acroread &」のようにバックグランドプロセスとしてアプリケーションを起動したとしても、シェルの設定によってはシェルを終了するとバックグランドプロセルも一緒に終了してしまう。シェルの設定を変更すればよいわけだ。しかし、これを「daemon acroread」と実行すればターミナルの制御下にはないため、シェルを終了しても動作し続けることになる。便利なコマンドなので、覚えておくとよいだろう。要するにdaemonコマンドはコマンドを引数とするということだ。

zsh 4.3.2にはdaemonコマンド用の補完設定がないので、「daemon タブキー」だとそのままファイル補完が行われてしまう。ここはコマンドが補完されて欲しいところだ。

プロンプト3.1 設定がないのでファイル補完が行われてしまう


% daemon [タブキーを押すとファイル補完が行われる]

さて、そろそろコマンド補完設定ファイルについて述べよう。リスト3.1のようなファイルを作成して先程設定した~/.zsh/functions/Completion/においておく。~/.zsh/functions/Completion/_daemonというファイルを作成することになるわけだ。

リスト3.1 ~/.zsh/functions/Completion/_daemon - daemonコマンド用の補完設定ファイル


#compdef daemon

_arguments \
  ':command:_command_names -e'

1行目の#から始まる文字列には意味がある。ここはむやみに書き換えてはいけない。「#compdef daemon」でdaemonコマンドに対する補完設定で、あることを指定している。複数のコマンドで補完設定を共有する場合は、ここでさらに空白区切りでコマンド名を追加していけばよい。

この設定を行うと、プロンプト3.2のようにタブキーを押すとコマンドが補完対象になる。プロンプト3.2の場合、コマンド候補が3803もあるので本当に表示するのかどうか確認が求められている。

プロンプト3.2 コマンド補完設定が有効になっているため、目的どおりコマンドが補完対象になっている


% daemon [タブキーを押すとコマンドの補完候補を表示する動作をみせる]
zsh: do you wish to see all 3803 possibilities (1902 lines)?

プロンプト3.3のように途中まで文字列を入力してあれば、その文字列からはじまるコマンドのみが補完候補一覧に表示される。

プロンプト3.3 文字列を入力してあれば、その文字列からはじまるコマンドが補完される


% daemon ac[ここでタブキーを押すと補完候補が表示される]
ac accton aclocal15 acpiconf acpidump activation-client
accept aclocal14 aclocal19 acpidb acroread

これが基本的な作成方法だ。あとはオプションに対する補完設定を追加したりすればよい。それについては、次回説明する。さぁ、強力なコマンド補完の世界へ出かけよう!!