]> code.delx.au - gnu-emacs-elpa/blob - packages/hydra/hydra-examples.el
Merge commit 'f062d5a55496e22cf89f2ef9778a24a840a5a68e' from context-coloring
[gnu-emacs-elpa] / packages / hydra / hydra-examples.el
1 ;;; hydra-examples.el --- Some applications for Hydra
2
3 ;; Copyright (C) 2015 Free Software Foundation, Inc.
4
5 ;; Author: Oleh Krehel
6
7 ;; This file is part of GNU Emacs.
8
9 ;; GNU Emacs is free software: you can redistribute it and/or modify
10 ;; it under the terms of the GNU General Public License as published by
11 ;; the Free Software Foundation, either version 3 of the License, or
12 ;; (at your option) any later version.
13
14 ;; GNU Emacs is distributed in the hope that it will be useful,
15 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 ;; GNU General Public License for more details.
18
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
21
22 ;;; Commentary:
23 ;;
24 ;; These are the sample Hydras.
25 ;;
26 ;; If you want to use them plainly, set `hydra-examples-verbatim' to t
27 ;; before requiring this file. But it's probably better to only look
28 ;; at them and use them as templates for building your own.
29
30 ;;; Code:
31
32 (require 'hydra)
33
34 ;;* Examples
35 ;;** Example 1: text scale
36 (when (bound-and-true-p hydra-examples-verbatim)
37 (defhydra hydra-zoom (global-map "<f2>")
38 "zoom"
39 ("g" text-scale-increase "in")
40 ("l" text-scale-decrease "out")))
41
42 ;; This example generates three commands:
43 ;;
44 ;; `hydra-zoom/text-scale-increase'
45 ;; `hydra-zoom/text-scale-decrease'
46 ;; `hydra-zoom/body'
47 ;;
48 ;; In addition, two of them are bound like this:
49 ;;
50 ;; (global-set-key (kbd "<f2> g") 'hydra-zoom/text-scale-increase)
51 ;; (global-set-key (kbd "<f2> l") 'hydra-zoom/text-scale-decrease)
52 ;;
53 ;; Note that you can substitute `global-map' with e.g. `emacs-lisp-mode-map' if you need.
54 ;; The functions generated will be the same, except the binding code will change to:
55 ;;
56 ;; (define-key emacs-lisp-mode-map [f2 103]
57 ;; (function hydra-zoom/text-scale-increase))
58 ;; (define-key emacs-lisp-mode-map [f2 108]
59 ;; (function hydra-zoom/text-scale-decrease))
60
61 ;;** Example 2: move window splitter
62 (when (bound-and-true-p hydra-examples-verbatim)
63 (defhydra hydra-splitter (global-map "C-M-s")
64 "splitter"
65 ("h" hydra-move-splitter-left)
66 ("j" hydra-move-splitter-down)
67 ("k" hydra-move-splitter-up)
68 ("l" hydra-move-splitter-right)))
69
70 ;;** Example 3: jump to error
71 (when (bound-and-true-p hydra-examples-verbatim)
72 (defhydra hydra-error (global-map "M-g")
73 "goto-error"
74 ("h" first-error "first")
75 ("j" next-error "next")
76 ("k" previous-error "prev")
77 ("v" recenter-top-bottom "recenter")
78 ("q" nil "quit")))
79
80 ;; This example introduces only one new thing: since the command
81 ;; passed to the "q" head is nil, it will quit the Hydra without doing
82 ;; anything. Heads that quit the Hydra instead of continuing are
83 ;; referred to as having blue :color. All the other heads have red
84 ;; :color, unless other is specified.
85
86 ;;** Example 4: toggle rarely used modes
87 (when (bound-and-true-p hydra-examples-verbatim)
88 (global-set-key
89 (kbd "C-c C-v")
90 (defhydra hydra-toggle (:color blue)
91 "toggle"
92 ("a" abbrev-mode "abbrev")
93 ("d" toggle-debug-on-error "debug")
94 ("f" auto-fill-mode "fill")
95 ("t" toggle-truncate-lines "truncate")
96 ("w" whitespace-mode "whitespace")
97 ("q" nil "cancel"))))
98
99 ;; Note that in this case, `defhydra' returns the `hydra-toggle/body'
100 ;; symbol, which is then passed to `global-set-key'.
101 ;;
102 ;; Another new thing is that both the keymap and the body prefix are
103 ;; skipped. This means that `defhydra' will bind nothing - that's why
104 ;; `global-set-key' is necessary.
105 ;;
106 ;; One more new thing is that you can assign a :color to the body. All
107 ;; heads will inherit this color. The code above is very much equivalent to:
108 ;;
109 ;; (global-set-key (kbd "C-c C-v a") 'abbrev-mode)
110 ;; (global-set-key (kbd "C-c C-v d") 'toggle-debug-on-error)
111 ;;
112 ;; The differences are:
113 ;;
114 ;; * You get a hint immediately after "C-c C-v"
115 ;; * You can cancel and call a command immediately, e.g. "C-c C-v C-n"
116 ;; is equivalent to "C-n" with Hydra approach, while it will error
117 ;; that "C-c C-v C-n" isn't bound with the usual approach.
118
119 ;;** Example 5: mini-vi
120 (defun hydra-vi/pre ()
121 (set-cursor-color "#e52b50"))
122
123 (defun hydra-vi/post ()
124 (set-cursor-color "#ffffff"))
125
126 (when (bound-and-true-p hydra-examples-verbatim)
127 (global-set-key
128 (kbd "C-z")
129 (defhydra hydra-vi (:pre hydra-vi/pre :post hydra-vi/post :color amaranth)
130 "vi"
131 ("l" forward-char)
132 ("h" backward-char)
133 ("j" next-line)
134 ("k" previous-line)
135 ("m" set-mark-command "mark")
136 ("a" move-beginning-of-line "beg")
137 ("e" move-end-of-line "end")
138 ("d" delete-region "del" :color blue)
139 ("y" kill-ring-save "yank" :color blue)
140 ("q" nil "quit"))))
141
142 ;; This example introduces :color amaranth. It's similar to red,
143 ;; except while you can quit red with any binding which isn't a Hydra
144 ;; head, you can quit amaranth only with a blue head. So you can quit
145 ;; this mode only with "d", "y", "q" or "C-g".
146 ;;
147 ;; Another novelty are the :pre and :post handlers. :pre will be
148 ;; called before each command, while :post will be called when the
149 ;; Hydra quits. In this case, they're used to override the cursor
150 ;; color while Hydra is active.
151
152 ;;** Example 6: selective global bind
153 (when (bound-and-true-p hydra-examples-verbatim)
154 (defhydra hydra-next-error (global-map "C-x")
155 "next-error"
156 ("`" next-error "next")
157 ("j" next-error "next" :bind nil)
158 ("k" previous-error "previous" :bind nil)))
159
160 ;; This example will bind "C-x `" in `global-map', but it will not
161 ;; bind "C-x j" and "C-x k".
162 ;; You can still "C-x `jjk" though.
163 ;;** Example 7: toggle with Ruby-style docstring
164 (when (bound-and-true-p hydra-examples-verbatim)
165 (defhydra hydra-toggle (:color pink)
166 "
167 _a_ abbrev-mode: %`abbrev-mode
168 _d_ debug-on-error: %`debug-on-error
169 _f_ auto-fill-mode: %`auto-fill-function
170 _g_ golden-ratio-mode: %`golden-ratio-mode
171 _t_ truncate-lines: %`truncate-lines
172 _w_ whitespace-mode: %`whitespace-mode
173
174 "
175 ("a" abbrev-mode nil)
176 ("d" toggle-debug-on-error nil)
177 ("f" auto-fill-mode nil)
178 ("g" golden-ratio-mode nil)
179 ("t" toggle-truncate-lines nil)
180 ("w" whitespace-mode nil)
181 ("q" nil "quit"))
182 (global-set-key (kbd "C-c C-v") 'hydra-toggle/body))
183
184 ;; Here, using e.g. "_a_" translates to "a" with proper face.
185 ;; More interestingly:
186 ;;
187 ;; "foobar %`abbrev-mode" means roughly (format "foobar %S" abbrev-mode)
188 ;;
189 ;; This means that you actually see the state of the mode that you're changing.
190 ;;** Example 8: the whole menu for `Buffer-menu-mode'
191 (defhydra hydra-buffer-menu (:color pink)
192 "
193 Mark Unmark Actions Search
194 ------------------------------------------------------------------------- (__)
195 _m_: mark _u_: unmark _x_: execute _R_: re-isearch (oo)
196 _s_: save _U_: unmark up _b_: bury _I_: isearch /------\\/
197 _d_: delete _g_: refresh _O_: multi-occur / | ||
198 _D_: delete up _T_: files only: % -28`Buffer-menu-files-only * /\\---/\\
199 _~_: modified ~~ ~~
200 "
201 ("m" Buffer-menu-mark nil)
202 ("u" Buffer-menu-unmark nil)
203 ("U" Buffer-menu-backup-unmark nil)
204 ("d" Buffer-menu-delete nil)
205 ("D" Buffer-menu-delete-backwards nil)
206 ("s" Buffer-menu-save nil)
207 ("~" Buffer-menu-not-modified nil)
208 ("x" Buffer-menu-execute nil)
209 ("b" Buffer-menu-bury nil)
210 ("g" revert-buffer nil)
211 ("T" Buffer-menu-toggle-files-only nil)
212 ("O" Buffer-menu-multi-occur nil :color blue)
213 ("I" Buffer-menu-isearch-buffers nil :color blue)
214 ("R" Buffer-menu-isearch-buffers-regexp nil :color blue)
215 ("c" nil "cancel")
216 ("v" Buffer-menu-select "select" :color blue)
217 ("o" Buffer-menu-other-window "other-window" :color blue)
218 ("q" quit-window "quit" :color blue))
219 ;; Recommended binding:
220 ;; (define-key Buffer-menu-mode-map "." 'hydra-buffer-menu/body)
221 ;;** Example 9: s-expressions in the docstring
222 ;; You can inline s-expresssions into the docstring like this:
223 (when (bound-and-true-p hydra-examples-verbatim)
224 (eval-after-load 'dired
225 (defhydra hydra-marked-items (dired-mode-map "")
226 "
227 Number of marked items: %(length (dired-get-marked-files))
228 "
229 ("m" dired-mark "mark"))))
230
231 ;; This results in the following dynamic docstring:
232 ;;
233 ;; (format "Number of marked items: %S\n"
234 ;; (length (dired-get-marked-files)))
235 ;;
236 ;; You can use `format'-style width specs, e.g. % 10(length nil).
237
238 ;;* Windmove helpers
239 (require 'windmove)
240
241 (defun hydra-move-splitter-left (arg)
242 "Move window splitter left."
243 (interactive "p")
244 (if (let ((windmove-wrap-around))
245 (windmove-find-other-window 'right))
246 (shrink-window-horizontally arg)
247 (enlarge-window-horizontally arg)))
248
249 (defun hydra-move-splitter-right (arg)
250 "Move window splitter right."
251 (interactive "p")
252 (if (let ((windmove-wrap-around))
253 (windmove-find-other-window 'right))
254 (enlarge-window-horizontally arg)
255 (shrink-window-horizontally arg)))
256
257 (defun hydra-move-splitter-up (arg)
258 "Move window splitter up."
259 (interactive "p")
260 (if (let ((windmove-wrap-around))
261 (windmove-find-other-window 'up))
262 (enlarge-window arg)
263 (shrink-window arg)))
264
265 (defun hydra-move-splitter-down (arg)
266 "Move window splitter down."
267 (interactive "p")
268 (if (let ((windmove-wrap-around))
269 (windmove-find-other-window 'up))
270 (shrink-window arg)
271 (enlarge-window arg)))
272
273 (provide 'hydra-examples)
274 ;;; hydra-examples.el ends here