emacs: Hooks
51.2.2 Hooks
------------
“Hooks” are an important mechanism for customizing Emacs. A hook is a
Lisp variable which holds a list of functions, to be called on some
well-defined occasion. (This is called “running the hook”.) The
individual functions in the list are called the “hook functions” of the
hook. For example, the hook ‘kill-emacs-hook’ runs just before exiting
Emacs (Exiting).
Most hooks are “normal hooks”. This means that when Emacs runs the
hook, it calls each hook function in turn, with no arguments. We have
made an effort to keep most hooks normal, so that you can use them in a
uniform way. Every variable whose name ends in ‘-hook’ is a normal
hook.
A few hooks are “abnormal hooks”. Their names end in ‘-functions’,
instead of ‘-hook’ (some old code may also use the deprecated suffix
‘-hooks’). What makes these hooks abnormal is the way its functions are
called—perhaps they are given arguments, or perhaps the values they
return are used in some way. For example,
‘find-file-not-found-functions’ is abnormal because as soon as one hook
function returns a non-‘nil’ value, the rest are not called at all
(Visiting). The documentation of each abnormal hook variable
explains how its functions are used.
You can set a hook variable with ‘setq’ like any other Lisp variable,
but the recommended way to add a function to a hook (either normal or
abnormal) is to use ‘add-hook’, as shown by the following examples.
(elisp)Hooks, for details.
Most major modes run one or more “mode hooks” as the last step of
initialization. Mode hooks are a convenient way to customize the
behavior of individual modes; they are always normal. For example,
here’s how to set up a hook to turn on Auto Fill mode in Text mode and
other modes based on Text mode:
(add-hook 'text-mode-hook 'auto-fill-mode)
This works by calling ‘auto-fill-mode’, which enables the minor mode
when no argument is supplied (Minor Modes). Next, suppose you
don’t want Auto Fill mode turned on in LaTeX mode, which is one of the
modes based on Text mode. You can do this with the following additional
line:
(add-hook 'latex-mode-hook (lambda () (auto-fill-mode -1)))
Here we have used the special macro ‘lambda’ to construct an anonymous
function ((elisp)Lambda Expressions), which calls
‘auto-fill-mode’ with an argument of ‘-1’ to disable the minor mode.
Because LaTeX mode runs ‘latex-mode-hook’ after running
‘text-mode-hook’, the result leaves Auto Fill mode disabled.
Here is a more complex example, showing how to use a hook to
customize the indentation of C code:
(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)))
Major mode hooks also apply to other major modes “derived” from the
original mode ((elisp)Derived Modes). For instance, HTML mode
is derived from Text mode (HTML Mode); when HTML mode is
enabled, it runs ‘text-mode-hook’ before running ‘html-mode-hook’. This
provides a convenient way to use a single hook to affect several related
modes. In particular, if you want to apply a hook function to any
programming language mode, add it to ‘prog-mode-hook’; Prog mode is a
major mode that does little else than to let other major modes inherit
from it, exactly for this purpose.
It is best to design your hook functions so that the order in which
they are executed does not matter. Any dependence on the order is
asking for trouble. However, the order is predictable: the hook
functions are executed in the order they appear in the hook.
If you play with adding various different versions of a hook function
by calling ‘add-hook’ over and over, remember that all the versions you
added will remain in the hook variable together. You can clear out
individual functions by calling ‘remove-hook’, or do ‘(setq
HOOK-VARIABLE nil)’ to remove everything.
If the hook variable is buffer-local, the buffer-local variable will
be used instead of the global variable. However, if the buffer-local
variable contains the element ‘t’, the global hook variable will be run
as well.