Emacs: How to Override Minor Mode Keybinding

Buy Xah Emacs Tutorial. Master emacs benefits for life.
, , …,

This page shows you how to override minor mode keys.

To define minor mode keys, you need to modify the key of that mode's keymap, and this needs to happen after that mode finished loading, because otherwise when the mode is activated, its keymap definition may overrides yours.

Here's a simple example:

;; modify isearch's keymap
(define-key isearch-mode-map (kbd "<next>") 'isearch-repeat-forward) ; page down key
(define-key isearch-mode-map (kbd "<prior>") 'isearch-repeat-backward) ; page up key

For some minor modes, you need to load it first, example:

(progn
  ;; modify dired keys
  (require 'dired )
  (define-key dired-mode-map (kbd "o") 'other-window)
  (define-key dired-mode-map (kbd "1") 'xah-previous-user-buffer)
  (define-key dired-mode-map (kbd "2") 'delete-window)
  (define-key dired-mode-map (kbd "3") 'delete-other-windows)
  (define-key dired-mode-map (kbd "4") 'split-window-vertically)
  (define-key dired-mode-map (kbd "C-o") 'find-file))

General Steps

  1. Call describe-function, then type the mode activation command name, then click on the link to open its elisp source code file.
  2. in the mode's source code, search for “-map” to find it's keymap name. Let's say it's “xyz-map”.
  3. in the mode's source code, go all the way to bottom to find (provide 'xyz) if it exists. The “'xyz” would be the symbol for the mode.
  4. In your emacs init file, start with (require 'xyz) (if the mode has a symbol), then (define-key keymap name (kbd "key") 'command name)

Note that not all modes defines a keymap in its source file. Some inherit from other modes, some uses keymaps from other elisp file that are not modes, some doesn't have a keymap.

When you redefine some keys in a mode's keymap, be sure to make keybinding for the displaced commands if you still want a key for them.

For example, in “shell-mode”, i wanted “M-p” to do something. The “M-p” is previous-history-element. I think that command is useful enough to have a hotkey. So, i defined some other key for that. (You can call describe-key command to find out a key's binding while in that mode.)

Examples

Modify Isearch Keys

By default, 【Ctrl+s】 will do a interactive search. Pressing that again will find the next match. Suppose you prefer to have 【Alt+s】 instead, so in your emacs init file you defined:

(global-set-key (kbd "M-s") 'isearch-forward)
(global-set-key (kbd "M-S") 'isearch-backward)

You want to use “M-s” to repeat the search. However, once you are in the isearch prompt, technically it is a minor mode called isearch-mode. In isearch-mode, “C-s” is defined to run isearch-repeat-forward. You want “M-s” to run isearch-repeat-forward. Here's the code to reclaim it:

(define-key isearch-mode-map (kbd "M-s") 'isearch-repeat-forward)
(define-key isearch-mode-map (kbd "M-S") 'isearch-repeat-backward)

Note: insearch is loaded by emacs by default. So, there's no need for (require 'package symbol)

Modify Shell Keys

shell and shell-commandAlt+!】 have many special keys. Suppose you want to change them. They both use a keymap named comint-mode-map. The following is a example of redefining some of its keys.

(progn
  ;; "change keybindings for shell related modes."
   (define-key comint-mode-map (kbd "M-p") 'recenter) ; was comint-previous-input
   (define-key comint-mode-map (kbd "M-n") 'nil) ; was comint-next-input
   (define-key comint-mode-map (kbd "M-r") 'kill-word) ; was comint-previous-matching-input
   (define-key comint-mode-map (kbd "M-s") 'other-window) ; was comint-next-matching-input

   ;; rebind displaced commands that i still want a key
   (define-key comint-mode-map (kbd "<f11>") 'comint-previous-input)
   (define-key comint-mode-map (kbd "<f12>") 'comint-next-input)
   (define-key comint-mode-map (kbd "S-<f11>") 'comint-previous-matching-input)
   (define-key comint-mode-map (kbd "S-<f12>") 'comint-next-matching-input)
)

Modify Minibuffer Keys

The minibuffer is where emacs does prompts. It defines the following keys:

Minibuffer's Keybinding
KeyCommand
C-jexit-minibuffer
<RET>exit-minibuffer
C-gabort-recursive-edit
M-nnext-history-element
<down>next-history-element
M-pprevious-history-element
<up>previous-history-element
M-snext-matching-history-element
M-rprevious-matching-history-element

Here's a example of how to redefine its keybinding:

;; reclaim some bindings used in minibuffer for ergoemacs bindings for QWERTY
(define-key minibuffer-local-map (kbd "M-p") 'recenter) ; was previous-history-element. Use ↑ key or f11.
(define-key minibuffer-local-map (kbd "M-n") 'nil) ; was next-history-element. Use ↓ key or f12.

(define-key minibuffer-local-map (kbd "M-r") 'kill-word) ; was previous-matching-history-element.
(define-key minibuffer-local-map (kbd "M-s") 'other-window) ; was nest-matching-history-element

;; add back some bindings for commands whose binding we displaced
(define-key minibuffer-local-map (kbd "<f11>") 'previous-history-element)
(define-key minibuffer-local-map (kbd "<f12>") 'next-history-element)
(define-key minibuffer-local-map (kbd "S-<f11>") 'previous-matching-history-element)
(define-key minibuffer-local-map (kbd "S-<f12>") 'next-matching-history-element)

(info "(elisp) Text from Minibuffer")

Like it?
Buy Xah Emacs Tutorial
or share
blog comments powered by Disqus