zshでは、何か操作を行ったときに呼び出されるhook関数を登録できる。これを使うと、例えば「コマンドを実行するたびにこの関数を実行する」ということができるようになる。もうすでに使ってる人も多いと思うけど、ここでその使い方をまとめておく。
hook関数を登録する
hook関数を登録するには、add-zsh-hook関数を使う。使い方としては、「add-zsh-hook <hook名> <関数名>」という形で呼び出す。「hook名」はどういうときに関数が呼び出されるかというイベント種別を表す文字列で、詳しくは後で説明する。
例
次の例ではprecmdのときにprecmd_function1という関数を呼び出すように登録している。
function precmd_function1() {
# 何か処理
}
autoload -Uz add-zsh-hook
add-zsh-hook precmd precmd_function1
これとは違う登録方法もあるけど、特に理由がなければadd-zsh-hookを使うのが分かりやすいと思う。
hook名とは
「hook名」というのは、どのタイミングで関数が呼ばれるかを指定するための文字列のこと。具体的には次の7種類がある。
hook名 | 呼び出される条件 |
---|---|
chpwd | カレントディレクトリが変更したとき |
periodic | プロンプトを表示するたびに、$PERIOD秒ごと |
precmd | プロンプトを表示する直前 |
preexec | Enterを押してコマンドを実行する直前 |
zshaddhistory | コマンドラインがヒストリに追加される直前 |
zshexit | zshを終了する直前 |
zsh_directory_name | Dynamic named directoriesによるディレクトリ名変換 |
いくつか分かりにくいものがあるので解説する。
periodic
periodicというのはprecmdと似てるけど、precmdがプロンプトを表示するたびに必ず呼び出されるのに対して、periodicは前回実行時から一定時間経過しているときだけ呼び出される。その間隔はPERIOD変数で、秒単位の数値として指定する。
例えば、次の例ではperiodic_function1という関数を5秒間隔で呼び出すように登録している。
PERIOD=5
function periodic_function1() {
echo "periodic $(date)"
}
autoload -Uz add-zsh-hook
add-zsh-hook periodic periodic_function1
これを登録して動作させた様子は以下の通り。
%
periodic 2014年 12月 15日 月曜日 10:51:03 JST
# <= periodicを登録した時点でまずhook関数が呼び出される
%
%
%
#<= Enterを連打しても5秒たつまではなにも表示されない
%
periodic 2014年 12月 15日 月曜日 10:51:09 JST
#<= 前回実行時から5秒以上過ぎてから新しいプロンプトを表示したときにprecmd_function1が呼び出される
これは一定間隔でポーリングしたいときに役に立つ。
zshexit
zshexitは、その名の通りzshが終了したときに呼び出されるhookイベント。対話的に起動しているzshをexit
で終了したときとか、zshのシェルスクリプトが終了したときに呼び出される。終わる直前に後片付けの処理を行いときに役に立つ。
zsh_directory_name
これはややこしいやつなので、今回は解説しない。
どの順番に呼び出されるのか
似たようなhookがいっぱいあるので、それらがどういう順番で呼び出されるのかを確認してみた。まず準備として、次のようにして「chpwd」「periodic」「precmd」「preexec」「zshaddhistory」という5つのhookイベントに関数を登録した。
function chpwd_function1() {
echo "chpwd_function1"
}
function periodic_function1() {
echo "periodic_function1"
}
function precmd_function1() {
echo "precmd_function1"
}
function preexec_function1() {
echo "preexec_function1"
}
function zshaddhistory_function1() {
echo "zshaddhistory_function1"
}
autoload -Uz add-zsh-hook
PERIOD=5
add-zsh-hook chpwd chpwd_function1
add-zsh-hook periodic periodic_function1
add-zsh-hook precmd precmd_function1
add-zsh-hook preexec preexec_function1
add-zsh-hook zshaddhistory zshaddhistory_function1
その後5秒待ってからecho hoge && cd /usr
というコマンドを実行してみた。これで5種類すべてのhook関数が呼び出されるので、その順番を見てみた。
% cd /usr && ls
zshaddhistory_function1
preexec_function1
hoge
chpwd_function1
precmd_function1
periodic_function1
結果として、呼び出される順番は次の通り。
- zshaddhistory
- preexec
- コマンドラインに入力した本来のコマンドを実行
- chpwd
- precmd
- periodic
まとめ
ここまで書いた程度のことが分かっていれば、だいたいの場合に対応できると思う。もっと詳しいことを知りたいときはmanを読んでください。