6

Emacs' source code contains multiple instances of using fset with a keymap.

For example, in ediff-util.el:

;; Allow ediff-mode-map to be referenced indirectly
(fset 'ediff-mode-map ediff-mode-map)

Or in esh-mode.el:

(fset eshell-command-prefix (make-sparse-keymap))

Or compile.el:

(defvar compilation-button-map
  (let ((map (make-sparse-keymap)))
    (define-key map [mouse-2] 'compile-goto-error)
    (define-key map [follow-link] 'mouse-face)
    (define-key map "\C-m" 'compile-goto-error)
    map)
  "Keymap for compilation-message buttons.")
(fset 'compilation-button-map compilation-button-map)

I've found examples in third-party elisp projects too, such as projectile. I've looked at the creating keymaps documentation but I can't find anything relevant.

These values cannot even be called as functions:

ELISP> (compilation-button-map)
*** Eval error ***  Invalid function: compilation-button-map

What's the purpose of setting the function slot of a symbol with a keymap? Where is it documented?

2 Answers 2

4

There's nothing new or unusual about this. This is how prefix keys work. They are bound to a keymap -- or they are bound to a symbol whose value or whose function definition is a keymap.

The Elisp manual node Prefix Keys tells you this:

The keymap binding of a prefix key is used for looking up the event that follows the prefix key. (It may instead be a symbol whose function definition is a keymap. The effect is the same, but the symbol serves as a name for the prefix key.) Thus, the binding of C-x is the symbol Control-X-prefix, whose function cell holds the keymap for C-x commands. (The same keymap is also the value of [variable] ctl-x-map.)

1

This was news to me. After doing some experiment it looks like it allows you to refer to a keymap by name.

(defun my-test () (interactive) (message "TEST TEST"))
(defvar my-test-mode t)
(defvar my-test-map (make-sparse-keymap))
(define-key my-test-map (kbd "C-c q") 'my-test)
(add-to-list 'minor-mode-map-alist '(my-test-mode . my-test-map))

If you press C-c q, Emacs informs that they binding is undefined.

Add the following:

(fset 'my-test-map my-test-map)

Now, the key binding is working.

My guess is that when the key lookup code find a symbol it looks at its function definition. If that looks like a keymap it will use it.

Note: You don't need to add a key binding by name. The standard way to add a keymap is by value:

(add-to-list 'minor-mode-map-alist (cons 'my-test-mode . my-test-map))

This will include the value of my-test-map. Since all functions binding keys destructively change the keymap, the change will take effect both in my-test-map and minor-mode-map-alist. The only drawback is that if you reinitialize the keymap variable, the old value will still be in minor-mode-map-alist. Effectively, it would appear as though new bindings wouldn't work.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.