Skip to main content

49.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 (see 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 (see 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. See Hooks in The Emacs Lisp Reference Manual, 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 (see 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 (see Lambda Expressions in The Emacs Lisp Reference Manual), 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 (see Derived Modes in The Emacs Lisp Reference Manual). For instance, HTML mode is derived from Text mode (see 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.