Colorful Hydras
02 Feb 2015This post advertises the release of hydra.el 0.5.0. The package was introduced in an earlier post and received some positive feedback. Currently, it's available in both GNU ELPA (slightly behind) and MELPA (always current).
The newfound utility
As I originally released the Hydra, I was asked if it was similar to this approach described on Endless Parentheses. I said that it's not, since Hydra commands are meant to be repeatable instead of being called just once.
Now, after I've designated the repeatable heads with red color and the one-off heads with blue color, Hydra can reproduce the mentioned approach. Here's how it looks like:
(global-set-key
(kbd "C-c C-v")
(defhydra hydra-toggle (:color blue)
"toggle"
("a" abbrev-mode "abbrev")
("d" toggle-debug-on-error "debug")
("f" auto-fill-mode "fill")
("t" toggle-truncate-lines "truncate")
("w" whitespace-mode "whitespace")
("q" nil "cancel")))
And this is what I see in the echo area after pressing C-c C-v:
At this point:
- q will cancel without doing anything. I think it's more
convenient than doing the equivalent C-g with the
global-set-key
approach. - a, d, f, t, and a will call the appropriate function.
The advantage of blue Hydra heads over
global-set-key
is that you immediately get the hint: this can be useful for rarely used commands. - as with the old red Hydra heads, pressing anything other than
a, d, f, t, a,
or q will vanquish the Hydra and call the key binding
that you just pressed. This is different from the
global-set-key
approach, which would e.g. error to your C-c C-v C-n with"C-c C-v C-n is undefined"
, unlike the Hydra, which would call C-n (next-line
).
The full defhydra
syntax
Note that defhydra
looks intentionally like a defun
, so that it's
easier to remember how it works.
Here's a more verbose Hydra that's largely equivalent to the one above:
(defhydra hydra-toggle (global-map "C-c" :color red)
"toggle"
("a" abbrev-mode "abbrev" :color blue)
("d" toggle-debug-on-error "debug" :color blue)
("f" auto-fill-mode "fill" :color blue)
("t" toggle-truncate-lines "truncate" :color blue)
("w" whitespace-mode "whitespace" :color blue)
("v" recenter-top-bottom "recenter" :color red)
("q" nil "cancel" :color blue))
(global-set-key (kbd "C-c C-v") 'hydra-toggle/body)
First argument: Hydra name
This argument decides the prefix to all the functions that will be generated. In this case the following functions will be generated:
hydra-toggle/abbrev-mode
hydra-toggle/toggle-debug-on-error
hydra-toggle/auto-fill-mode
hydra-toggle/toggle-truncate-lines
hydra-toggle/whitespace-mode
hydra-toggle/recenter-top-bottom
hydra-toggle/nil
hydra-toggle/body
The final function calls the Hydra's body, displaying the hint in the echo area and setting
the transient map. It's the return result of defhydra
, that's why it was possible to pass it
to global-set-key
in the first example.
Second argument: Hydra body
The Hydra body consists of:
- a map used for binding, like
global-map
orc++-mode-map
orprojectile-mode-map
- the body prefix: it's a string passable to
kbd
that will be used in conjunction with heads' prefixes to bind the functions - an optional plist, which currently recognizes only the
:color
key, which in turn can be either red (the old behavior) or blue.
It's possible to omit the map and the body prefix simultaneously (it
doesn't make sense to omit one but not the other), or just pass ()
if you want to get a red Hydra body that you can bind yourself.
Third argument: Hydra hint
This string will be used in the echo area to distinguish the current
Hydra. This is optional, it case you don't provide it, it will default
to "hydra"
.
Fourth argument: Hydra heads
Each Hydra head is a list of:
- the key extension
- the function
- optional hint
- optional plist.
Again, the plist recognizes only :color
currently. The color is inherited from the body, if
you don't specify it. In turn, the body color is red if you don't specify it.
The code above:
- binds C-c a, C-c d etc with the usual
global-set-key
approach. - binds C-c C-v a, C-c C-v d with the new approach, which shows you the hint right after C-c C-v and allows you to cancel easier.
- binds C-c v to be repeatable, i.e. you can press C-c v v v. Same with C-c C-v v v v.
Some more ideas for blue Hydras
Here's one for some helm
-related functions, don't ask how
projectile-find-file
ended up here:
(global-set-key
"κ"
(defhydra hydra-helm (:color blue)
"helm"
("f" projectile-find-file "file")
("w" helm-org-wiki "wiki")
("r" helm-recentf "recent")
("s" helm-swoop "swoop")
("q" nil "quit")))
Here's one more for gnus
; I'm just getting the hang of it, so some hints are useful:
(defhydra hydra-gnus-reply (:color blue)
"reply"
("o" gnus-summary-reply-with-original "one")
("O" gnus-summary-reply)
("a" gnus-summary-wide-reply-with-original "all")
("A" gnus-summary-wide-reply)
("u" gnus-summary-very-wide-reply-with-original "universe")
("U" gnus-summary-very-wide-reply)
("q" nil "quit"))
(define-key gnus-summary-mode-map "r" 'hydra-gnus-reply/body)
I omit the hint for the commands that do the same as the previous one, just without citing.
Outro
I hope that you enjoy the update and let me know when you invent some efficient blue or red-and-blue Hydras. Happy hacking!