Help us understand the problem. What is going on with this article?

zshでhook関数を登録する

More than 5 years have passed since last update.

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を読んでください。

mollifier
zsh, vim, vimperator, JavaScript, iOS, .NET に興味があるプログラマ
http://mollifier.hatenablog.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした