前: Font Lock Mode, 上: Modes


22.6 フック

フック(hook)とは、既存のプログラムから特定の場面で 呼び出される(1つか一連の)関数を収めた変数です。 Emacsは、カスタマイズのためにフックを用意しています。 ほとんどの場合、フックはファイル.emacsで設定しますが、 Lispプログラムが行ってもかまいません。 標準のフック関数一覧については、See Standard Hooks

Emacsの多くのフックはノーマルフック(normal hook)です。 これらの変数は、引数なしで呼び出される関数のリストを保持しています。 フック名が`-hook'で終っていると、ノーマルフックを意味します。 読者がそれらを単一の方法で使えるように、 可能な限りノーマルフックにするように心掛けています。

各メジャーモード関数は、 その初期化の最終段階でモードフック(mode hook)と呼ばれる ノーマルフックを実行すると期待されます。 これにより、モードがすでに設定したバッファローカルな変数を上書きすることで、 ユーザーがモードのふるまいをカスタマイズしやすくしています。 しかし、フックは別の場面でも使われています。 たとえば、フックsuspend-hookは、 Emacsが自身を一時休止する直前に実行されます。 (see Suspending Emacs)。

ノーマルフックにフック関数を追加する推奨方法は、 add-hook(下記参照)を呼ぶことです。 フック関数は、funcall(see What Is a Function)が 受け付けるならばどんな種類の関数でもかまいません。 ほとんどのノーマルフック変数は最初は空ですが、 add-hookはその扱い方を知っています。

フック変数の名前が`-hook'で終らない場合、 それがアブノーマルフック(abnormal hook)であることを表します。 読者は、そのようなフックの正しい使い方を説明書で調べるべきです。

変数名が`-functions'や`-hooks'で終っていると、 その値は関数のリストですが、 それらの関数を引数ありで呼び出したり、 関数の戻り値をどこかで使うという意味でアブノーマル(異常)なのです。 リストに関数を追加するにはadd-hookを使えますが、 関数を書くときには注意する必要があります。 (これらの変数のうち、実際にはノーマルフックであるものもある。 ノーマルフックには`-hook'を使うという慣習を 確立するまえに命名したものである。)

変数名が`-function'で終っていると、 その値は、関数のリストではなく、1つの関数です。

lisp対話モードで自動詰め込み(auto-fill)モードをオンにするために モードフックを使った例を示します。

     (add-hook 'lisp-interaction-mode-hook 'turn-on-auto-fill)

適当な時期に、Emacsは関数run-hooksを使って 特定のフックを実行します。 この関数は、add-hookで追加されたフック関数を呼び出します。

— 機能: run-hooks &rest hookvar

この関数は複数個のフック変数名を引数にとり、各フックを順に実行する。 各引数hookvarは、フック変数のシンボルであること。 これらの引数は、指定された順に処理される。

フック変数がnil以外の値であると、 その値は、関数か関数のリストである。 値が関数(ラムダ式や関数定義を持つシンボル)であると、それを呼び出す。 値がリストであると、順番にその要素を呼び出す。 フック関数は、引数なしで呼び出される。 現在、フック変数に1つの関数を入れることは廃れかけている。 つねに関数のリストを使うべきである。

例として、emacs-lisp-modeがそのモードフックをどのように 実行するかを示す。

          (run-hooks 'emacs-lisp-mode-hook)
     
— 機能: run-hook-with-args hook &rest args

この関数は、フック関数に引数を渡すアブノーマルフックを実行する方法である。 各フック関数に引数argsを渡して呼び出す。

— 機能: run-hook-with-args-until-failure hook &rest args

この関数は、フック関数に引数を渡すアブノーマルフックを実行するが、 フック関数が失敗するとただちに止める方法である。 フック関数がnilを返すまで、 各フック関数に引数argsを渡して呼び出す。 nilが返ってくるとnilで戻る。 さもなければ、nil以外の値を返す。

— 機能: run-hook-with-args-until-success hook &rest args

この関数は、フック関数に引数を渡すアブノーマルフックを実行するが、 フック関数が成功するとただちに止める方法である。 フック関数がnil以外を返すまで、 各フック関数に引数argsを渡して呼び出す。 nil以外が返ってくると 最後に呼び出したフック関数の戻り値を返す。

— 機能: add-hook hook function &optional append local

この関数はフック変数hookに関数functionを追加する 手軽な方法である。 引数functionは、正しい個数の引数をとる任意の正しいLisp関数であること。 たとえば、

          (add-hook 'text-mode-hook 'my-text-hook-function)
     

は、text-mode-hookというフックに my-text-hook-functionを追加する。

add-hookは、ノーマルフックに加えてアブノーマルフックにも使える。

フック関数は実行順序に依存しないように設計するのが最良である。 実行順序に依存すると『トラブルを呼び込む』ようなものである。 しかし、順序は予測できる。 通常、functionはフックリストの先頭に置かれるので、 (ほかにadd-hookの呼び出しがなければ)最初に実行される。 省略可能な引数appendnil以外であると、 新たなフック関数はフックリストの末尾に置かれ、 最後に実行される。

localnil以外であると、 新たなフック関数をカレントバッファにバッファローカルにすることを意味する。 これを行うまえに、(make-local-variableではなくmake-local-hookを呼んで フック自身をバッファローカルにしておく必要がある。 フック自身がバッファローカルでないと、localの値は意味を持たない。 フック関数はつねにグローバルである。

— 機能: remove-hook hook function &optional local

この関数は、フック変数hookからfunctionを取り除く。

localnil以外であると、 グローバルなフックリストではなくバッファローカルなフックリストから functionを削除することを指定する。 フック変数自身がバッファローカルでないと、localの値は意味を持たない。

— 機能: make-local-hook hook

この関数は、フック変数hookをカレントバッファにバッファローカルにする。 フック変数がバッファローカルであると、 バッファローカルなフック関数とグローバルなフック関数を持つことができ、 run-hooksはそれらすべてを実行する。

この関数は、バッファローカルな値の要素をtにすることで動作する。 これは、バッファローカルな値に加えてフック変数のデフォルト値にある フック関数を使うことを表すフラグである。 run-hooksはこのフラグを理解し、 make-local-hookはすべてのノーマルフックを処理できる。 アブノーマルフックに関しては、 tの意味を理解するように更新したものだけが処理できる。

フック変数に対してmake-local-variableを直接使わないこと。 それだけでは不十分である。