This page shows you how to reclaim keybinding when some major or minor mode override your global keybinding. If you don't know how to define global keybinding, see: Emacs: How to Define Keys.
When you have made some personal keyboard shortcuts in emacs using
global-set-key, both major modes and minor modes will override those
if it uses the same keys. This is because major mode and minor
mode's keymaps have priority over global keymaps.
To reclaim your binding, you will have to redefine 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 simply overrides yours.
Well written major modes will run hook at the end. So, you can use a hook to define your keybinding. Minor modes usually do not have hooks. In that case, you can call (require ‹minor mode feature symbol›) first, then define your keybinding.
The exact steps may not be the same for every mode, but the principle is the same. The following shows several examples.
⓪ Start with this template in your init file:
(defun MY-XYZ-HOOK () "My hook for `XYZ-MODE-HOOK'." (local-set-key (kbd "KEY1") 'COMMAND1) (local-set-key (kbd "KEY2") 'COMMAND2) … ) (add-hook 'XYZ-MODE-HOOK 'MY-XYZ-HOOK)
① Call describe-function, then the mode activation command name (⁖ html-mode), then click on the link to open its elisp source code file.
② In the elisp source code, search for run-mode-hooks or “-hook”. You'll find the right hook name to add. (most major mode shoud have a hook)
③ in the mode's source code, search for “-mode-map” or “-map” to look at the keys it defines.
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
bindings for the displaced commands if those commands are important to
you. 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.)
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:
(add-hook 'isearch-mode-hook (lambda () (define-key isearch-mode-map (kbd "M-s") 'isearch-repeat-forward) (define-key isearch-mode-map (kbd "M-S") 'isearch-repeat-backward) ) )
shell and shell-command 【Alt+!】 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.
;; reclaim some keybinding used by shell mode and shell-command. shell and associated modes/commands use keys in “comint-mode-map”. (add-hook 'comint-mode-hook (lambda () (define-key comint-mode-map (kbd "M-p") 'recenter) ; was comint-previous-input. Use Ctrl+↑ or f11 (define-key comint-mode-map (kbd "M-n") 'nil) ; was comint-next-input. Use Ctrl+↓ or f12 (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) ))
The minibuffer is where emacs does prompts. It is technically a minor mode. It defines the following keybinding:
| Key | Command |
|---|---|
C-j | exit-minibuffer |
<RET> | exit-minibuffer |
C-g | abort-recursive-edit |
M-n | next-history-element |
<down> | next-history-element |
M-p | previous-history-element |
<up> | previous-history-element |
M-s | next-matching-history-element |
M-r | previous-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")