]> code.delx.au - gnu-emacs-elpa/blob - packages/hydra/README.md
Merge commit '7ae5f6528df5073eb2b42ec45a21af73bc7047c0'
[gnu-emacs-elpa] / packages / hydra / README.md
1 [![Build Status](https://travis-ci.org/abo-abo/hydra.svg?branch=master)](https://travis-ci.org/abo-abo/hydra)
2
3 This is a package for GNU Emacs that can be used to tie related commands into a family of short
4 bindings with a common prefix - a Hydra.
5
6 ![hydra](http://oremacs.com/download/Hydra.jpg)
7
8 Once you summon the Hydra through the prefixed binding (the body + any one head), all heads can be
9 called in succession with only a short extension.
10
11 The Hydra is vanquished once Hercules, any binding that isn't the Hydra's head, arrives. Note that
12 Hercules, besides vanquishing the Hydra, will still serve his original purpose, calling his proper
13 command. This makes the Hydra very seamless, it's like a minor mode that disables itself
14 auto-magically.
15
16 <!-- markdown-toc start - Don't edit this section. Run M-x markdown-toc/generate-toc again -->
17 **Table of Contents**
18
19 - [Sample Hydras](#sample-hydras)
20 - [The one with the least amount of code](#the-one-with-the-least-amount-of-code)
21 - [The impressive-looking one](#the-impressive-looking-one)
22 - [Community wiki](#community-wiki)
23 - [The Rules of Hydra-tics](#the-rules-of-hydra-tics)
24 - [`hydra-awesome`](#hydra-awesome)
25 - [`awesome-map` and `awesome-binding`](#awesome-map-and-awesome-binding)
26 - [`awesome-plist`](#awesome-plist)
27 - [`:pre` and `:post`](#pre-and-post)
28 - [`:exit`](#exit)
29 - [`:foreign-keys`](#foreign-keys)
30 - [`:color`](#color)
31 - [`:timeout`](#timeout)
32 - [`:hint`](#hint)
33 - [`:bind`](#bind)
34 - [`awesome-docstring`](#awesome-docstring)
35 - [`awesome-head-1`](#awesome-head-1)
36 - [`head-binding`](#head-binding)
37 - [`head-command`](#head-command)
38 - [`head-hint`](#head-hint)
39 - [`head-plist`](#head-plist)
40
41 <!-- markdown-toc end -->
42
43 # Sample Hydras
44
45 ## The one with the least amount of code
46
47 ```cl
48 (defhydra hydra-zoom (global-map "<f2>")
49 "zoom"
50 ("g" text-scale-increase "in")
51 ("l" text-scale-decrease "out"))
52 ```
53
54 With this simple code, you can:
55
56 - Start zooming in with <kbd>&lt;f2&gt; g</kbd>.
57 - Continue to zoom in with <kbd>g</kbd>.
58 - Or zoom out with <kbd>l</kbd>.
59 - Zoom in five times at once with <kbd>5g</kbd>.
60 - Stop zooming with *any* key that isn't <kbd>g</kbd> or <kbd>l</kbd>.
61
62 For any Hydra:
63
64 - `digit-argument` can be called with <kbd>0</kbd>-<kbd>9</kbd>.
65 - `negative-argument` can be called with <kbd>-</kbd>.
66 - `universal-argument` can be called with <kbd>C-u</kbd>.
67
68 ## The impressive-looking one
69
70 Here's the result of pressing <kbd>.</kbd> in the good-old Buffer menu:
71
72 ![hydra-buffer-menu](http://oremacs.com/download/hydra-buffer-menu.png)
73
74 The code is large but very simple:
75
76 ```cl
77 (defhydra hydra-buffer-menu (:color pink
78 :hint nil)
79 "
80 ^Mark^ ^Unmark^ ^Actions^ ^Search
81 ^^^^^^^^-----------------------------------------------------------------
82 _m_: mark _u_: unmark _x_: execute _R_: re-isearch
83 _s_: save _U_: unmark up _b_: bury _I_: isearch
84 _d_: delete ^ ^ _g_: refresh _O_: multi-occur
85 _D_: delete up ^ ^ _T_: files only: % -28`Buffer-menu-files-only
86 _~_: modified
87 "
88 ("m" Buffer-menu-mark)
89 ("u" Buffer-menu-unmark)
90 ("U" Buffer-menu-backup-unmark)
91 ("d" Buffer-menu-delete)
92 ("D" Buffer-menu-delete-backwards)
93 ("s" Buffer-menu-save)
94 ("~" Buffer-menu-not-modified)
95 ("x" Buffer-menu-execute)
96 ("b" Buffer-menu-bury)
97 ("g" revert-buffer)
98 ("T" Buffer-menu-toggle-files-only)
99 ("O" Buffer-menu-multi-occur :color blue)
100 ("I" Buffer-menu-isearch-buffers :color blue)
101 ("R" Buffer-menu-isearch-buffers-regexp :color blue)
102 ("c" nil "cancel")
103 ("v" Buffer-menu-select "select" :color blue)
104 ("o" Buffer-menu-other-window "other-window" :color blue)
105 ("q" quit-window "quit" :color blue))
106
107 (define-key Buffer-menu-mode-map "." 'hydra-buffer-menu/body)
108 ```
109
110 Looking at the code, you can see `hydra-buffer-menu` as sort of a namespace construct that wraps
111 each function that it's given in code that shows that hint and makes it easy to call the related
112 functions. One additional function is created and returned as the result of `defhydra` -
113 `hydra-buffer-menu/body`. This function does nothing except setting up the hint and the keymap, and
114 is usually the entry point to complex hydras.
115
116 To write your own hydras, you can:
117
118 - Either modify an existing hydra to do what you want to do.
119 - Or read [the rules](#the-rules-of-hydra-tics),
120 [the examples](https://github.com/abo-abo/hydra/blob/master/hydra-examples.el),
121 the docstrings and comments in the source.
122
123 # Community wiki
124
125 You can find some user created hydras and more documentation in the project's
126 [community wiki](https://github.com/abo-abo/hydra/wiki/). Feel free to add your
127 own or edit the existing ones.
128
129 # The Rules of Hydra-tics
130
131 Each hydra (take `awesome` as a prefix to make it more specific) looks like this:
132
133 ```
134 (defhydra hydra-awesome (awesome-map awesome-binding awesome-plist)
135 awesome-docstring
136 awesome-head-1
137 awesome-head-2
138 awesome-head-3
139 ...)
140 ```
141
142 ## `hydra-awesome`
143
144 Each hydra needs a name, and this one is named `hydra-awesome`. You can name your hydras as you wish,
145 but I prefer to start each one with `hydra-`, because it acts as an additional namespace layer, for example:
146 `hydra-zoom`, `hydra-helm`, `hydra-apropos` etc.
147
148 If you name your hydra `hydra-awesome`, the return result of `defhydra` will be `hydra-awesome/body`.
149
150 Here's what `hydra-zoom/body` looks like, if you're interested:
151
152 ```cl
153 (defun hydra-zoom/body nil
154 "Create a hydra with a \"<f2>\" body and the heads:
155
156 \"g\": `text-scale-increase',
157 \"l\": `text-scale-decrease'
158
159 The body can be accessed via `hydra-zoom/body'."
160 (interactive)
161 (hydra-disable)
162 (catch (quote hydra-disable)
163 (when hydra-is-helpful (hydra-zoom/hint))
164 (setq hydra-last
165 (hydra-set-transient-map
166 (setq hydra-curr-map
167 (quote
168 (keymap (7 . hydra-keyboard-quit)
169 (108 . hydra-zoom/text-scale-decrease)
170 (103 . hydra-zoom/text-scale-increase)
171 (kp-subtract . hydra--negative-argument)
172 (kp-9 . hydra--digit-argument)
173 (kp-8 . hydra--digit-argument)
174 (kp-7 . hydra--digit-argument)
175 (kp-6 . hydra--digit-argument)
176 (kp-5 . hydra--digit-argument)
177 (kp-4 . hydra--digit-argument)
178 (kp-3 . hydra--digit-argument)
179 (kp-2 . hydra--digit-argument)
180 (kp-1 . hydra--digit-argument)
181 (kp-0 . hydra--digit-argument)
182 (57 . hydra--digit-argument)
183 (56 . hydra--digit-argument)
184 (55 . hydra--digit-argument)
185 (54 . hydra--digit-argument)
186 (53 . hydra--digit-argument)
187 (52 . hydra--digit-argument)
188 (51 . hydra--digit-argument)
189 (50 . hydra--digit-argument)
190 (49 . hydra--digit-argument)
191 (48 . hydra--digit-argument)
192 (45 . hydra--negative-argument)
193 (21 . hydra--universal-argument))))
194 t (lambda nil (hydra-cleanup))))
195 (setq prefix-arg current-prefix-arg)))
196 ```
197
198 ## `awesome-map` and `awesome-binding`
199
200 This can be any keymap, for instance, `global-map` or `isearch-mode-map`.
201
202 For this example:
203
204 ```cl
205 (defhydra hydra-zoom (global-map "<f2>")
206 "zoom"
207 ("g" text-scale-increase "in")
208 ("l" text-scale-decrease "out"))
209 ```
210
211 - `awesome-map` is `global-map`
212 - `awesome-binding` is `"<f2>"`
213
214 And here's the relevant generated code:
215
216 ```cl
217 (unless (keymapp (lookup-key global-map (kbd "<f2>")))
218 (define-key global-map (kbd "<f2>") nil))
219 (define-key global-map [f2 103]
220 (function hydra-zoom/text-scale-increase))
221 (define-key global-map [f2 108]
222 (function hydra-zoom/text-scale-decrease))
223 ```
224
225 As you see, `"<f2>"` is used as a prefix for <kbd>g</kbd> (char value 103) and <kbd>l</kbd>
226 (char value 108).
227
228 If you don't want to use a map right now, you can skip it like this:
229
230 ```cl
231 (defhydra hydra-zoom (nil nil)
232 "zoom"
233 ("g" text-scale-increase "in")
234 ("l" text-scale-decrease "out"))
235 ```
236
237 Or even simpler:
238
239 ```cl
240 (defhydra hydra-zoom ()
241 "zoom"
242 ("g" text-scale-increase "in")
243 ("l" text-scale-decrease "out"))
244 ```
245
246 But then you would have to bind `hydra-zoom/text-scale-increase` and
247 `hydra-zoom/text-scale-decrease` yourself.
248
249 ## `awesome-plist`
250
251 You can read up on what a plist is in
252 [the Elisp manual](https://www.gnu.org/software/emacs/manual/html_node/elisp/Property-Lists.html).
253
254 You can use `awesome-plist` to modify the behavior of each head in some way.
255 Below is a list of each key.
256
257 ### `:pre` and `:post`
258
259 You can specify code that will be called before each head, and after the body. For example:
260
261 ```cl
262 (defhydra hydra-vi (:pre (set-cursor-color "#40e0d0")
263 :post (progn
264 (set-cursor-color "#ffffff")
265 (message
266 "Thank you, come again.")))
267 "vi"
268 ("l" forward-char)
269 ("h" backward-char)
270 ("j" next-line)
271 ("k" previous-line)
272 ("q" nil "quit"))
273 ```
274
275 Thanks to `:pre`, each time any head is called, the cursor color is changed.
276 And when the hydra quits, the cursor color will be made black again with `:post`.
277
278 ### `:exit`
279
280 The `:exit` key is inherited by every head (they can override it) and influences what will happen
281 after executing head's command:
282
283 - `:exit nil` (the default) means that the hydra state will continue - you'll still see the hint and be able to use short bindings.
284 - `:exit t` means that the hydra state will stop.
285
286 ### `:foreign-keys`
287
288 The `:foreign-keys` key belongs to the body and decides what to do when a key is pressed that doesn't
289 belong to any head:
290
291 - `:foreign-keys nil` (the default) means that the hydra state will stop and the foreign key will
292 do whatever it was supposed to do if there was no hydra state.
293 - `:foreign-keys warn` will not stop the hydra state, but instead will issue a warning without
294 running the foreign key.
295 - `:foreign-keys run` will not stop the hydra state, and try to run the foreign key.
296
297 ### `:color`
298
299 The `:color` key is a shortcut. It aggregates `:exit` and `:foreign-keys` key in the following way:
300
301 | color | toggle |
302 |----------+----------------------------|
303 | red | |
304 | blue | :exit t |
305 | amaranth | :foreign-keys warn |
306 | teal | :foreign-keys warn :exit t |
307 | pink | :foreign-keys run |
308
309 It's also a trick to make you instantly aware of the current hydra keys that you're about to press:
310 the keys will be highlighted with the appropriate color.
311
312 ### `:timeout`
313
314 The `:timeout` key starts a timer for the corresponding amount of seconds that disables the hydra.
315 Calling any head will refresh the timer.
316
317 ### `:hint`
318
319 The `:hint` key will be inherited by each head. Each head is allowed to override it, of course.
320 One value that makes sense is `:hint nil`. See below for an explanation of head hint.
321
322 ### `:bind`
323
324 The `:bind` key provides a lambda to be used to bind each head. This is quite advanced and rarely
325 used, you're not likely to need it. But if you would like to bind your heads with e.g. `bind-key`
326 instead of `define-key` you can use this option.
327
328 The `:bind` key can be overridden by each head. This is useful if you want to have a few heads that
329 are not bound outside the hydra.
330
331 ## `awesome-docstring`
332
333 This can be a simple string used to build the final hydra hint. However, if you start it with a
334 newline, the key-highlighting and Ruby-style string interpolation becomes enabled, as you can see in
335 `hydra-buffer-menu` above.
336
337 To highlight a key, just wrap it in underscores. Note that the key must belong to one of the heads.
338 The key will be highlighted with the color that is appropriate to the behavior of the key, i.e. if
339 the key will make the hydra exit, the color will be blue.
340
341 To insert an empty character, use `^`. The only use of this is to have your code aligned as
342 nicely as the result.
343
344 To insert a dynamic Elisp variable, use `%`&#96; followed by the variable. Each time the variable
345 changes due to a head, the docstring will be updated. `format`-style width specifiers can be used.
346
347 To insert a dynamic Elisp expression, use e.g. `%(length (dired-get-marked-files))`. If a head will
348 change the amount of marked files, for example, it will be appropriately updated.
349
350 If the result of the Elisp expression is a string and you don't want to quote it, use this form:
351 `%s(shell-command-to-string "du -hs")`.
352
353 ## `awesome-head-1`
354
355 Each head looks like this:
356
357 ```cl
358 (head-binding head-command head-hint head-plist)
359 ```
360
361 For the head `("g" text-scale-increase "in")`:
362
363 - `head-binding` is `"g"`.
364 - `head-command` is `text-scale-increase`.
365 - `head-hint` is `"in"`.
366 - `head-plist` is `nil`.
367
368 ### `head-binding`
369
370 The `head-binding` is a string that can be passed to `kbd`.
371
372 ### `head-command`
373
374 The `head-command` can be:
375
376 - command name, like `text-scale-increase`.
377 - a lambda, like
378
379 ("g" (lambda ()
380 (interactive)
381 (let ((current-prefix-arg 4))
382 (call-interactively #'magit-status)))
383 "git")
384
385 - nil, which exits the hydra.
386 - a single sexp, which will be wrapped in an interactive lambda.
387
388 Here's an example of the last option:
389
390 ```cl
391 (defhydra hydra-launcher (:color blue)
392 "Launch"
393 ("h" man "man")
394 ("r" (browse-url "http://www.reddit.com/r/emacs/") "reddit")
395 ("w" (browse-url "http://www.emacswiki.org/") "emacswiki")
396 ("s" shell "shell")
397 ("q" nil "cancel"))
398 (global-set-key (kbd "C-c r") 'hydra-launcher/body)
399 ```
400
401 ### `head-hint`
402
403 In case of a large body docstring, you usually don't want the head hint to show up, since
404 you've already documented it the the body docstring.
405 You can set the head hint to `nil` to do this.
406
407 Example:
408
409 ```cl
410 (defhydra hydra-zoom (global-map "<f2>")
411 "
412 Press _g_ to zoom in.
413 "
414 ("g" text-scale-increase nil)
415 ("l" text-scale-decrease "out"))
416 ```
417
418 ### `head-plist`
419
420 Here's a list of body keys that can be overridden in each head:
421
422 - `:exit`
423 - `:color`
424 - `:bind`