When defining and initializing a variable that holds a complicated
value (such as a keymap with bindings in it), it's best to put the
entire computation of the value into the defvar
, like this:
(defvar my-mode-map (let ((map (make-sparse-keymap))) (define-key map "\C-c\C-a" 'my-command) ... map) docstring)
This method has several benefits. First, if the user quits while
loading the file, the variable is either still uninitialized or
initialized properly, never in-between. If it is still uninitialized,
reloading the file will initialize it properly. Second, reloading the
file once the variable is initialized will not alter it; that is
important if the user has run hooks to alter part of the contents (such
as, to rebind keys). Third, evaluating the defvar
form with
C-M-x will reinitialize the map completely.
Putting so much code in the defvar
form has one disadvantage:
it puts the documentation string far away from the line which names the
variable. Here's a safe way to avoid that:
(defvar my-mode-map nil docstring) (if my-mode-map nil (let ((map (make-sparse-keymap))) (define-key my-mode-map "\C-c\C-a" 'my-command) ... (setq my-mode-map map)))
This has all the same advantages as putting the initialization inside
the defvar
, except that you must type C-M-x twice, once on
each form, if you do want to reinitialize the variable.
But be careful not to write the code like this:
(defvar my-mode-map nil docstring) (if my-mode-map nil (setq my-mode-map (make-sparse-keymap)) (define-key my-mode-map "\C-c\C-a" 'my-command) ...)
This code sets the variable, then alters it, but it does so in more than
one step. If the user quits just after the setq
, that leaves the
variable neither correctly initialized nor void nor nil
. Once
that happens, reloading the file will not initialize the variable; it
will remain incomplete.
Go to the first, previous, next, last section, table of contents.