Emacs: paired Commands — Efficient Keyboard Interaction Using Hydra
1 Executive Summary
Emacs commands such as
undo-redo come in logical pairs. Such logical pairs (or command
tuples in general) are characterized by the fact that one often
invokes a sequence of these commands repeatedly until the desired
result is attained. Package Hydra defines an elegant means of
combining such command pairs into a single higher-level command that
can be invoked more efficiently from the keyboard.
To my knowledge, the only built-in Emacs command that exhibits a
similar behavior is Emacs'
undo-only allows one to move back through a sequence of
undo-redo in contrast undoes previous undo
In practice, one often moves back through a sequence of operations,
with a few
undo-redo invocations mixed in if one moves back too far.
Emacs convention would suggest that one bind these commands to separate keys, but this has a few disadvantages:
- Binding separate keys to the two commands feels wasteful, especially as unbound keys in Emacs become increasingly precious.
- It's not ergonomic to jump between the two commands in this pair
unless one chooses the key-bindings carefully — as an example,
I used C-x u for
undo-only and _C-x C-ufor
undo-redofor many years. But now, a continuous sequence of undo operations requires too much chording.
1.2 A Hydra Inspired Solution
- Combine the two commands into a higher-level command.
- Bind that command to a single key, in my case C-/ (C-_ on a tty).
- When invoked, the Hydra-defined command does one of the following:
undo-onlyon being called, then continues to read keys.
- Subsequent presses of / invoke command
- Pressing \ invokes
- Any other key quits the Hydra-generated higher-level command.
This is defined as part of Emacspeak's collection of Muggles, as is evident, this is much nicer to your wrists.
(global-set-key (kbd "C-/") (defhydra emacspeak-muggles-undo-only/undo-redo (:body-pre (emacspeak-hydra-body-pre "Undo Smartly") :pre (progn (when hydra-is-helpful (emacspeak-hydra-toggle-talkative)) (emacspeak-hydra-pre)) :post emacspeak-hydra-post) "Undo" ("?" (emacspeak-hydra-self-help "emacspeak-muggles-undo-only/undo-redo")) ("/" undo-only nil) ("\\" undo-redo nil)))
Note that the above can be simplified by dropping the emacspeak-specific clauses when not using Emacspeak.
1.3 Repeatable Yank/Pop From The Hydra Wiki
- C-y invokes the hydra-generated higher-level command.
- Subsequent presses of y is the same of
- Pressing Y invokes
yank-popwith a negative argument.
- Consequence of above, you can grab the last entry on the
kill-ringby pressing Y after invoking the command — would take a lot more keystrokes in vanilla Emacs.
- You can also add smart affordances such as searching the
kill-ringvia interfaces such as
As Emacs gains in functionality, grouping commands into higher-level abstractions, generating a single higher-level command that is bound to a key, and using that invocation context to implement the result of subsequent keypresses is an abstraction that generalizes well.