フック(hook)とは、Emacsをカスタマイズするための重要な仕組みです。フックは関数のリストを保持するLisp変数で、これらの関数は、ある定められたタイミングで呼び出されます(これは、フックを実行する(running
the hook))、と呼ばれます)。リストの中の個別の関数は、そのフックのフック関数(hook
functions)と呼ばれます。たとえばフックkill-emacs-hook
は、Emacsを終了する直前に実行されます(Emacsからのexitを参照してください)。
ほとんどのフックはノーマルフック(normal hooks)です。これは、Emacsがフックを実行するとき、フック関数が引数なしで順に呼び出します。わたしたちは、ほとんどのフックをノーマルフックに保つために努力しているので、あなたはこれらのフックを一貫した方法で使用することができます。変数名の最後が‘-hook’の変数は、ノーマルフックです。
多くはありませんが、アブノーマルフック(abnormal
hooks)もあります。アブノーマルフックは、名前の最後が‘-hook’ではなく‘-functions’です(古いコードの中には時代遅れのサフィックス‘-hooks’を使うものもあります)。これらのフックがアブノーマルな理由は、関数が呼び出される方法にあります
—
もしかしたら引数が与えられているかもしれず、ことによると関数が返す値が何かに使用されるかもしれません。たとえばfind-file-not-found-functions
はアブノーマルです。なぜならフック関数のうちの1つが非nil
値を返した場合、残りの関数は呼び出されないからです(ファイルのvisit(訪問)を参照してください)。アブノーマルフック変数のドキュメントには、フック関数がどのように使用されるかの説明があります。
他のLisp変数と同じように、setq
でフック変数をセットすることもできますが、フック(ノーマルとアブノーマルの両方)に関数を追加するための推奨される方法は、以下の例で示されるような、add-hook
を使う方法です。詳細は、Hooks in The Emacs Lisp Reference Manualを参照してください。
ほとんどのメジャーモードは初期化の最終ステップで、1つ以上のモードフック(mode hooks)を実行します。モードフックは個々のモードの振る舞いをカスタマイズするための便利な方法で、常にノーマルフックです。たとえば、以下はTextモードと、Textモードを基礎とする他のモードで、Auto Fillモードをオンにするフックをセットアップする方法です:
(add-hook 'text-mode-hook 'auto-fill-mode)
これは、引数を与えられない場合にマイナーモードを有効にするauto-fill-mode
を呼び出すことにより機能します(マイナーモードを参照してください)。次に、Textモードを基礎とするLaTeXモードではAuto
Fillモードをオンにしたくない場合、以下の行を追加してこれを行なうことができます:
(add-hook 'latex-mode-hook (lambda () (auto-fill-mode -1)))
ここでは、無名関数(anonymous function。Lambda Expressions in The Emacs
Lisp Reference
Manualを参照してください)を構築するために、特別なマクロlambda
を使用しており、auto-fill-mode
に-1
を与えて呼び出すことにより、マイナーモードを無効にしています。LaTeXモードは、text-mode-hook
を実行した後に、latex-mode-hook
モードを実行するので、その結果Auto
Fillモードが無効になります。
以下はもっと複雑な例で、Cコードのインデントをカスタマイズするのにフックを使う方法です:
(setq my-c-style '((c-comment-only-line-offset . 4)
(c-cleanup-list . (scope-operator empty-defun-braces defun-close-semi))))
(add-hook 'c-mode-common-hook (lambda () (c-add-style "my-style" my-c-style t)))
メジャーモードフックは、それを元のモードとして派生された(derived)他のメジャーモードにも適用されます(Derived
Modes in The Emacs Lisp Reference
Manualを参照してください)。たとえばHTMLモード(SGMLモードとHTMLモードを参照してください)はTextモードから派生しており、HTMLモードが有効になるときは、html-mode-hook
を実行する前にtext-mode-hook
が実行されます。これは1つのフックを複数の関連するモードに作用させるための便利な方法を提供します。特に任意のプログラミング言語にたいしてフック関数を適用したい場合は、それをprog-mode-hook
モードに追加します。Progモードは、それを継承する他のメジャーモードと比較すると、ほとんど何も行なわないメジャーモードで、まさにこの目的のために存在します。
実行される順番に依存しないようにフック関数をデザインするのがベストです。実行順への依存はトラブルを招きます。しかし実行順は予測可能です。フック関数はフックに登録された順に実行されます。
何度もadd-hook
を呼び出すことにより、さまざまな異なるバージョンのフック関数を追加した場合、追加されたすべてのバージョンのフック関数がフック変数に残ることを忘れないでください。remove-hook
を呼び出すことにより関数を個別にクリアーするか、(setq
hook-variable nil)
ですべてのフック関数を削除できます。
フック変数がバッファーローカルな場合、グローバル変数のかわりにバッファーローカル変数が使用されます。しかしバッファーローカル変数が要素t
を含む場合は、グローバル変数も同様に実行されます。