Next: , Previous: , Up: Keymaps   [Contents][Index]


23.12 Changing Key Bindings

The way to rebind a key is to change its entry in a keymap. If you change a binding in the global keymap, the change is effective in all buffers (though it has no direct effect in buffers that shadow the global binding with a local one). If you change the current buffer’s local map, that usually affects all buffers using the same major mode. The global-set-key and local-set-key functions are convenient interfaces for these operations (see Key Binding Commands). You can also use define-key, a more general function; then you must explicitly specify the map to change.

When choosing the key sequences for Lisp programs to rebind, please follow the Emacs conventions for use of various keys (see Key Binding Conventions).

define-key (and other functions that are used to rebind keys) understand a number of different syntaxes for the keys.

A vector containing a single string.

This is the preferred way to represent a key sequence. Here’s a couple of examples:

["C-c M-f"]
["S-<home>"]

The syntax is the same as the one used by Emacs when displaying key bindings, for instance in ‘*Help*’ buffers and help texts.

If the syntax isn’t valid, an error will be raised when running define-key, or when byte-compiling code that has these calls.

A vector containing lists of keys.

You can use a list containing modifier names plus one base event (a character or function key name). For example, [(control ?a) (meta b)] is equivalent to C-a M-b and [(hyper control left)] is equivalent to C-H-left.

A string with control and meta characters.

Internally, key sequences are often represented as strings using the special escape sequences for control and meta characters (see String Type), but this representation can also be used by users when rebinding keys. A string like "\M-x" is read as containing a single M-x, "\C-f" is read as containing a single C-f, and "\M-\C-x" and "\C-\M-x" are both read as containing a single C-M-x.

a vector of characters.

This is the other internal representation of key sequences, and supports a fuller range of modifiers than the string representation. One example is ‘[?\C-\H-x home]’, which represents the C-H-x home key sequence. See Character Type.

The functions below signal an error if keymap is not a keymap, or if key is not a string or vector representing a key sequence. You can use event types (symbols) as shorthand for events that are lists. The kbd function (see Key Sequences) is a convenient way to specify the key sequence.

Function: define-key keymap key binding

This function sets the binding for key in keymap. (If key is more than one event long, the change is actually made in another keymap reached from keymap.) The argument binding can be any Lisp object, but only certain types are meaningful. (For a list of meaningful types, see Key Lookup.) The value returned by define-key is binding.

If key is [t], this sets the default binding in keymap. When an event has no binding of its own, the Emacs command loop uses the keymap’s default binding, if there is one.

Every prefix of key must be a prefix key (i.e., bound to a keymap) or undefined; otherwise an error is signaled. If some prefix of key is undefined, then define-key defines it as a prefix key so that the rest of key can be defined as specified.

If there was previously no binding for key in keymap, the new binding is added at the beginning of keymap. The order of bindings in a keymap makes no difference for keyboard input, but it does matter for menu keymaps (see Menu Keymaps).

This example creates a sparse keymap and makes a number of bindings in it:

(setq map (make-sparse-keymap))
    ⇒ (keymap)
(define-key map ["C-f"] 'forward-char)
    ⇒ forward-char
map
    ⇒ (keymap (6 . forward-char))

;; Build sparse submap for C-x and bind f in that.
(define-key map ["C-x f"] 'forward-word)
    ⇒ forward-word
map
⇒ (keymap
    (24 keymap                ; C-x
        (102 . forward-word)) ;      f
    (6 . forward-char))       ; C-f

;; Bind C-p to the ctl-x-map.
(define-key map ["C-p"] ctl-x-map)
;; ctl-x-map
⇒ [nil … find-file … backward-kill-sentence]

;; Bind C-f to foo in the ctl-x-map.
(define-key map ["C-p C-f"] 'foo)
⇒ 'foo
map
⇒ (keymap     ; Note foo in ctl-x-map.
    (16 keymap [nil … foo … backward-kill-sentence])
    (24 keymap
        (102 . forward-word))
    (6 . forward-char))

Note that storing a new binding for C-p C-f actually works by changing an entry in ctl-x-map, and this has the effect of changing the bindings of both C-p C-f and C-x C-f in the default global map.

Function: define-keymap &key options... &rest pairs...

define-key is the general work horse for defining a key in a keymap. When writing modes, however, you frequently have to bind a large number of keys at once, and using define-key on them all can be tedious and error-prone. Instead you can use define-keymap, which creates a keymaps and binds a number of keys. Here’s a very basic example:

(define-keymap
  "n" #'forward-line
  "f" #'previous-line
  ["C-c C-c"] #'quit-window)

This function creates a new sparse keymap, defines the two keystrokes in pairs, and returns the new keymap.

pairs is a list of alternating key bindings and key definitions, as accepted by define-key. In addition the key can be the special symbol :menu, in which case the definition should be a menu definition as accepted by easy-menu-define (see Easy Menu). Here’s a brief example:

(define-keymap :full t
  "g" #'eww-reload
  :menu '("Eww"
          ["Exit" quit-window t]
          ["Reload" eww-reload t]))

A number of keywords can be used before the key/definition pairs to changes features of the new keymap. If the keyword is missing, the default value for the feature is nil. Here’s a list of the available keywords:

:full

If non-nil, create a chartable keymap (as from make-keymap) instead of a sparse keymap (as from make-sparse-keymap (see Creating Keymaps). A sparse keymap is the default.

:parent

If non-nil, this should be a keymap to use as the parent (see Inheritance and Keymaps).

:keymap

If non-nil, this should be a keymap. Instead of creating a new keymap, this keymap is modified instead.

:suppress

If non-nil, the keymap will be suppressed with suppress-keymap (see Changing Key Bindings). If nodigits, treat digits like other chars.

:name

If non-nil, this should be a string to use as the menu for the keymap if you use it as a menu with x-popup-menu (see Pop-Up Menus).

:prefix

If non-nil, this should be a symbol to be used as a prefix command (see Prefix Keys). If this is the case, this symbol is returned by define-keymap instead of the map itself.

Macro: defvar-keymap name &key options... &rest pairs...

By far, the most common thing to do with a keymap is to bind it to a variable. This is what virtually all modes do—a mode called foo almost always has a variable called foo-mode-map.

This macro defines name as a variable, and passes options and pars to define-keymap, and uses the result as the default value for the variable.

options is like the keywords in define-keymap, but adds a :doc keyword that says what the doc string for the name variable should be.

Here’s an example:

(defvar-keymap eww-textarea-map
  :parent text-mode-map
  "\r" #'forward-line
  [?\t] #'shr-next-link)

The function substitute-key-definition scans a keymap for keys that have a certain binding and rebinds them with a different binding. Another feature which is cleaner and can often produce the same results is to remap one command into another (see Remapping Commands).

Function: substitute-key-definition olddef newdef keymap &optional oldmap

This function replaces olddef with newdef for any keys in keymap that were bound to olddef. In other words, olddef is replaced with newdef wherever it appears. The function returns nil.

For example, this redefines C-x C-f, if you do it in an Emacs with standard bindings:

(substitute-key-definition
 'find-file 'find-file-read-only (current-global-map))

If oldmap is non-nil, that changes the behavior of substitute-key-definition: the bindings in oldmap determine which keys to rebind. The rebindings still happen in keymap, not in oldmap. Thus, you can change one map under the control of the bindings in another. For example,

(substitute-key-definition
  'delete-backward-char 'my-funny-delete
  my-map global-map)

puts the special deletion command in my-map for whichever keys are globally bound to the standard deletion command.

Here is an example showing a keymap before and after substitution:

(setq map (list 'keymap
                (cons ?1 olddef-1)
                (cons ?2 olddef-2)
                (cons ?3 olddef-1)))
⇒ (keymap (49 . olddef-1) (50 . olddef-2) (51 . olddef-1))

(substitute-key-definition 'olddef-1 'newdef map)
⇒ nil
map
⇒ (keymap (49 . newdef) (50 . olddef-2) (51 . newdef))
Function: suppress-keymap keymap &optional nodigits

This function changes the contents of the full keymap keymap by remapping self-insert-command to the command undefined (see Remapping Commands). This has the effect of undefining all printing characters, thus making ordinary insertion of text impossible. suppress-keymap returns nil.

If nodigits is nil, then suppress-keymap defines digits to run digit-argument, and - to run negative-argument. Otherwise it makes them undefined like the rest of the printing characters.

The suppress-keymap function does not make it impossible to modify a buffer, as it does not suppress commands such as yank and quoted-insert. To prevent any modification of a buffer, make it read-only (see Read Only Buffers).

Since this function modifies keymap, you would normally use it on a newly created keymap. Operating on an existing keymap that is used for some other purpose is likely to cause trouble; for example, suppressing global-map would make it impossible to use most of Emacs.

This function can be used to initialize the local keymap of a major mode for which insertion of text is not desirable. But usually such a mode should be derived from special-mode (see Basic Major Modes); then its keymap will automatically inherit from special-mode-map, which is already suppressed. Here is how special-mode-map is defined:

(defvar special-mode-map
  (let ((map (make-sparse-keymap)))
    (suppress-keymap map)
    (define-key map "q" 'quit-window)
    …
    map))

Next: , Previous: , Up: Keymaps   [Contents][Index]