]> code.delx.au - gnu-emacs-elpa/blob - hydra-test.el
hydra.el (hydra--format): Update regex order
[gnu-emacs-elpa] / hydra-test.el
1 ;;; hydra-test.el --- Tests 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
25 ;;; Code:
26
27 (require 'ert)
28
29 (ert-deftest hydra-red-error ()
30 (should
31 (equal
32 (macroexpand
33 '(defhydra hydra-error (global-map "M-g")
34 "error"
35 ("h" first-error "first")
36 ("j" next-error "next")
37 ("k" previous-error "prev")
38 ("SPC" hydra-repeat "rep" :bind nil)))
39 '(progn
40 (defun hydra-error/first-error nil "Create a hydra with a \"M-g\" body and the heads:
41
42 \"h\": `first-error',
43 \"j\": `next-error',
44 \"k\": `previous-error',
45 \"SPC\": `hydra-repeat'
46
47 The body can be accessed via `hydra-error/body'.
48
49 Call the head: `first-error'."
50 (interactive)
51 (hydra-disable)
52 (catch (quote hydra-disable)
53 (condition-case err (prog1 t (call-interactively (function first-error)))
54 ((quit error)
55 (message "%S" err)
56 (unless hydra-lv (sit-for 0.8))
57 nil))
58 (when hydra-is-helpful (hydra-error/hint))
59 (setq hydra-last
60 (hydra-set-transient-map
61 (setq hydra-curr-map
62 (quote (keymap (7 . hydra-keyboard-quit)
63 (32 . hydra-repeat)
64 (107 . hydra-error/previous-error)
65 (106 . hydra-error/next-error)
66 (104 . hydra-error/first-error)
67 (switch-frame . hydra--handle-switch-frame)
68 (kp-subtract . hydra--negative-argument)
69 (kp-9 . hydra--digit-argument)
70 (kp-8 . hydra--digit-argument)
71 (kp-7 . hydra--digit-argument)
72 (kp-6 . hydra--digit-argument)
73 (kp-5 . hydra--digit-argument)
74 (kp-4 . hydra--digit-argument)
75 (kp-3 . hydra--digit-argument)
76 (kp-2 . hydra--digit-argument)
77 (kp-1 . hydra--digit-argument)
78 (kp-0 . hydra--digit-argument)
79 (57 . hydra--digit-argument)
80 (56 . hydra--digit-argument)
81 (55 . hydra--digit-argument)
82 (54 . hydra--digit-argument)
83 (53 . hydra--digit-argument)
84 (52 . hydra--digit-argument)
85 (51 . hydra--digit-argument)
86 (50 . hydra--digit-argument)
87 (49 . hydra--digit-argument)
88 (48 . hydra--digit-argument)
89 (45 . hydra--negative-argument)
90 (21 . hydra--universal-argument))))
91 t (lambda nil (hydra-cleanup))))))
92 (defun hydra-error/next-error nil "Create a hydra with a \"M-g\" body and the heads:
93
94 \"h\": `first-error',
95 \"j\": `next-error',
96 \"k\": `previous-error',
97 \"SPC\": `hydra-repeat'
98
99 The body can be accessed via `hydra-error/body'.
100
101 Call the head: `next-error'."
102 (interactive)
103 (hydra-disable)
104 (catch (quote hydra-disable)
105 (condition-case err (prog1 t (call-interactively (function next-error)))
106 ((quit error)
107 (message "%S" err)
108 (unless hydra-lv (sit-for 0.8))
109 nil))
110 (when hydra-is-helpful (hydra-error/hint))
111 (setq hydra-last
112 (hydra-set-transient-map
113 (setq hydra-curr-map
114 (quote (keymap (7 . hydra-keyboard-quit)
115 (32 . hydra-repeat)
116 (107 . hydra-error/previous-error)
117 (106 . hydra-error/next-error)
118 (104 . hydra-error/first-error)
119 (switch-frame . hydra--handle-switch-frame)
120 (kp-subtract . hydra--negative-argument)
121 (kp-9 . hydra--digit-argument)
122 (kp-8 . hydra--digit-argument)
123 (kp-7 . hydra--digit-argument)
124 (kp-6 . hydra--digit-argument)
125 (kp-5 . hydra--digit-argument)
126 (kp-4 . hydra--digit-argument)
127 (kp-3 . hydra--digit-argument)
128 (kp-2 . hydra--digit-argument)
129 (kp-1 . hydra--digit-argument)
130 (kp-0 . hydra--digit-argument)
131 (57 . hydra--digit-argument)
132 (56 . hydra--digit-argument)
133 (55 . hydra--digit-argument)
134 (54 . hydra--digit-argument)
135 (53 . hydra--digit-argument)
136 (52 . hydra--digit-argument)
137 (51 . hydra--digit-argument)
138 (50 . hydra--digit-argument)
139 (49 . hydra--digit-argument)
140 (48 . hydra--digit-argument)
141 (45 . hydra--negative-argument)
142 (21 . hydra--universal-argument))))
143 t (lambda nil (hydra-cleanup))))))
144 (defun hydra-error/previous-error nil "Create a hydra with a \"M-g\" body and the heads:
145
146 \"h\": `first-error',
147 \"j\": `next-error',
148 \"k\": `previous-error',
149 \"SPC\": `hydra-repeat'
150
151 The body can be accessed via `hydra-error/body'.
152
153 Call the head: `previous-error'."
154 (interactive)
155 (hydra-disable)
156 (catch (quote hydra-disable)
157 (condition-case err (prog1 t (call-interactively (function previous-error)))
158 ((quit error)
159 (message "%S" err)
160 (unless hydra-lv (sit-for 0.8))
161 nil))
162 (when hydra-is-helpful (hydra-error/hint))
163 (setq hydra-last
164 (hydra-set-transient-map
165 (setq hydra-curr-map
166 (quote (keymap (7 . hydra-keyboard-quit)
167 (32 . hydra-repeat)
168 (107 . hydra-error/previous-error)
169 (106 . hydra-error/next-error)
170 (104 . hydra-error/first-error)
171 (switch-frame . hydra--handle-switch-frame)
172 (kp-subtract . hydra--negative-argument)
173 (kp-9 . hydra--digit-argument)
174 (kp-8 . hydra--digit-argument)
175 (kp-7 . hydra--digit-argument)
176 (kp-6 . hydra--digit-argument)
177 (kp-5 . hydra--digit-argument)
178 (kp-4 . hydra--digit-argument)
179 (kp-3 . hydra--digit-argument)
180 (kp-2 . hydra--digit-argument)
181 (kp-1 . hydra--digit-argument)
182 (kp-0 . hydra--digit-argument)
183 (57 . hydra--digit-argument)
184 (56 . hydra--digit-argument)
185 (55 . hydra--digit-argument)
186 (54 . hydra--digit-argument)
187 (53 . hydra--digit-argument)
188 (52 . hydra--digit-argument)
189 (51 . hydra--digit-argument)
190 (50 . hydra--digit-argument)
191 (49 . hydra--digit-argument)
192 (48 . hydra--digit-argument)
193 (45 . hydra--negative-argument)
194 (21 . hydra--universal-argument))))
195 t (lambda nil (hydra-cleanup))))))
196 (unless (keymapp (lookup-key global-map (kbd "M-g")))
197 (define-key global-map (kbd "M-g")
198 nil))
199 (define-key global-map [134217831 104]
200 (function hydra-error/first-error))
201 (define-key global-map [134217831 106]
202 (function hydra-error/next-error))
203 (define-key global-map [134217831 107]
204 (function hydra-error/previous-error))
205 (defun hydra-error/hint nil
206 (if hydra-lv (lv-message (format #("error: [h]: first, [j]: next, [k]: prev, [SPC]: rep." 8 9 (face hydra-face-red)
207 20 21 (face hydra-face-red)
208 31 32 (face hydra-face-red)
209 42 45 (face hydra-face-red))))
210 (message (format #("error: [h]: first, [j]: next, [k]: prev, [SPC]: rep." 8 9 (face hydra-face-red)
211 20 21 (face hydra-face-red)
212 31 32 (face hydra-face-red)
213 42 45 (face hydra-face-red))))))
214 (defun hydra-error/body nil "Create a hydra with a \"M-g\" body and the heads:
215
216 \"h\": `first-error',
217 \"j\": `next-error',
218 \"k\": `previous-error',
219 \"SPC\": `hydra-repeat'
220
221 The body can be accessed via `hydra-error/body'."
222 (interactive)
223 (hydra-disable)
224 (catch (quote hydra-disable)
225 (when hydra-is-helpful (hydra-error/hint))
226 (setq hydra-last
227 (hydra-set-transient-map
228 (setq hydra-curr-map
229 (quote (keymap (7 . hydra-keyboard-quit)
230 (32 . hydra-repeat)
231 (107 . hydra-error/previous-error)
232 (106 . hydra-error/next-error)
233 (104 . hydra-error/first-error)
234 (switch-frame . hydra--handle-switch-frame)
235 (kp-subtract . hydra--negative-argument)
236 (kp-9 . hydra--digit-argument)
237 (kp-8 . hydra--digit-argument)
238 (kp-7 . hydra--digit-argument)
239 (kp-6 . hydra--digit-argument)
240 (kp-5 . hydra--digit-argument)
241 (kp-4 . hydra--digit-argument)
242 (kp-3 . hydra--digit-argument)
243 (kp-2 . hydra--digit-argument)
244 (kp-1 . hydra--digit-argument)
245 (kp-0 . hydra--digit-argument)
246 (57 . hydra--digit-argument)
247 (56 . hydra--digit-argument)
248 (55 . hydra--digit-argument)
249 (54 . hydra--digit-argument)
250 (53 . hydra--digit-argument)
251 (52 . hydra--digit-argument)
252 (51 . hydra--digit-argument)
253 (50 . hydra--digit-argument)
254 (49 . hydra--digit-argument)
255 (48 . hydra--digit-argument)
256 (45 . hydra--negative-argument)
257 (21 . hydra--universal-argument))))
258 t (lambda nil (hydra-cleanup))))
259 (setq prefix-arg current-prefix-arg)))))))
260
261 (ert-deftest hydra-blue-toggle ()
262 (should
263 (equal
264 (macroexpand
265 '(defhydra hydra-toggle (:color blue)
266 "toggle"
267 ("t" toggle-truncate-lines "truncate")
268 ("f" auto-fill-mode "fill")
269 ("a" abbrev-mode "abbrev")
270 ("q" nil "cancel")))
271 '(progn
272 (defun hydra-toggle/toggle-truncate-lines-and-exit nil "Create a hydra with no body and the heads:
273
274 \"t\": `toggle-truncate-lines',
275 \"f\": `auto-fill-mode',
276 \"a\": `abbrev-mode',
277 \"q\": `nil'
278
279 The body can be accessed via `hydra-toggle/body'.
280
281 Call the head: `toggle-truncate-lines'."
282 (interactive)
283 (hydra-disable)
284 (hydra-cleanup)
285 (catch (quote hydra-disable)
286 (call-interactively (function toggle-truncate-lines))))
287 (defun hydra-toggle/auto-fill-mode-and-exit nil "Create a hydra with no body and the heads:
288
289 \"t\": `toggle-truncate-lines',
290 \"f\": `auto-fill-mode',
291 \"a\": `abbrev-mode',
292 \"q\": `nil'
293
294 The body can be accessed via `hydra-toggle/body'.
295
296 Call the head: `auto-fill-mode'."
297 (interactive)
298 (hydra-disable)
299 (hydra-cleanup)
300 (catch (quote hydra-disable)
301 (call-interactively (function auto-fill-mode))))
302 (defun hydra-toggle/abbrev-mode-and-exit nil "Create a hydra with no body and the heads:
303
304 \"t\": `toggle-truncate-lines',
305 \"f\": `auto-fill-mode',
306 \"a\": `abbrev-mode',
307 \"q\": `nil'
308
309 The body can be accessed via `hydra-toggle/body'.
310
311 Call the head: `abbrev-mode'."
312 (interactive)
313 (hydra-disable)
314 (hydra-cleanup)
315 (catch (quote hydra-disable)
316 (call-interactively (function abbrev-mode))))
317 (defun hydra-toggle/nil nil "Create a hydra with no body and the heads:
318
319 \"t\": `toggle-truncate-lines',
320 \"f\": `auto-fill-mode',
321 \"a\": `abbrev-mode',
322 \"q\": `nil'
323
324 The body can be accessed via `hydra-toggle/body'.
325
326 Call the head: `nil'."
327 (interactive)
328 (hydra-disable)
329 (hydra-cleanup)
330 (catch (quote hydra-disable)))
331 (defun hydra-toggle/hint nil
332 (if hydra-lv (lv-message (format #("toggle: [t]: truncate, [f]: fill, [a]: abbrev, [q]: cancel." 9 10 (face hydra-face-blue)
333 24 25 (face hydra-face-blue)
334 35 36 (face hydra-face-blue)
335 48 49 (face hydra-face-blue))))
336 (message (format #("toggle: [t]: truncate, [f]: fill, [a]: abbrev, [q]: cancel." 9 10 (face hydra-face-blue)
337 24 25 (face hydra-face-blue)
338 35 36 (face hydra-face-blue)
339 48 49 (face hydra-face-blue))))))
340 (defun hydra-toggle/body nil "Create a hydra with no body and the heads:
341
342 \"t\": `toggle-truncate-lines',
343 \"f\": `auto-fill-mode',
344 \"a\": `abbrev-mode',
345 \"q\": `nil'
346
347 The body can be accessed via `hydra-toggle/body'."
348 (interactive)
349 (hydra-disable)
350 (catch (quote hydra-disable)
351 (when hydra-is-helpful (hydra-toggle/hint))
352 (setq hydra-last
353 (hydra-set-transient-map
354 (setq hydra-curr-map
355 (quote (keymap (7 . hydra-keyboard-quit)
356 (113 . hydra-toggle/nil)
357 (97 . hydra-toggle/abbrev-mode-and-exit)
358 (102 . hydra-toggle/auto-fill-mode-and-exit)
359 (116 . hydra-toggle/toggle-truncate-lines-and-exit)
360 (switch-frame . hydra--handle-switch-frame)
361 (kp-subtract . hydra--negative-argument)
362 (kp-9 . hydra--digit-argument)
363 (kp-8 . hydra--digit-argument)
364 (kp-7 . hydra--digit-argument)
365 (kp-6 . hydra--digit-argument)
366 (kp-5 . hydra--digit-argument)
367 (kp-4 . hydra--digit-argument)
368 (kp-3 . hydra--digit-argument)
369 (kp-2 . hydra--digit-argument)
370 (kp-1 . hydra--digit-argument)
371 (kp-0 . hydra--digit-argument)
372 (57 . hydra--digit-argument)
373 (56 . hydra--digit-argument)
374 (55 . hydra--digit-argument)
375 (54 . hydra--digit-argument)
376 (53 . hydra--digit-argument)
377 (52 . hydra--digit-argument)
378 (51 . hydra--digit-argument)
379 (50 . hydra--digit-argument)
380 (49 . hydra--digit-argument)
381 (48 . hydra--digit-argument)
382 (45 . hydra--negative-argument)
383 (21 . hydra--universal-argument))))
384 t (lambda nil (hydra-cleanup))))
385 (setq prefix-arg current-prefix-arg)))))))
386
387 (ert-deftest hydra-amaranth-vi ()
388 (should
389 (equal
390 (macroexpand
391 '(defhydra hydra-vi
392 (:pre
393 (set-cursor-color "#e52b50")
394 :post
395 (set-cursor-color "#ffffff")
396 :color amaranth)
397 "vi"
398 ("j" next-line)
399 ("k" previous-line)
400 ("q" nil "quit")))
401 '(progn
402 (defun hydra-vi/hydra-keyboard-quit-and-exit nil "Create a hydra with no body and the heads:
403
404 \"\a\": `hydra-keyboard-quit',
405 \"j\": `next-line',
406 \"k\": `previous-line',
407 \"q\": `nil'
408
409 The body can be accessed via `hydra-vi/body'.
410
411 Call the head: `hydra-keyboard-quit'."
412 (interactive)
413 (set-cursor-color "#e52b50")
414 (hydra-disable)
415 (hydra-cleanup)
416 (catch (quote hydra-disable)
417 (call-interactively (function hydra-keyboard-quit))
418 (set-cursor-color "#ffffff")))
419 (defun hydra-vi/next-line nil "Create a hydra with no body and the heads:
420
421 \"\a\": `hydra-keyboard-quit',
422 \"j\": `next-line',
423 \"k\": `previous-line',
424 \"q\": `nil'
425
426 The body can be accessed via `hydra-vi/body'.
427
428 Call the head: `next-line'."
429 (interactive)
430 (set-cursor-color "#e52b50")
431 (hydra-disable)
432 (catch (quote hydra-disable)
433 (condition-case err (prog1 t (call-interactively (function next-line)))
434 ((quit error)
435 (message "%S" err)
436 (unless hydra-lv (sit-for 0.8))
437 nil))
438 (when hydra-is-helpful (hydra-vi/hint))
439 (setq hydra-last
440 (hydra-set-transient-map
441 (setq hydra-curr-map
442 (quote (keymap (t lambda nil (interactive)
443 (message "An amaranth Hydra can only exit through a blue head")
444 (hydra-set-transient-map hydra-curr-map t)
445 (when hydra-is-helpful (unless hydra-lv (sit-for 0.8))
446 (hydra-vi/hint)))
447 (113 . hydra-vi/nil)
448 (107 . hydra-vi/previous-line)
449 (106 . hydra-vi/next-line)
450 (7 . hydra-vi/hydra-keyboard-quit-and-exit)
451 (switch-frame . hydra--handle-switch-frame)
452 (kp-subtract . hydra--negative-argument)
453 (kp-9 . hydra--digit-argument)
454 (kp-8 . hydra--digit-argument)
455 (kp-7 . hydra--digit-argument)
456 (kp-6 . hydra--digit-argument)
457 (kp-5 . hydra--digit-argument)
458 (kp-4 . hydra--digit-argument)
459 (kp-3 . hydra--digit-argument)
460 (kp-2 . hydra--digit-argument)
461 (kp-1 . hydra--digit-argument)
462 (kp-0 . hydra--digit-argument)
463 (57 . hydra--digit-argument)
464 (56 . hydra--digit-argument)
465 (55 . hydra--digit-argument)
466 (54 . hydra--digit-argument)
467 (53 . hydra--digit-argument)
468 (52 . hydra--digit-argument)
469 (51 . hydra--digit-argument)
470 (50 . hydra--digit-argument)
471 (49 . hydra--digit-argument)
472 (48 . hydra--digit-argument)
473 (45 . hydra--negative-argument)
474 (21 . hydra--universal-argument))))
475 t (lambda nil (hydra-cleanup))))))
476 (defun hydra-vi/previous-line nil "Create a hydra with no body and the heads:
477
478 \"\a\": `hydra-keyboard-quit',
479 \"j\": `next-line',
480 \"k\": `previous-line',
481 \"q\": `nil'
482
483 The body can be accessed via `hydra-vi/body'.
484
485 Call the head: `previous-line'."
486 (interactive)
487 (set-cursor-color "#e52b50")
488 (hydra-disable)
489 (catch (quote hydra-disable)
490 (condition-case err (prog1 t (call-interactively (function previous-line)))
491 ((quit error)
492 (message "%S" err)
493 (unless hydra-lv (sit-for 0.8))
494 nil))
495 (when hydra-is-helpful (hydra-vi/hint))
496 (setq hydra-last
497 (hydra-set-transient-map
498 (setq hydra-curr-map
499 (quote (keymap (t lambda nil (interactive)
500 (message "An amaranth Hydra can only exit through a blue head")
501 (hydra-set-transient-map hydra-curr-map t)
502 (when hydra-is-helpful (unless hydra-lv (sit-for 0.8))
503 (hydra-vi/hint)))
504 (113 . hydra-vi/nil)
505 (107 . hydra-vi/previous-line)
506 (106 . hydra-vi/next-line)
507 (7 . hydra-vi/hydra-keyboard-quit-and-exit)
508 (switch-frame . hydra--handle-switch-frame)
509 (kp-subtract . hydra--negative-argument)
510 (kp-9 . hydra--digit-argument)
511 (kp-8 . hydra--digit-argument)
512 (kp-7 . hydra--digit-argument)
513 (kp-6 . hydra--digit-argument)
514 (kp-5 . hydra--digit-argument)
515 (kp-4 . hydra--digit-argument)
516 (kp-3 . hydra--digit-argument)
517 (kp-2 . hydra--digit-argument)
518 (kp-1 . hydra--digit-argument)
519 (kp-0 . hydra--digit-argument)
520 (57 . hydra--digit-argument)
521 (56 . hydra--digit-argument)
522 (55 . hydra--digit-argument)
523 (54 . hydra--digit-argument)
524 (53 . hydra--digit-argument)
525 (52 . hydra--digit-argument)
526 (51 . hydra--digit-argument)
527 (50 . hydra--digit-argument)
528 (49 . hydra--digit-argument)
529 (48 . hydra--digit-argument)
530 (45 . hydra--negative-argument)
531 (21 . hydra--universal-argument))))
532 t (lambda nil (hydra-cleanup))))))
533 (defun hydra-vi/nil nil "Create a hydra with no body and the heads:
534
535 \"\a\": `hydra-keyboard-quit',
536 \"j\": `next-line',
537 \"k\": `previous-line',
538 \"q\": `nil'
539
540 The body can be accessed via `hydra-vi/body'.
541
542 Call the head: `nil'."
543 (interactive)
544 (set-cursor-color "#e52b50")
545 (hydra-disable)
546 (hydra-cleanup)
547 (catch (quote hydra-disable)
548 (set-cursor-color "#ffffff")))
549 (defun hydra-vi/hint nil
550 (if hydra-lv (lv-message (format #("vi: j, k, [q]: quit." 4 5 (face hydra-face-amaranth)
551 7 8 (face hydra-face-amaranth)
552 11 12 (face hydra-face-blue))))
553 (message (format #("vi: j, k, [q]: quit." 4 5 (face hydra-face-amaranth)
554 7 8 (face hydra-face-amaranth)
555 11 12 (face hydra-face-blue))))))
556 (defun hydra-vi/body nil "Create a hydra with no body and the heads:
557
558 \"\a\": `hydra-keyboard-quit',
559 \"j\": `next-line',
560 \"k\": `previous-line',
561 \"q\": `nil'
562
563 The body can be accessed via `hydra-vi/body'."
564 (interactive)
565 (set-cursor-color "#e52b50")
566 (hydra-disable)
567 (catch (quote hydra-disable)
568 (when hydra-is-helpful (hydra-vi/hint))
569 (setq hydra-last
570 (hydra-set-transient-map
571 (setq hydra-curr-map
572 (quote (keymap (t lambda nil (interactive)
573 (message "An amaranth Hydra can only exit through a blue head")
574 (hydra-set-transient-map hydra-curr-map t)
575 (when hydra-is-helpful (unless hydra-lv (sit-for 0.8))
576 (hydra-vi/hint)))
577 (113 . hydra-vi/nil)
578 (107 . hydra-vi/previous-line)
579 (106 . hydra-vi/next-line)
580 (7 . hydra-vi/hydra-keyboard-quit-and-exit)
581 (switch-frame . hydra--handle-switch-frame)
582 (kp-subtract . hydra--negative-argument)
583 (kp-9 . hydra--digit-argument)
584 (kp-8 . hydra--digit-argument)
585 (kp-7 . hydra--digit-argument)
586 (kp-6 . hydra--digit-argument)
587 (kp-5 . hydra--digit-argument)
588 (kp-4 . hydra--digit-argument)
589 (kp-3 . hydra--digit-argument)
590 (kp-2 . hydra--digit-argument)
591 (kp-1 . hydra--digit-argument)
592 (kp-0 . hydra--digit-argument)
593 (57 . hydra--digit-argument)
594 (56 . hydra--digit-argument)
595 (55 . hydra--digit-argument)
596 (54 . hydra--digit-argument)
597 (53 . hydra--digit-argument)
598 (52 . hydra--digit-argument)
599 (51 . hydra--digit-argument)
600 (50 . hydra--digit-argument)
601 (49 . hydra--digit-argument)
602 (48 . hydra--digit-argument)
603 (45 . hydra--negative-argument)
604 (21 . hydra--universal-argument))))
605 t (lambda nil (hydra-cleanup))))
606 (setq prefix-arg current-prefix-arg)))))))
607
608 (ert-deftest defhydradio ()
609 (should (equal
610 (macroexpand
611 '(defhydradio hydra-test ()
612 (num "Num" [0 1 2 3 4 5 6 7 8 9 10])
613 (str "Str" ["foo" "bar" "baz"])))
614 '(progn
615 (defvar hydra-test/num 0
616 "Num")
617 (put 'hydra-test/num 'range [0 1 2 3 4 5 6 7 8 9 10])
618 (defun hydra-test/num ()
619 (hydra--cycle-radio 'hydra-test/num))
620 (defvar hydra-test/str "foo"
621 "Str")
622 (put 'hydra-test/str 'range ["foo" "bar" "baz"])
623 (defun hydra-test/str ()
624 (hydra--cycle-radio 'hydra-test/str))
625 (defvar hydra-test/names '(hydra-test/num hydra-test/str))))))
626
627 (ert-deftest hydra-blue-compat ()
628 (should
629 (equal
630 (macroexpand
631 '(defhydra hydra-toggle (:color blue)
632 "toggle"
633 ("t" toggle-truncate-lines "truncate")
634 ("f" auto-fill-mode "fill")
635 ("a" abbrev-mode "abbrev")
636 ("q" nil "cancel")))
637 (macroexpand
638 '(defhydra hydra-toggle (:exit t)
639 "toggle"
640 ("t" toggle-truncate-lines "truncate")
641 ("f" auto-fill-mode "fill")
642 ("a" abbrev-mode "abbrev")
643 ("q" nil "cancel"))))))
644
645 (ert-deftest hydra-amaranth-compat ()
646 (should
647 (equal
648 (macroexpand
649 '(defhydra hydra-vi
650 (:pre
651 (set-cursor-color "#e52b50")
652 :post
653 (set-cursor-color "#ffffff")
654 :color amaranth)
655 "vi"
656 ("j" next-line)
657 ("k" previous-line)
658 ("q" nil "quit")))
659 (macroexpand
660 '(defhydra hydra-vi
661 (:pre
662 (set-cursor-color "#e52b50")
663 :post
664 (set-cursor-color "#ffffff")
665 :foreign-keys warn)
666 "vi"
667 ("j" next-line)
668 ("k" previous-line)
669 ("q" nil "quit"))))))
670
671 (ert-deftest hydra-pink-compat ()
672 (should
673 (equal
674 (macroexpand
675 '(defhydra hydra-zoom (global-map "<f2>"
676 :color pink)
677 "zoom"
678 ("g" text-scale-increase "in")
679 ("l" text-scale-decrease "out")
680 ("q" nil "quit")))
681 (macroexpand
682 '(defhydra hydra-zoom (global-map "<f2>"
683 :foreign-keys run)
684 "zoom"
685 ("g" text-scale-increase "in")
686 ("l" text-scale-decrease "out")
687 ("q" nil "quit"))))))
688
689 (ert-deftest hydra-teal-compat ()
690 (should
691 (equal
692 (macroexpand
693 '(defhydra hydra-zoom (global-map "<f2>"
694 :color teal)
695 "zoom"
696 ("g" text-scale-increase "in")
697 ("l" text-scale-decrease "out")
698 ("q" nil "quit")))
699 (macroexpand
700 '(defhydra hydra-zoom (global-map "<f2>"
701 :foreign-keys warn
702 :exit t)
703 "zoom"
704 ("g" text-scale-increase "in")
705 ("l" text-scale-decrease "out")
706 ("q" nil "quit"))))))
707
708 (ert-deftest hydra-format-1 ()
709 (should (equal
710 (let ((hydra-fontify-head-function
711 'hydra-fontify-head-greyscale))
712 (hydra--format
713 'hydra-toggle
714 nil
715 "
716 _a_ abbrev-mode: %`abbrev-mode
717 _d_ debug-on-error: %`debug-on-error
718 _f_ auto-fill-mode: %`auto-fill-function
719 " '(("a" abbrev-mode nil)
720 ("d" toggle-debug-on-error nil)
721 ("f" auto-fill-mode nil)
722 ("g" golden-ratio-mode nil)
723 ("t" toggle-truncate-lines nil)
724 ("w" whitespace-mode nil)
725 ("q" nil "quit"))))
726 '(concat (format "%s abbrev-mode: %S
727 %s debug-on-error: %S
728 %s auto-fill-mode: %S
729 " "{a}" abbrev-mode "{d}" debug-on-error "{f}" auto-fill-function) "[[q]]: quit"))))
730
731 (ert-deftest hydra-format-2 ()
732 (should (equal
733 (let ((hydra-fontify-head-function
734 'hydra-fontify-head-greyscale))
735 (hydra--format
736 'bar
737 nil
738 "\n bar %s`foo\n"
739 '(("a" (quote t) "" :cmd-name bar/lambda-a)
740 ("q" nil "" :cmd-name bar/nil))))
741 '(concat (format " bar %s\n" foo) "{a}, [q]"))))
742
743 (ert-deftest hydra-format-3 ()
744 (should (equal
745 (let ((hydra-fontify-head-function
746 'hydra-fontify-head-greyscale))
747 (hydra--format
748 'bar
749 nil
750 "\n_<SPC>_ ^^ace jump\n"
751 '(("<SPC>" ace-jump-char-mode nil :cmd-name bar/ace-jump-char-mode))))
752 '(concat (format "%s ace jump\n" "{<SPC>}") ""))))
753
754 (ert-deftest hydra-format-with-sexp-1 ()
755 (should (equal
756 (let ((hydra-fontify-head-function
757 'hydra-fontify-head-greyscale))
758 (hydra--format
759 'hydra-toggle nil
760 "\n_n_ narrow-or-widen-dwim %(progn (message \"checking\")(buffer-narrowed-p))asdf\n"
761 '(("n" narrow-to-region nil) ("q" nil "cancel"))))
762 '(concat (format "%s narrow-or-widen-dwim %Sasdf\n"
763 "{n}"
764 (progn
765 (message "checking")
766 (buffer-narrowed-p)))
767 "[[q]]: cancel"))))
768
769 (ert-deftest hydra-format-with-sexp-2 ()
770 (should (equal
771 (let ((hydra-fontify-head-function
772 'hydra-fontify-head-greyscale))
773 (hydra--format
774 'hydra-toggle nil
775 "\n_n_ narrow-or-widen-dwim %s(progn (message \"checking\")(buffer-narrowed-p))asdf\n"
776 '(("n" narrow-to-region nil) ("q" nil "cancel"))))
777 '(concat (format "%s narrow-or-widen-dwim %sasdf\n"
778 "{n}"
779 (progn
780 (message "checking")
781 (buffer-narrowed-p)))
782 "[[q]]: cancel"))))
783
784 (ert-deftest hydra-compat-colors-1 ()
785 (should (equal (hydra--head-color
786 '("e" (message "Exiting now") "blue")
787 '(nil nil :color blue))
788 'blue))
789 (should (equal (hydra--head-color
790 '("c" (message "Continuing") "red" :color red)
791 '(nil nil :color blue))
792 'red))
793 (should (equal (hydra--head-color
794 '("e" (message "Exiting now") "blue")
795 '(nil nil :exit t))
796 'blue))
797 (should (equal (hydra--head-color
798 '("j" next-line "" :exit t)
799 '(nil nil))
800 'blue))
801 (should (equal (hydra--head-color
802 '("c" (message "Continuing") "red" :exit nil)
803 '(nil nil :exit t))
804 'red))
805 (equal (hydra--head-color
806 '("a" abbrev-mode nil)
807 '(nil nil :color teal))
808 'teal)
809 (equal (hydra--head-color
810 '("a" abbrev-mode :exit nil)
811 '(nil nil :color teal))
812 'amaranth))
813
814 (ert-deftest hydra-compat-colors-2 ()
815 (should
816 (equal
817 (macroexpand
818 '(defhydra hydra-test (:color amaranth)
819 ("a" fun-a)
820 ("b" fun-b :color blue)
821 ("c" fun-c :color blue)
822 ("d" fun-d :color blue)
823 ("e" fun-e :color blue)
824 ("f" fun-f :color blue)))
825 (macroexpand
826 '(defhydra hydra-test (:color teal)
827 ("a" fun-a :color red)
828 ("b" fun-b)
829 ("c" fun-c)
830 ("d" fun-d)
831 ("e" fun-e)
832 ("f" fun-f))))))
833
834 (ert-deftest hydra-compat-colors-3 ()
835 (should
836 (equal
837 (macroexpand
838 '(defhydra hydra-test ()
839 ("a" fun-a)
840 ("b" fun-b :color blue)
841 ("c" fun-c :color blue)
842 ("d" fun-d :color blue)
843 ("e" fun-e :color blue)
844 ("f" fun-f :color blue)))
845 (macroexpand
846 '(defhydra hydra-test (:color blue)
847 ("a" fun-a :color red)
848 ("b" fun-b)
849 ("c" fun-c)
850 ("d" fun-d)
851 ("e" fun-e)
852 ("f" fun-f))))))
853
854 (ert-deftest hydra-compat-colors-4 ()
855 (should
856 (equal
857 (macroexpand
858 '(defhydra hydra-test ()
859 ("a" fun-a)
860 ("b" fun-b :exit t)
861 ("c" fun-c :exit t)
862 ("d" fun-d :exit t)
863 ("e" fun-e :exit t)
864 ("f" fun-f :exit t)))
865 (macroexpand
866 '(defhydra hydra-test (:exit t)
867 ("a" fun-a :exit nil)
868 ("b" fun-b)
869 ("c" fun-c)
870 ("d" fun-d)
871 ("e" fun-e)
872 ("f" fun-f))))))
873
874 (ert-deftest hydra-zoom-duplicate-1 ()
875 (should
876 (equal
877 (macroexpand
878 '(defhydra hydra-zoom ()
879 "zoom"
880 ("r" (text-scale-set 0) "reset")
881 ("0" (text-scale-set 0) :bind nil :exit t)
882 ("1" (text-scale-set 0) nil :bind nil :exit t)))
883 '(progn
884 (defun hydra-zoom/lambda-r nil "Create a hydra with no body and the heads:
885
886 \"r\": `(text-scale-set 0)',
887 \"0\": `(text-scale-set 0)',
888 \"1\": `(text-scale-set 0)'
889
890 The body can be accessed via `hydra-zoom/body'.
891
892 Call the head: `(text-scale-set 0)'."
893 (interactive)
894 (hydra-disable)
895 (catch (quote hydra-disable)
896 (condition-case err (prog1 t (call-interactively (function (lambda nil (interactive)
897 (text-scale-set 0)))))
898 ((quit error)
899 (message "%S" err)
900 (unless hydra-lv (sit-for 0.8))
901 nil))
902 (when hydra-is-helpful (hydra-zoom/hint))
903 (setq hydra-last
904 (hydra-set-transient-map
905 (setq hydra-curr-map
906 (quote (keymap (7 . hydra-keyboard-quit)
907 (114 . hydra-zoom/lambda-r)
908 (switch-frame . hydra--handle-switch-frame)
909 (kp-subtract . hydra--negative-argument)
910 (kp-9 . hydra--digit-argument)
911 (kp-8 . hydra--digit-argument)
912 (kp-7 . hydra--digit-argument)
913 (kp-6 . hydra--digit-argument)
914 (kp-5 . hydra--digit-argument)
915 (kp-4 . hydra--digit-argument)
916 (kp-3 . hydra--digit-argument)
917 (kp-2 . hydra--digit-argument)
918 (kp-1 . hydra--digit-argument)
919 (kp-0 . hydra--digit-argument)
920 (57 . hydra--digit-argument)
921 (56 . hydra--digit-argument)
922 (55 . hydra--digit-argument)
923 (54 . hydra--digit-argument)
924 (53 . hydra--digit-argument)
925 (52 . hydra--digit-argument)
926 (51 . hydra--digit-argument)
927 (50 . hydra--digit-argument)
928 (49 . hydra-zoom/lambda-0-and-exit)
929 (48 . hydra-zoom/lambda-0-and-exit)
930 (45 . hydra--negative-argument)
931 (21 . hydra--universal-argument))))
932 t (lambda nil (hydra-cleanup))))))
933 (defun hydra-zoom/lambda-0-and-exit nil "Create a hydra with no body and the heads:
934
935 \"r\": `(text-scale-set 0)',
936 \"0\": `(text-scale-set 0)',
937 \"1\": `(text-scale-set 0)'
938
939 The body can be accessed via `hydra-zoom/body'.
940
941 Call the head: `(text-scale-set 0)'."
942 (interactive)
943 (hydra-disable)
944 (hydra-cleanup)
945 (catch (quote hydra-disable)
946 (call-interactively (function (lambda nil (interactive)
947 (text-scale-set 0))))))
948 (defun hydra-zoom/hint nil
949 (if hydra-lv (lv-message (format #("zoom: [r 0]: reset." 7 8 (face hydra-face-red)
950 9 10 (face hydra-face-blue))))
951 (message (format #("zoom: [r 0]: reset." 7 8 (face hydra-face-red)
952 9 10 (face hydra-face-blue))))))
953 (defun hydra-zoom/body nil "Create a hydra with no body and the heads:
954
955 \"r\": `(text-scale-set 0)',
956 \"0\": `(text-scale-set 0)',
957 \"1\": `(text-scale-set 0)'
958
959 The body can be accessed via `hydra-zoom/body'."
960 (interactive)
961 (hydra-disable)
962 (catch (quote hydra-disable)
963 (when hydra-is-helpful (hydra-zoom/hint))
964 (setq hydra-last
965 (hydra-set-transient-map
966 (setq hydra-curr-map
967 (quote (keymap (7 . hydra-keyboard-quit)
968 (114 . hydra-zoom/lambda-r)
969 (switch-frame . hydra--handle-switch-frame)
970 (kp-subtract . hydra--negative-argument)
971 (kp-9 . hydra--digit-argument)
972 (kp-8 . hydra--digit-argument)
973 (kp-7 . hydra--digit-argument)
974 (kp-6 . hydra--digit-argument)
975 (kp-5 . hydra--digit-argument)
976 (kp-4 . hydra--digit-argument)
977 (kp-3 . hydra--digit-argument)
978 (kp-2 . hydra--digit-argument)
979 (kp-1 . hydra--digit-argument)
980 (kp-0 . hydra--digit-argument)
981 (57 . hydra--digit-argument)
982 (56 . hydra--digit-argument)
983 (55 . hydra--digit-argument)
984 (54 . hydra--digit-argument)
985 (53 . hydra--digit-argument)
986 (52 . hydra--digit-argument)
987 (51 . hydra--digit-argument)
988 (50 . hydra--digit-argument)
989 (49 . hydra-zoom/lambda-0-and-exit)
990 (48 . hydra-zoom/lambda-0-and-exit)
991 (45 . hydra--negative-argument)
992 (21 . hydra--universal-argument))))
993 t (lambda nil (hydra-cleanup))))
994 (setq prefix-arg current-prefix-arg)))))))
995
996 (ert-deftest hydra-zoom-duplicate-2 ()
997 (should
998 (equal
999 (macroexpand
1000 '(defhydra hydra-zoom ()
1001 "zoom"
1002 ("r" (text-scale-set 0) "reset")
1003 ("0" (text-scale-set 0) :bind nil :exit t)
1004 ("1" (text-scale-set 0) nil :bind nil)))
1005 '(progn
1006 (defun hydra-zoom/lambda-r nil "Create a hydra with no body and the heads:
1007
1008 \"r\": `(text-scale-set 0)',
1009 \"0\": `(text-scale-set 0)',
1010 \"1\": `(text-scale-set 0)'
1011
1012 The body can be accessed via `hydra-zoom/body'.
1013
1014 Call the head: `(text-scale-set 0)'."
1015 (interactive)
1016 (hydra-disable)
1017 (catch (quote hydra-disable)
1018 (condition-case err (prog1 t (call-interactively (function (lambda nil (interactive)
1019 (text-scale-set 0)))))
1020 ((quit error)
1021 (message "%S" err)
1022 (unless hydra-lv (sit-for 0.8))
1023 nil))
1024 (when hydra-is-helpful (hydra-zoom/hint))
1025 (setq hydra-last
1026 (hydra-set-transient-map
1027 (setq hydra-curr-map
1028 (quote (keymap (7 . hydra-keyboard-quit)
1029 (114 . hydra-zoom/lambda-r)
1030 (switch-frame . hydra--handle-switch-frame)
1031 (kp-subtract . hydra--negative-argument)
1032 (kp-9 . hydra--digit-argument)
1033 (kp-8 . hydra--digit-argument)
1034 (kp-7 . hydra--digit-argument)
1035 (kp-6 . hydra--digit-argument)
1036 (kp-5 . hydra--digit-argument)
1037 (kp-4 . hydra--digit-argument)
1038 (kp-3 . hydra--digit-argument)
1039 (kp-2 . hydra--digit-argument)
1040 (kp-1 . hydra--digit-argument)
1041 (kp-0 . hydra--digit-argument)
1042 (57 . hydra--digit-argument)
1043 (56 . hydra--digit-argument)
1044 (55 . hydra--digit-argument)
1045 (54 . hydra--digit-argument)
1046 (53 . hydra--digit-argument)
1047 (52 . hydra--digit-argument)
1048 (51 . hydra--digit-argument)
1049 (50 . hydra--digit-argument)
1050 (49 . hydra-zoom/lambda-r)
1051 (48 . hydra-zoom/lambda-0-and-exit)
1052 (45 . hydra--negative-argument)
1053 (21 . hydra--universal-argument))))
1054 t (lambda nil (hydra-cleanup))))))
1055 (defun hydra-zoom/lambda-0-and-exit nil "Create a hydra with no body and the heads:
1056
1057 \"r\": `(text-scale-set 0)',
1058 \"0\": `(text-scale-set 0)',
1059 \"1\": `(text-scale-set 0)'
1060
1061 The body can be accessed via `hydra-zoom/body'.
1062
1063 Call the head: `(text-scale-set 0)'."
1064 (interactive)
1065 (hydra-disable)
1066 (hydra-cleanup)
1067 (catch (quote hydra-disable)
1068 (call-interactively (function (lambda nil (interactive)
1069 (text-scale-set 0))))))
1070 (defun hydra-zoom/hint nil
1071 (if hydra-lv (lv-message (format #("zoom: [r 0]: reset." 7 8 (face hydra-face-red)
1072 9 10 (face hydra-face-blue))))
1073 (message (format #("zoom: [r 0]: reset." 7 8 (face hydra-face-red)
1074 9 10 (face hydra-face-blue))))))
1075 (defun hydra-zoom/body nil "Create a hydra with no body and the heads:
1076
1077 \"r\": `(text-scale-set 0)',
1078 \"0\": `(text-scale-set 0)',
1079 \"1\": `(text-scale-set 0)'
1080
1081 The body can be accessed via `hydra-zoom/body'."
1082 (interactive)
1083 (hydra-disable)
1084 (catch (quote hydra-disable)
1085 (when hydra-is-helpful (hydra-zoom/hint))
1086 (setq hydra-last
1087 (hydra-set-transient-map
1088 (setq hydra-curr-map
1089 (quote (keymap (7 . hydra-keyboard-quit)
1090 (114 . hydra-zoom/lambda-r)
1091 (switch-frame . hydra--handle-switch-frame)
1092 (kp-subtract . hydra--negative-argument)
1093 (kp-9 . hydra--digit-argument)
1094 (kp-8 . hydra--digit-argument)
1095 (kp-7 . hydra--digit-argument)
1096 (kp-6 . hydra--digit-argument)
1097 (kp-5 . hydra--digit-argument)
1098 (kp-4 . hydra--digit-argument)
1099 (kp-3 . hydra--digit-argument)
1100 (kp-2 . hydra--digit-argument)
1101 (kp-1 . hydra--digit-argument)
1102 (kp-0 . hydra--digit-argument)
1103 (57 . hydra--digit-argument)
1104 (56 . hydra--digit-argument)
1105 (55 . hydra--digit-argument)
1106 (54 . hydra--digit-argument)
1107 (53 . hydra--digit-argument)
1108 (52 . hydra--digit-argument)
1109 (51 . hydra--digit-argument)
1110 (50 . hydra--digit-argument)
1111 (49 . hydra-zoom/lambda-r)
1112 (48 . hydra-zoom/lambda-0-and-exit)
1113 (45 . hydra--negative-argument)
1114 (21 . hydra--universal-argument))))
1115 t (lambda nil (hydra-cleanup))))
1116 (setq prefix-arg current-prefix-arg)))))))
1117
1118 (ert-deftest hydra--pad ()
1119 (should (equal (hydra--pad '(a b c) 3)
1120 '(a b c)))
1121 (should (equal (hydra--pad '(a) 3)
1122 '(a nil nil))))
1123
1124 (ert-deftest hydra--matrix ()
1125 (should (equal (hydra--matrix '(a b c) 2 2)
1126 '((a b) (c nil))))
1127 (should (equal (hydra--matrix '(a b c d e f g h i) 4 3)
1128 '((a b c d) (e f g h) (i nil nil nil)))))
1129
1130 (ert-deftest hydra--cell ()
1131 (should (equal (hydra--cell "% -75s %%`%s" '(hydra-lv hydra-verbose))
1132 "When non-nil, `lv-message' (not `message') will be used to display hints. %`hydra-lv^^^^^
1133 When non-nil, hydra will issue some non essential style warnings. %`hydra-verbose")))
1134
1135 (ert-deftest hydra--vconcat ()
1136 (should (equal (hydra--vconcat '("abc\ndef" "012\n34" "def\nabc"))
1137 "abc012def\ndef34abc")))
1138
1139 (defhydradio hydra-tng ()
1140 (picard "_p_ Captain Jean Luc Picard:")
1141 (riker "_r_ Commander William Riker:")
1142 (data "_d_ Lieutenant Commander Data:")
1143 (worf "_w_ Worf:")
1144 (la-forge "_f_ Geordi La Forge:")
1145 (troi "_t_ Deanna Troi:")
1146 (dr-crusher "_c_ Doctor Beverly Crusher:")
1147 (phaser "_h_ Set phasers to " [stun kill]))
1148
1149 (ert-deftest hydra--table ()
1150 (let ((hydra-cell-format "% -30s %% -8`%s"))
1151 (should (equal (hydra--table hydra-tng/names 5 2)
1152 (substring "
1153 _p_ Captain Jean Luc Picard: % -8`hydra-tng/picard^^ _t_ Deanna Troi: % -8`hydra-tng/troi^^^^^^
1154 _r_ Commander William Riker: % -8`hydra-tng/riker^^^ _c_ Doctor Beverly Crusher: % -8`hydra-tng/dr-crusher
1155 _d_ Lieutenant Commander Data: % -8`hydra-tng/data^^^^ _h_ Set phasers to % -8`hydra-tng/phaser^^^^
1156 _w_ Worf: % -8`hydra-tng/worf^^^^
1157 _f_ Geordi La Forge: % -8`hydra-tng/la-forge" 1)))
1158 (should (equal (hydra--table hydra-tng/names 4 3)
1159 (substring "
1160 _p_ Captain Jean Luc Picard: % -8`hydra-tng/picard _f_ Geordi La Forge: % -8`hydra-tng/la-forge^^
1161 _r_ Commander William Riker: % -8`hydra-tng/riker^ _t_ Deanna Troi: % -8`hydra-tng/troi^^^^^^
1162 _d_ Lieutenant Commander Data: % -8`hydra-tng/data^^ _c_ Doctor Beverly Crusher: % -8`hydra-tng/dr-crusher
1163 _w_ Worf: % -8`hydra-tng/worf^^ _h_ Set phasers to % -8`hydra-tng/phaser^^^^" 1)))))
1164
1165 (provide 'hydra-test)
1166
1167 ;;; hydra-test.el ends here