Emacs is well-known for its arcane keybindings, often involving three or more keypresses. For example, C-x z is bound to the repeat command which – well – repeats the last command. However, there is another feature of Emacs which uses the word “repeat” and is very useful. (Actually, there’s even more of them.)
The Repeat mode allows some multi-key commands to be executed again by pressing only the last key in their keybinding sequence. For example, after you say M-x repeat-mode and press C-x o, you can press o more times to walk through the open windows (or O to walk back). Making your current window wider, narrower, taller and shorter can be achieved by pressing C-x } and then any combination of }, {, ^, and v, making resizing windows a much more pleasant experience. Undoing more than one change becomes C-x u u ... u, etc.
That is not the whole story, though. The real fun begins when you make your own commands work like that. For example, I use git-gutter and I have the git-gutter:next-hunk and git-gutter:previous-hunk bound to C-x v ] and C-x v [. I’d love to be able to press C-x v ] ] ] to move forward by three hunks (and yes, I know I can say C-2 C-x v ], but it’s not the same – I might not know in advance how many hunks I want to move, and just pressing ] repeatedly lets me discover that more easily).
So, here is what I can do.
(bind-key "C-x v ]" #'git-gutter:next-hunk) (bind-key "C-x v [" #'git-gutter:previous-hunk) (defvar-keymap vc-dir-repeat-map :doc "Keymap to repeat `vc-dir' commands. Used in `repeat-mode'." :repeat t "]" #'git-gutter:next-hunk "[" #'git-gutter:previous-hunk) (put 'git-gutter:next-hunk 'repeat-map 'vc-dir-repeat-map) (put 'git-gutter:previous-hunk 'repeat-map 'vc-dir-repeat-map)
This way, when I activate Repeat mode, I can press C-x v and then move around my hunks with brackets. Very useful!
That, however, is not the end of the story. There is one more Emacs feature which gives me a similar experience without Repeat mode – the so-called transient keymaps (not related to the Transient library). They are a low-level feature used internally by Repeat mode, and they don’t require it to work.
(bind-key "C-x v ]" #'mbork-git-gutter:next-hunk) (bind-key "C-x v [" #'mbork-git-gutter:previous-hunk) (defvar-keymap vc-dir-repeat-map :doc "Keymap to repeat `vc-dir' commands. Used in `repeat-mode'." :repeat t "]" #'mbork-git-gutter:next-hunk "[" #'mbork-git-gutter:previous-hunk) (defun mbork-git-gutter:next-hunk (arg) "Move to next diff hunk, and allow this command to be repeated." (interactive "p") (set-transient-map vc-dir-repeat-map) (git-gutter:next-hunk arg)) (defun mbork-git-gutter:previous-hunk (arg) "Move to previous diff hunk, and allow this command to be repeated." (interactive "p") (set-transient-map vc-dir-repeat-map) (git-gutter:previous-hunk arg))
There’s more to transient keymaps than this simple example – consult the Elisp reference and examples of usage in Emacs sources for more. In the meantime, see you next week!