Emacs New Keymap Functions

February 2, 2024

Emacs 29 comes with new functions for defining and manipulating keystrokes.

These all take the syntax defined by key-valid-p, which is basically the same syntax as the one accepted by the kbd macro. None of the older functions have been deprecated or altered, but they are now de-emphasized in the documentation, and we encourage Lisp programs to switch to these new functions.

New function key-valid-p predicate does a stricter check of the syntax. New function key-parse is like kbd, but only returns vectors instead of a mix of vectors and strings.

New function define-keymap allows defining a number of keystrokes with one form. New macro defvar-keymap allows defining keymap variables more conveniently, can specify repeat-mode behavior for the keymap.

I have already redefine my own keybinds with these new functions.

Protesilaos Stavrou posted a video on nested key maps. The video shows how to define a prefix key in Emacs 29 using built-in functionality. The idea is to organise our keys in an efficient way. Using this method, we can have nested key maps as well, meaning that the prefix key can have access to the contents of another map which holds more key bindings. The video also shows us how to describe the keymaps with which-key.

Here is the example, we can have C-z as a prefix, C-z b as a nested key maps for buffer-related commands, and C-z f for file-related commands.

;; Read this to learn about key binding conventions so that you know
;; which keys are safe for users:
;;
;;     (info "(elisp) Key Binding Conventions")

;; Sample of a generic command with a corresponding key binding
(defun test-command ()
  (interactive)
  (message "Hello world"))

(keymap-set global-map "C-z" #'test-command)

;; Define key maps that will then be added to the prefix map
(defvar-keymap test-prefix-buffer-map
  :doc "My prefix key map for buffers."
  "s" #'save-buffer
  "w" #'write-file
  "p" #'previous-buffer
  "n" #'next-buffer)

(defvar-keymap test-prefix-mode-map
  :doc "My prefix key map for minor modes."
  "l" #'display-line-numbers-mode
  "h" #'hl-line-mode)

;; Define a key map with commands and nested key maps
(defvar-keymap test-prefix-map
  :doc "My prefix key map."
  "b" test-prefix-buffer-map
  "m" test-prefix-mode-map
  "f" #'find-file
  "d" #'dired)

;; Define how the nested keymaps are labelled in `which-key-mode'.
(which-key-add-keymap-based-replacements test-prefix-map
  "b" `("Buffer" . ,test-prefix-buffer-map)
  "m" `("Testing" . ,test-prefix-mode-map))

;; Bind the prefix key map to a key.  Notice the absence of a quote for
;; the map's symbol.
(keymap-set global-map "C-z" test-prefix-map)

Top