zshでhook関数を登録する

  • 58
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

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

結果として、呼び出される順番は次の通り。

  1. zshaddhistory
  2. preexec
  3. コマンドラインに入力した本来のコマンドを実行
  4. chpwd
  5. precmd
  6. periodic

まとめ

ここまで書いた程度のことが分かっていれば、だいたいの場合に対応できると思う。もっと詳しいことを知りたいときはmanを読んでください。

この投稿は zsh Advent Calendar 201415日目の記事です。