Building fundamental in Emacs: How to customize key binding in vanilla Emacs?
By Anak Wannaphaschaiyong
When I first get into Emacs, I was a vim user before, so I picked up Doom Emacs without experience with vanilla Emacs. Transition has been smooth so far, but because I never has experience with Vanilla Emacs before when I encounter a bug in Doom Emacs. I always have to first figure out if it is Doom Emacs problem or Emacs problems. Because of this, I put out a new blog series to help me build a stronger foundation of Vanilla Emacs.
I started of the series with a topic that irritate me quite often, key binding.
My goal of this blog is as followed
- Understand priority of keymaps
- Understand stand enough to distinguish vanilla Emacs problem from Doom problem.
This is a summarize of Emacs Internal Manual under Emacs topic on chapter 49.3 Key Binding Chapter
.
Keymaps
Most modes have their own key binding which can overwrite your custom keybinding. For this reasons Emacs has reserve small number of keys to create a “safe space” for custom or build-in key binding example of these are ‘C-c <a char>'', ‘F5’ - ‘F9’ keys.
Key sequence and its command function are recorded in Emacs as a data structure called “keymaps”.
Keymap’s value consist of sequence of key binding
and command
where sequence of key binding
can either be a key or a chain of keymaps
, more in “Visualize how a chain of keymaps works” section. In the other word, a keymap is a map between presentation of key sequence
to a command.
Note that since keymaps
is simply just a data structure. A mode can define its own keymaps
such as org-mode-map
etc.
To inspect current keymaps availble in a buffer, you can use C-h b
.
Keymaps accepts values from variety of keys including ‘<Home>’ and mouse.
Prefix
Emacs interprets one keymap at a time, however, a “chain” of keymap commands is also accepted. A “chain” of keymap contains “prefix”. “prefix” is a keymap that map to other keymaps.
Some keymap (not all) have symbols representation, for example, symbol of ‘C-x’ is ‘Control-X-prefix’.
Local Keymaps
local keymaps can have their own prefix key.
It is important to note that global prefix is ALWAYS vulnerable to be overwritten by higher priority keys. Still, there are keys that are reserved for the user. (From what I have read, it is unclear which keys are reserved.)
When local keymap is defined, global keymaps and local keymaps are chain together. To clarify, given that we have “C-x C-z h”, “C-x” is global prefix and “C-z” is local prefix. instead of one “C-x C-z” prefix.
Visualize how a chain of keymaps works?
This is how I think of it visually. It maybe incorrect or imprecise, but, at least, it helps me visualize in my head.
Says, we have a keymap a,b,...,n
that map to foo-command
.
Recall that a keymap is a map between presentation of key sequence
to a command.
When sequence of key is pressed, a chain of keymap will be evaluated as followed.
(key a, keymap b)-> (key b, keymap c) -> ... -> (key n, foo-commands)
Key precedence (keymap lookup order)
local keymaps can be defined in 3 different places.
- Major mode
- Minor mode
- area of text within a buffer.
To be more precise, in term of commands, key precedence (keymap lookup order) is as followed. Emacs look up keymap from top to bottom of the list.
overriding-terminal-local-map
for terminal-specific key bindoverriding-local-map
keymap char property at point
keymaps for the current character. Yasnippet keymaps are in this category.emulation-mode-map-alists
. Apparently, its more multi-mode keymap management. I am not sure what this means, but if i have to guess it is used in modes that have its known key precedence or other complexity that its key binding system brings. Evil mode keymap falls into this category.minor-mode-overriding-map-alise
minor-mode-map-alist
keymap text property at point
current-local-map
current-global-map
Modifying Keybinding
Note that, Emacs always treats ‘C-A’ as ‘C-a’, ‘C-B’ as ‘C-b’, and so forth. This is because, in non-graphical environment, ‘A’ is the same as ‘a.’ To let Emacs know about the difference, we can pass in ‘C-S-a’ where S is <Shift>.
You have to think in the point of view of how computer compile information.
Emacs also accpets uncommon including <Super>, <Hyper>, and <Alt>, these are represented as ‘s-', ‘H-', and ‘A-'. Without these keys on the keyboard, you can still activate the key with ‘C-x @ s’, ‘C-x @ h’, and ‘C-x @ a’, respectively.
There are more valid keys. I only provide few examples.
The goal of modifying a keymap is to either modify sequence of key binding
or command
of a keymap.
Changing Keybinding for current Emacs session.
One can change keybinding for CURRENT Emacs session with the following options.
‘M-x global-set-key <RET> KEY CMD <RET>’
Define KEY globally to run CMD.
‘M-x local-set-key <RET> KEY CMD <RET>’
Define KEY locally (in the major mode now in effect) to run CMD.
‘M-x global-unset-key <RET> KEY’
Make KEY undefined in the global map.
‘M-x local-unset-key <RET> KEY’
Make KEY undefined locally (in the major mode now in effect).
Changing Keybinding permanently.
One can change keybinding permanently using the following commands.
(global-set-key (kbd "C-c y") 'clipboard-yank)
(global-set-key (kbd "C-M-q") 'query-replace)
(global-set-key (kbd "<f5>") 'flyspell-mode)
(global-set-key (kbd "C-<f5>") 'display-line-numbers-mode)
(global-set-key (kbd "C-<right>") 'forward-sentence)
(global-set-key (kbd "<mouse-2>") 'mouse-save-then-kill)
One can also delay local keymap to be evaluated by using hook as followed.
(add-hook 'texinfo-mode-hook
(lambda ()
(define-key texinfo-mode-map "\C-cp"
'backward-paragraph)
(define-key texinfo-mode-map "\C-cn"
'forward-paragraph)))
(define-key texinfo-mode-map "\C-c\C-xx" nil)
Rebinding with Mouse event
valid key includes
[mouse-N] where 1 is the leftmost mouse button.
[drag-mouse-N]
[down-mouse-N]
[double-mouse-N]
keyboard prefix precedes mouse prefix.
Keybinding for clicking on frame has the following format [frame-type mouse-N] frame-type includes
‘mode-line’
The mouse was in the mode line of a window.
‘vertical-line’
The mouse was in the vertical line separating side-by-side windows.
(If you use scroll bars, they appear in place of these vertical
lines.)
‘vertical-scroll-bar’
The mouse was in a vertical scroll bar. (This is the only kind of
scroll bar Emacs currently supports.)
‘menu-bar’
The mouse was in the menu bar.
‘tab-bar’
The mouse was in a tab bar.
‘tab-line’
The mouse was in a tab line.
‘header-line’
The mouse was in a header line.
Disabling Commands
disable Commands silently
(put 'delete-region 'disabled
"It's better to use `kill-region' instead.\n")
disable commands with message
(put 'delete-region 'disabled
"It's better to use `kill-region' instead.\n")
When to define a mode?
You might imagine to simply have one of these modifier keymap function in your init.el and keymaps will be rebind.
Not so fast.
Sometimes, major mode or minor mode may define their keybinding using mode-hook. In this case, keymaps that are defined later can override your init.el configuration. In the cases as this, you have to dig into thier souce code to understand when you want your new keybinding to be evaluated.
Conclusion
This blog summarizes Emacs Internal Manual under Emacs topic on chapter 49.3 Key Binding Chapter
. We have learn that keymap priority based on context from highest to lowest: region in buffer, minor mode, and major mode.
Lastly, I have learned that vanilla Emacs doesn’t exc. I can’t say what exactly.