emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] master da45e68 18/18: Merge commit '4a6a31d6d4d479720f4b66091892b


From: Oleh Krehel
Subject: [elpa] master da45e68 18/18: Merge commit '4a6a31d6d4d479720f4b66091892b0cda2377346' from hydra
Date: Sat, 28 Mar 2015 15:04:29 +0000

branch: master
commit da45e6864dabc213961d8c5727a99556d831a145
Merge: 059c3d5 4a6a31d
Author: Oleh Krehel <address@hidden>
Commit: Oleh Krehel <address@hidden>

    Merge commit '4a6a31d6d4d479720f4b66091892b0cda2377346' from hydra
---
 packages/hydra/hydra-examples.el |    8 +-
 packages/hydra/hydra-test.el     |  119 +++++++++++++++---
 packages/hydra/hydra.el          |  249 +++++++++++++++++++------------------
 3 files changed, 231 insertions(+), 145 deletions(-)

diff --git a/packages/hydra/hydra-examples.el b/packages/hydra/hydra-examples.el
index 872814b..67aaffd 100644
--- a/packages/hydra/hydra-examples.el
+++ b/packages/hydra/hydra-examples.el
@@ -262,10 +262,10 @@ _v_ariable       _u_ser-option
                            :color pink
                            :post (deactivate-mark))
   "
-  ^_k_^     _d_elete    _s_tring     |\\     _,,,--,,_
-_h_   _l_   _o_k        _y_ank       /,`.-'`'   ._  \-;;,_
-  ^_j_^     _n_ew-copy  _r_eset     |,4-  ) )_   .;.(  `'-'
-^^^^        _e_xchange  _u_ndo     '---''(_/._)-'(_\_)
+  ^_k_^     _d_elete    _s_tring
+_h_   _l_   _o_k        _y_ank
+  ^_j_^     _n_ew-copy  _r_eset
+^^^^        _e_xchange  _u_ndo
 ^^^^        ^ ^         _p_aste
 "
   ("h" backward-char nil)
diff --git a/packages/hydra/hydra-test.el b/packages/hydra/hydra-test.el
index b908ac0..155c047 100644
--- a/packages/hydra/hydra-test.el
+++ b/packages/hydra/hydra-test.el
@@ -48,6 +48,7 @@ The body can be accessed via `hydra-error/body'.
 
 Call the head: `first-error'."
              (interactive)
+             (hydra-default-pre)
              (hydra-disable)
              (catch (quote hydra-disable)
                (condition-case err (prog1 t (call-interactively (function 
first-error)))
@@ -100,6 +101,7 @@ The body can be accessed via `hydra-error/body'.
 
 Call the head: `next-error'."
              (interactive)
+             (hydra-default-pre)
              (hydra-disable)
              (catch (quote hydra-disable)
                (condition-case err (prog1 t (call-interactively (function 
next-error)))
@@ -152,6 +154,7 @@ The body can be accessed via `hydra-error/body'.
 
 Call the head: `previous-error'."
              (interactive)
+             (hydra-default-pre)
              (hydra-disable)
              (catch (quote hydra-disable)
                (condition-case err (prog1 t (call-interactively (function 
previous-error)))
@@ -220,6 +223,7 @@ Call the head: `previous-error'."
 
 The body can be accessed via `hydra-error/body'."
              (interactive)
+             (hydra-default-pre)
              (hydra-disable)
              (catch (quote hydra-disable)
                (when hydra-is-helpful (hydra-error/hint))
@@ -269,7 +273,7 @@ The body can be accessed via `hydra-error/body'."
        ("a" abbrev-mode "abbrev")
        ("q" nil "cancel")))
     '(progn
-      (defun hydra-toggle/toggle-truncate-lines nil "Create a hydra with no 
body and the heads:
+      (defun hydra-toggle/toggle-truncate-lines-and-exit nil "Create a hydra 
with no body and the heads:
 
 \"t\":    `toggle-truncate-lines',
 \"f\":    `auto-fill-mode',
@@ -280,11 +284,12 @@ The body can be accessed via `hydra-toggle/body'.
 
 Call the head: `toggle-truncate-lines'."
              (interactive)
+             (hydra-default-pre)
              (hydra-disable)
              (hydra-cleanup)
              (catch (quote hydra-disable)
                (call-interactively (function toggle-truncate-lines))))
-      (defun hydra-toggle/auto-fill-mode nil "Create a hydra with no body and 
the heads:
+      (defun hydra-toggle/auto-fill-mode-and-exit nil "Create a hydra with no 
body and the heads:
 
 \"t\":    `toggle-truncate-lines',
 \"f\":    `auto-fill-mode',
@@ -295,11 +300,12 @@ The body can be accessed via `hydra-toggle/body'.
 
 Call the head: `auto-fill-mode'."
              (interactive)
+             (hydra-default-pre)
              (hydra-disable)
              (hydra-cleanup)
              (catch (quote hydra-disable)
                (call-interactively (function auto-fill-mode))))
-      (defun hydra-toggle/abbrev-mode nil "Create a hydra with no body and the 
heads:
+      (defun hydra-toggle/abbrev-mode-and-exit nil "Create a hydra with no 
body and the heads:
 
 \"t\":    `toggle-truncate-lines',
 \"f\":    `auto-fill-mode',
@@ -310,6 +316,7 @@ The body can be accessed via `hydra-toggle/body'.
 
 Call the head: `abbrev-mode'."
              (interactive)
+             (hydra-default-pre)
              (hydra-disable)
              (hydra-cleanup)
              (catch (quote hydra-disable)
@@ -325,6 +332,7 @@ The body can be accessed via `hydra-toggle/body'.
 
 Call the head: `nil'."
              (interactive)
+             (hydra-default-pre)
              (hydra-disable)
              (hydra-cleanup)
              (catch (quote hydra-disable)))
@@ -346,6 +354,7 @@ Call the head: `nil'."
 
 The body can be accessed via `hydra-toggle/body'."
              (interactive)
+             (hydra-default-pre)
              (hydra-disable)
              (catch (quote hydra-disable)
                (when hydra-is-helpful (hydra-toggle/hint))
@@ -354,9 +363,9 @@ The body can be accessed via `hydra-toggle/body'."
                       (setq hydra-curr-map
                             (quote (keymap (7 . hydra-keyboard-quit)
                                            (113 . hydra-toggle/nil)
-                                           (97 . hydra-toggle/abbrev-mode)
-                                           (102 . hydra-toggle/auto-fill-mode)
-                                           (116 . 
hydra-toggle/toggle-truncate-lines)
+                                           (97 . 
hydra-toggle/abbrev-mode-and-exit)
+                                           (102 . 
hydra-toggle/auto-fill-mode-and-exit)
+                                           (116 . 
hydra-toggle/toggle-truncate-lines-and-exit)
                                            (switch-frame . 
hydra--handle-switch-frame)
                                            (kp-subtract . 
hydra--negative-argument)
                                            (kp-9 . hydra--digit-argument)
@@ -399,7 +408,7 @@ The body can be accessed via `hydra-toggle/body'."
        ("k" previous-line)
        ("q" nil "quit")))
     '(progn
-      (defun hydra-vi/hydra-keyboard-quit nil "Create a hydra with no body and 
the heads:
+      (defun hydra-vi/hydra-keyboard-quit-and-exit nil "Create a hydra with no 
body and the heads:
 
 \"\":    `hydra-keyboard-quit',
 \"j\":    `next-line',
@@ -410,6 +419,7 @@ The body can be accessed via `hydra-vi/body'.
 
 Call the head: `hydra-keyboard-quit'."
              (interactive)
+             (hydra-default-pre)
              (set-cursor-color "#e52b50")
              (hydra-disable)
              (hydra-cleanup)
@@ -427,6 +437,7 @@ The body can be accessed via `hydra-vi/body'.
 
 Call the head: `next-line'."
              (interactive)
+             (hydra-default-pre)
              (set-cursor-color "#e52b50")
              (hydra-disable)
              (catch (quote hydra-disable)
@@ -447,7 +458,7 @@ Call the head: `next-line'."
                                            (113 . hydra-vi/nil)
                                            (107 . hydra-vi/previous-line)
                                            (106 . hydra-vi/next-line)
-                                           (7 . hydra-vi/hydra-keyboard-quit)
+                                           (7 . 
hydra-vi/hydra-keyboard-quit-and-exit)
                                            (switch-frame . 
hydra--handle-switch-frame)
                                            (kp-subtract . 
hydra--negative-argument)
                                            (kp-9 . hydra--digit-argument)
@@ -484,6 +495,7 @@ The body can be accessed via `hydra-vi/body'.
 
 Call the head: `previous-line'."
              (interactive)
+             (hydra-default-pre)
              (set-cursor-color "#e52b50")
              (hydra-disable)
              (catch (quote hydra-disable)
@@ -504,7 +516,7 @@ Call the head: `previous-line'."
                                            (113 . hydra-vi/nil)
                                            (107 . hydra-vi/previous-line)
                                            (106 . hydra-vi/next-line)
-                                           (7 . hydra-vi/hydra-keyboard-quit)
+                                           (7 . 
hydra-vi/hydra-keyboard-quit-and-exit)
                                            (switch-frame . 
hydra--handle-switch-frame)
                                            (kp-subtract . 
hydra--negative-argument)
                                            (kp-9 . hydra--digit-argument)
@@ -541,6 +553,7 @@ The body can be accessed via `hydra-vi/body'.
 
 Call the head: `nil'."
              (interactive)
+             (hydra-default-pre)
              (set-cursor-color "#e52b50")
              (hydra-disable)
              (hydra-cleanup)
@@ -562,6 +575,7 @@ Call the head: `nil'."
 
 The body can be accessed via `hydra-vi/body'."
              (interactive)
+             (hydra-default-pre)
              (set-cursor-color "#e52b50")
              (hydra-disable)
              (catch (quote hydra-disable)
@@ -577,7 +591,7 @@ The body can be accessed via `hydra-vi/body'."
                                            (113 . hydra-vi/nil)
                                            (107 . hydra-vi/previous-line)
                                            (106 . hydra-vi/next-line)
-                                           (7 . hydra-vi/hydra-keyboard-quit)
+                                           (7 . 
hydra-vi/hydra-keyboard-quit-and-exit)
                                            (switch-frame . 
hydra--handle-switch-frame)
                                            (kp-subtract . 
hydra--negative-argument)
                                            (kp-9 . hydra--digit-argument)
@@ -705,7 +719,7 @@ The body can be accessed via `hydra-vi/body'."
        ("l" text-scale-decrease "out")
        ("q" nil "quit"))))))
 
-(ert-deftest hydra-format ()
+(ert-deftest hydra-format-1 ()
   (should (equal
            (let ((hydra-fontify-head-function
                   'hydra-fontify-head-greyscale))
@@ -728,7 +742,41 @@ _f_ auto-fill-mode:    %`auto-fill-function
 %s auto-fill-mode:    %S
 " "{a}" abbrev-mode "{d}" debug-on-error "{f}" auto-fill-function) "[[q]]: 
quit"))))
 
-(ert-deftest hydra-format-with-sexp ()
+(ert-deftest hydra-format-2 ()
+  (should (equal
+           (let ((hydra-fontify-head-function
+                  'hydra-fontify-head-greyscale))
+             (hydra--format
+              'bar
+              nil
+              "\n  bar %s`foo\n"
+              '(("a" (quote t) "" :cmd-name bar/lambda-a)
+                ("q" nil "" :cmd-name bar/nil))))
+           '(concat (format "  bar %s\n" foo) "{a}, [q]"))))
+
+(ert-deftest hydra-format-3 ()
+  (should (equal
+           (let ((hydra-fontify-head-function
+                  'hydra-fontify-head-greyscale))
+             (hydra--format
+              'bar
+              nil
+              "\n_<SPC>_   ^^ace jump\n"
+              '(("<SPC>" ace-jump-char-mode nil :cmd-name 
bar/ace-jump-char-mode))))
+           '(concat (format "%s   ace jump\n" "{<SPC>}") ""))))
+
+(ert-deftest hydra-format-4 ()
+  (should
+   (equal (hydra--format
+           nil
+           '(nil nil :hint nil)
+           "\n_j_,_k_"
+           '(("j" nil) ("k" nil)))
+          '(concat (format "%s,%s"
+                    #("j" 0 1 (face hydra-face-blue))
+                    #("k" 0 1 (face hydra-face-blue))) ""))))
+
+(ert-deftest hydra-format-with-sexp-1 ()
   (should (equal
            (let ((hydra-fontify-head-function
                   'hydra-fontify-head-greyscale))
@@ -743,6 +791,21 @@ _f_ auto-fill-mode:    %`auto-fill-function
                        (buffer-narrowed-p)))
              "[[q]]: cancel"))))
 
+(ert-deftest hydra-format-with-sexp-2 ()
+  (should (equal
+           (let ((hydra-fontify-head-function
+                  'hydra-fontify-head-greyscale))
+             (hydra--format
+              'hydra-toggle nil
+              "\n_n_ narrow-or-widen-dwim %s(progn (message 
\"checking\")(buffer-narrowed-p))asdf\n"
+              '(("n" narrow-to-region nil) ("q" nil "cancel"))))
+           '(concat (format "%s narrow-or-widen-dwim %sasdf\n"
+                     "{n}"
+                     (progn
+                       (message "checking")
+                       (buffer-narrowed-p)))
+             "[[q]]: cancel"))))
+
 (ert-deftest hydra-compat-colors-1 ()
   (should (equal (hydra--head-color
                   '("e" (message "Exiting now") "blue")
@@ -757,6 +820,10 @@ _f_ auto-fill-mode:    %`auto-fill-function
                   '(nil nil :exit t))
                  'blue))
   (should (equal (hydra--head-color
+                  '("j" next-line "" :exit t)
+                  '(nil nil))
+                 'blue))
+  (should (equal (hydra--head-color
                   '("c" (message "Continuing") "red" :exit nil)
                   '(nil nil :exit t))
                  'red))
@@ -849,6 +916,7 @@ The body can be accessed via `hydra-zoom/body'.
 
 Call the head: `(text-scale-set 0)'."
              (interactive)
+             (hydra-default-pre)
              (hydra-disable)
              (catch (quote hydra-disable)
                (condition-case err (prog1 t (call-interactively (function 
(lambda nil (interactive)
@@ -883,12 +951,12 @@ Call the head: `(text-scale-set 0)'."
                                            (52 . hydra--digit-argument)
                                            (51 . hydra--digit-argument)
                                            (50 . hydra--digit-argument)
-                                           (49 . hydra-zoom/lambda-0)
-                                           (48 . hydra-zoom/lambda-0)
+                                           (49 . hydra-zoom/lambda-0-and-exit)
+                                           (48 . hydra-zoom/lambda-0-and-exit)
                                            (45 . hydra--negative-argument)
                                            (21 . hydra--universal-argument))))
                       t (lambda nil (hydra-cleanup))))))
-      (defun hydra-zoom/lambda-0 nil "Create a hydra with no body and the 
heads:
+      (defun hydra-zoom/lambda-0-and-exit nil "Create a hydra with no body and 
the heads:
 
 \"r\":    `(text-scale-set 0)',
 \"0\":    `(text-scale-set 0)',
@@ -898,6 +966,7 @@ The body can be accessed via `hydra-zoom/body'.
 
 Call the head: `(text-scale-set 0)'."
              (interactive)
+             (hydra-default-pre)
              (hydra-disable)
              (hydra-cleanup)
              (catch (quote hydra-disable)
@@ -916,6 +985,7 @@ Call the head: `(text-scale-set 0)'."
 
 The body can be accessed via `hydra-zoom/body'."
              (interactive)
+             (hydra-default-pre)
              (hydra-disable)
              (catch (quote hydra-disable)
                (when hydra-is-helpful (hydra-zoom/hint))
@@ -944,8 +1014,8 @@ The body can be accessed via `hydra-zoom/body'."
                                            (52 . hydra--digit-argument)
                                            (51 . hydra--digit-argument)
                                            (50 . hydra--digit-argument)
-                                           (49 . hydra-zoom/lambda-0)
-                                           (48 . hydra-zoom/lambda-0)
+                                           (49 . hydra-zoom/lambda-0-and-exit)
+                                           (48 . hydra-zoom/lambda-0-and-exit)
                                            (45 . hydra--negative-argument)
                                            (21 . hydra--universal-argument))))
                       t (lambda nil (hydra-cleanup))))
@@ -971,6 +1041,7 @@ The body can be accessed via `hydra-zoom/body'.
 
 Call the head: `(text-scale-set 0)'."
              (interactive)
+             (hydra-default-pre)
              (hydra-disable)
              (catch (quote hydra-disable)
                (condition-case err (prog1 t (call-interactively (function 
(lambda nil (interactive)
@@ -1006,11 +1077,11 @@ Call the head: `(text-scale-set 0)'."
                                            (51 . hydra--digit-argument)
                                            (50 . hydra--digit-argument)
                                            (49 . hydra-zoom/lambda-r)
-                                           (48 . hydra-zoom/lambda-0)
+                                           (48 . hydra-zoom/lambda-0-and-exit)
                                            (45 . hydra--negative-argument)
                                            (21 . hydra--universal-argument))))
                       t (lambda nil (hydra-cleanup))))))
-      (defun hydra-zoom/lambda-0 nil "Create a hydra with no body and the 
heads:
+      (defun hydra-zoom/lambda-0-and-exit nil "Create a hydra with no body and 
the heads:
 
 \"r\":    `(text-scale-set 0)',
 \"0\":    `(text-scale-set 0)',
@@ -1020,6 +1091,7 @@ The body can be accessed via `hydra-zoom/body'.
 
 Call the head: `(text-scale-set 0)'."
              (interactive)
+             (hydra-default-pre)
              (hydra-disable)
              (hydra-cleanup)
              (catch (quote hydra-disable)
@@ -1038,6 +1110,7 @@ Call the head: `(text-scale-set 0)'."
 
 The body can be accessed via `hydra-zoom/body'."
              (interactive)
+             (hydra-default-pre)
              (hydra-disable)
              (catch (quote hydra-disable)
                (when hydra-is-helpful (hydra-zoom/hint))
@@ -1067,7 +1140,7 @@ The body can be accessed via `hydra-zoom/body'."
                                            (51 . hydra--digit-argument)
                                            (50 . hydra--digit-argument)
                                            (49 . hydra-zoom/lambda-r)
-                                           (48 . hydra-zoom/lambda-0)
+                                           (48 . hydra-zoom/lambda-0-and-exit)
                                            (45 . hydra--negative-argument)
                                            (21 . hydra--universal-argument))))
                       t (lambda nil (hydra-cleanup))))
@@ -1120,6 +1193,12 @@ _r_ Commander William Riker:   % -8`hydra-tng/riker^    
_t_ Deanna Troi:
 _d_ Lieutenant Commander Data: % -8`hydra-tng/data^^    _c_ Doctor Beverly 
Crusher:    % -8`hydra-tng/dr-crusher
 _w_ Worf:                      % -8`hydra-tng/worf^^    _h_ Set phasers to     
        % -8`hydra-tng/phaser^^^^" 1)))))
 
+(ert-deftest hydra--make-funcall ()
+  (should (equal (let ((body-pre 'foo))
+                   (hydra--make-funcall body-pre)
+                   body-pre)
+                 '(funcall (function foo)))))
+
 (provide 'hydra-test)
 
 ;;; hydra-test.el ends here
diff --git a/packages/hydra/hydra.el b/packages/hydra/hydra.el
index a3e8b9b..18233af 100644
--- a/packages/hydra/hydra.el
+++ b/packages/hydra/hydra.el
@@ -1,11 +1,11 @@
-;;; hydra.el --- Make bindings that stick around
+;;; hydra.el --- Make bindings that stick around. -*- lexical-binding: t -*-
 
 ;; Copyright (C) 2015  Free Software Foundation, Inc.
 
 ;; Author: Oleh Krehel <address@hidden>
 ;; Maintainer: Oleh Krehel <address@hidden>
 ;; URL: https://github.com/abo-abo/hydra
-;; Version: 0.11.0
+;; Version: 0.12.1
 ;; Keywords: bindings
 ;; Package-Requires: ((cl-lib "0.5"))
 
@@ -82,7 +82,7 @@
 (defalias 'hydra-set-transient-map
     (if (fboundp 'set-transient-map)
         'set-transient-map
-      (lambda (map keep-pred &optional on-exit)
+      (lambda (map _keep-pred &optional on-exit)
         (with-no-warnings
           (set-temporary-overlay-map map (hydra--pred on-exit))))))
 
@@ -197,7 +197,7 @@ Vanquishable only through a blue head.")
   "Keymap of the current Hydra called.")
 
 (defun hydra--handle-switch-frame (evt)
-  "Quit hydra and call old switch-frame event handler."
+  "Quit hydra and call old switch-frame event handler for EVT."
   (interactive "e")
   (hydra-keyboard-quit)
   (funcall (lookup-key (current-global-map) [switch-frame]) evt))
@@ -230,12 +230,15 @@ Vanquishable only through a blue head.")
 (defvar hydra-repeat--command nil
   "Command to use with `hydra-repeat'.")
 
-(defun hydra-repeat ()
-  "Repeat last command with last prefix arg."
-  (interactive)
-  (unless (string-match "hydra-repeat$" (symbol-name last-command))
-    (setq hydra-repeat--command last-command)
-    (setq hydra-repeat--prefix-arg (or last-prefix-arg 1)))
+(defun hydra-repeat (&optional arg)
+  "Repeat last command with last prefix arg.
+When ARG is non-nil, use that instead."
+  (interactive "p")
+  (if (eq arg 1)
+      (unless (string-match "hydra-repeat$" (symbol-name last-command))
+        (setq hydra-repeat--command last-command)
+        (setq hydra-repeat--prefix-arg last-prefix-arg))
+    (setq hydra-repeat--prefix-arg arg))
   (setq current-prefix-arg hydra-repeat--prefix-arg)
   (funcall hydra-repeat--command))
 
@@ -321,26 +324,25 @@ Return DEFAULT if PROP is not in H."
                    'blue))
                 (t
                  (error "Unknown :exit %S" exit)))))
-    (let ((body-exit (plist-get (cddr body) :exit)))
-      (cond ((null (cadr h))
-             (when head-color
-               (hydra--complain
-                "Doubly specified blue head - nil cmd is already blue: %S" h))
-             'blue)
-            ((null head-color)
-             (hydra--body-color body))
-            ((null foreign-keys)
-             head-color)
-            ((eq foreign-keys 'run)
-             (if (eq head-color 'red)
-                 'pink
-               'blue))
-            ((eq foreign-keys 'warn)
-             (if (memq head-color '(red amaranth))
-                 'amaranth
-               'teal))
-            (t
-             (error "Unexpected %S %S" h body))))))
+    (cond ((null (cadr h))
+           (when head-color
+             (hydra--complain
+              "Doubly specified blue head - nil cmd is already blue: %S" h))
+           'blue)
+          ((null head-color)
+           (hydra--body-color body))
+          ((null foreign-keys)
+           head-color)
+          ((eq foreign-keys 'run)
+           (if (eq head-color 'red)
+               'pink
+             'blue))
+          ((eq foreign-keys 'warn)
+           (if (memq head-color '(red amaranth))
+               'amaranth
+             'teal))
+          (t
+           (error "Unexpected %S %S" h body)))))
 
 (defun hydra--body-foreign-keys (body)
   "Return what BODY does with a non-head binding."
@@ -374,8 +376,21 @@ BODY is the second argument to `defhydra'"
     (teal 'hydra-face-teal)
     (t (error "Unknown color for %S" h))))
 
+(defvar hydra--input-method-function nil
+  "Store overridden `input-method-function' here.")
+
+(defun hydra-default-pre ()
+  "Default setup that happens in each head before :pre."
+  (when (eq input-method-function 'key-chord-input-method)
+    (unless hydra--input-method-function
+      (setq hydra--input-method-function input-method-function)
+      (setq input-method-function nil))))
+
 (defun hydra-cleanup ()
   "Clean up after a Hydra."
+  (when hydra--input-method-function
+    (setq input-method-function hydra--input-method-function)
+    (setq hydra--input-method-function nil))
   (when (window-live-p lv-wnd)
     (let ((buf (window-buffer lv-wnd)))
       (delete-window lv-wnd)
@@ -420,9 +435,9 @@ Otherwise, add PREFIX to the symbol name."
         sym
       (intern (concat prefix "/" str)))))
 
-(defun hydra--hint (name body docstring heads)
+(defun hydra--hint (body heads)
   "Generate a hint for the echo area.
-NAME, BODY, DOCSTRING and HEADS are parameters to `defhydra'."
+BODY, and HEADS are parameters to `defhydra'."
   (let (alist)
     (dolist (h heads)
       (let ((val (assoc (cadr h) alist))
@@ -467,21 +482,19 @@ HEAD's binding is returned as a string wrapped with [] or 
{}."
   (funcall (or hydra-fontify-head-function 'hydra-fontify-head-default)
            head body))
 
-(defun hydra--format (name body docstring heads)
+(defun hydra--format (_name body docstring heads)
   "Generate a `format' statement from STR.
 \"%`...\" expressions are extracted into \"%S\".
-NAME, BODY, DOCSTRING and HEADS are parameters of `defhydra'.
+_NAME, BODY, DOCSTRING and HEADS are parameters of `defhydra'.
 The expressions can be auto-expanded according to NAME."
   (setq docstring (replace-regexp-in-string "\\^" "" docstring))
-  (let ((rest (hydra--hint name body docstring heads))
-        (body-color (hydra--body-color body))
-        (prefix (symbol-name name))
+  (let ((rest (hydra--hint body heads))
         (start 0)
         varlist
         offset)
     (while (setq start
                  (string-match
-                  "\\(?:%\\( 
?-?[0-9]*s?\\)\\(`[a-z-A-Z/0-9]+\\|(\\)\\)\\|\\(?:_\\( 
?-?[0-9]*\\)\\([a-z-~A-Z;:0-9/|?<>={}]+\\)_\\)"
+                  "\\(?:%\\( 
?-?[0-9]*s?\\)\\(`[a-z-A-Z/0-9]+\\|(\\)\\)\\|\\(?:_\\( 
?-?[0-9]*\\)\\([a-z-A-Z~.,;:0-9/|?<>={}]+\\)_\\)"
                   docstring start))
       (cond ((eq ?_ (aref (match-string 0 docstring) 0))
              (let* ((key (match-string 4 docstring))
@@ -494,25 +507,17 @@ The expressions can be auto-expanded according to NAME."
                             (or
                              hydra-key-format-spec
                              (concat "%" (match-string 3 docstring) "s"))
-                            nil nil docstring)))
+                            t nil docstring)))
                  (error "Unrecognized key: _%s_" key))))
 
-            ((eq ?` (aref (match-string 2 docstring) 0))
-             (push (hydra--unalias-var
-                    (substring (match-string 2 docstring) 1) prefix)
-                   varlist)
-             (setq docstring
-                   (replace-match
-                    (concat "%" (match-string 1 docstring) "S")
-                    nil nil docstring 0)))
-
             (t
-             (let* ((spec (match-string 1 docstring))
-                    (lspec (length spec))
-                    (me2 (match-end 2)))
+             (let* ((varp (if (eq ?` (aref (match-string 2 docstring) 0)) 1 0))
+                    (spec (match-string 1 docstring))
+                    (lspec (length spec)))
                (setq offset
                      (with-temp-buffer
-                       (insert (substring docstring (+ 1 start (length spec))))
+                       (insert (substring docstring (+ 1 start varp
+                                                       (length spec))))
                        (goto-char (point-min))
                        (push (read (current-buffer)) varlist)
                        (- (point) (point-min))))
@@ -523,7 +528,7 @@ The expressions can be auto-expanded according to NAME."
                      (concat
                       (substring docstring 0 start)
                       "%" spec
-                      (substring docstring (+ me2 offset -1))))))))
+                      (substring docstring (+ start offset 1 lspec varp))))))))
     (if (eq ?\n (aref docstring 0))
         `(concat (format ,(substring docstring 1) ,@(nreverse varlist))
                  ,rest)
@@ -567,7 +572,7 @@ DOC was generated with `hydra--doc'.
 HEAD is one of the HEADS passed to `defhydra'.
 BODY-PRE and BODY-POST are pre-processed in `defhydra'.
 OTHER-POST is an optional extension to the :post key of BODY."
-  (let ((name (hydra--head-name head name))
+  (let ((name (hydra--head-name head name body))
         (cmd (when (car head)
                (hydra--make-callable
                 (cadr head))))
@@ -582,6 +587,7 @@ OTHER-POST is an optional extension to the :post key of 
BODY."
     `(defun ,name ()
        ,doc
        (interactive)
+       (hydra-default-pre)
        ,@(when body-pre (list body-pre))
        (hydra-disable)
        ,@(when (memq color '(blue teal)) '((hydra-cleanup)))
@@ -658,8 +664,7 @@ NAME, BODY and HEADS are parameters to `defhydra'."
   (let ((body-color (hydra--body-color body))
         (body-post (plist-get (cddr body) :post)))
     (if body-post
-        (when (symbolp body-post)
-          (setq body-post `(funcall #',body-post)))
+        (hydra--make-funcall body-post)
       (when hydra-keyboard-quit
         (define-key keymap hydra-keyboard-quit #'hydra-keyboard-quit)))
     (when (memq body-color '(amaranth pink teal))
@@ -690,12 +695,16 @@ NAME, BODY and HEADS are parameters to `defhydra'."
            "An %S Hydra must have at least one blue head in order to exit"
            body-color))))))
 
-(defun hydra--head-name (h body-name)
-  "Return the symbol for head H of body BODY-NAME."
-  (intern (format "%S/%s" body-name
-                  (if (symbolp (cadr h))
-                      (cadr h)
-                    (concat "lambda-" (car h))))))
+(defun hydra--head-name (h name body)
+  "Return the symbol for head H of hydra with NAME and BODY."
+  (let ((str (format "%S/%s" name
+                     (if (symbolp (cadr h))
+                         (cadr h)
+                       (concat "lambda-" (car h))))))
+    (when (and (memq (hydra--head-color h body) '(blue teal))
+               (not (memq (cadr h) '(body nil))))
+      (setq str (concat str "-and-exit")))
+    (intern str)))
 
 (defun hydra--delete-duplicates (heads)
   "Return HEADS without entries that have the same CMD part.
@@ -726,7 +735,7 @@ In duplicate HEADS, :cmd-name is modified to whatever they 
duplicate."
 The matrix size is ROWS times COLS."
   (let ((ls (copy-sequence lst))
         res)
-    (dotimes (c cols)
+    (dotimes (_c cols)
       (push (hydra--pad (hydra-multipop ls rows) rows) res))
     (nreverse res)))
 
@@ -801,7 +810,7 @@ NAMES should be defined by `defhydradio' or similar."
   "Timer for `hydra-timeout'.")
 
 (defun hydra-timeout (secs &optional function)
-  "In SECS seconds call FUNCTION, then `hydra-keyboard-quit'.
+  "In SECS seconds call FUNCTION, then function `hydra-keyboard-quit'.
 Cancel the previous `hydra-timeout'."
   (cancel-timer hydra-timer)
   (setq hydra-timer (timer-create))
@@ -816,7 +825,6 @@ Cancel the previous `hydra-timeout'."
   (timer-activate hydra-timer))
 
 ;;* Macros
-;;** defhydra
 ;;;###autoload
 (defmacro defhydra (name body &optional docstring &rest heads)
   "Create a Hydra - a family of functions with prefix NAME.
@@ -826,10 +834,11 @@ defined here.
 
 BODY has the format:
 
-    (BODY-MAP BODY-KEY &rest PLIST)
+    (BODY-MAP BODY-KEY &rest BODY-PLIST)
 
 DOCSTRING will be displayed in the echo area to identify the
-Hydra.
+Hydra.  When DOCSTRING starts with a newline, special Ruby-style
+substitution will be performed by `hydra--format'.
 
 Functions are created on basis of HEADS, each of which has the
 format:
@@ -840,7 +849,7 @@ BODY-MAP is a keymap; `global-map' is used quite often.  
Each
 function generated from HEADS will be bound in BODY-MAP to
 BODY-KEY + KEY (both are strings passed to `kbd'), and will set
 the transient map so that all following heads can be called
-though KEY only.
+though KEY only. BODY-KEY can be an empty string.
 
 CMD is a callable expression: either an interactive function
 name, or an interactive lambda, or a single sexp (it will be
@@ -851,18 +860,16 @@ printed beside KEY in the echo erea if `hydra-is-helpful' 
is not
 nil.  If you don't even want the KEY to be printed, set HINT
 explicitly to nil.
 
-The heads inherit their PLIST from the body and are allowed to
-override each key.  The keys recognized are :color and :bind.
-:color can be:
+The heads inherit their PLIST from BODY-PLIST and are allowed to
+override some keys.  The keys recognized are :exit and :bind.
+:exit can be:
 
-- red (default): this head will continue the Hydra state.
-- blue: this head will stop the Hydra state.
-- amaranth (applies to body only): similar to red, but no binding
-except a blue head can stop the Hydra state.
+- nil (default): this head will continue the Hydra state.
+- t: this head will stop the Hydra state.
 
 :bind can be:
 - nil: this head will not be bound in BODY-MAP.
-- a lambda taking KEY and CMD used to bind a head
+- a lambda taking KEY and CMD used to bind a head.
 
 It is possible to omit both BODY-MAP and BODY-KEY if you don't
 want to bind anything.  In that case, typically you will bind the
@@ -878,38 +885,40 @@ result of `defhydra'."
          (setq docstring "hydra")))
   (when (keywordp (car body))
     (setq body (cons nil (cons nil body))))
-  (let ((keymap (copy-keymap hydra-base-map))
-        (body-name (intern (format "%S/body" name)))
-        (body-key (cadr body))
-        (body-color (hydra--body-color body))
-        (body-pre (plist-get (cddr body) :pre))
-        (body-body-pre (plist-get (cddr body) :body-pre))
-        (body-post (plist-get (cddr body) :post))
-        (method (or (plist-get body :bind)
-                    (car body))))
+  (let* ((keymap (copy-keymap hydra-base-map))
+         (body-name (intern (format "%S/body" name)))
+         (body-key (cadr body))
+         (body-plist (cddr body))
+         (body-map (or (car body)
+                       (plist-get body-plist :bind)))
+         (body-pre (plist-get body-plist :pre))
+         (body-body-pre (plist-get body-plist :body-pre))
+         (body-post (plist-get body-plist :post)))
+    (hydra--make-funcall body-post)
     (when body-post
-      (when (symbolp body-post)
-        (setq body-post `(funcall #',body-post)))
       (setq heads (cons (list hydra-keyboard-quit #'hydra-keyboard-quit nil 
:exit t)
                         heads)))
     (dolist (h heads)
-      (let ((len (length h))
-            (cmd-name (hydra--head-name h name)))
+      (let ((len (length h)))
         (cond ((< len 2)
                (error "Each head should have at least two items: %S" h))
               ((= len 2)
                (setcdr (cdr h)
                        (list
-                        (hydra-plist-get-default (cddr body) :hint "")
-                        :cmd-name cmd-name)))
+                        (hydra-plist-get-default body-plist :hint "")))
+               (setcdr (nthcdr 2 h)
+                       (list :cmd-name (hydra--head-name h name body))))
               (t
                (let ((hint (cl-caddr h)))
                  (unless (or (null hint)
                              (stringp hint))
                    (setcdr (cdr h) (cons
-                                    (hydra-plist-get-default (cddr body) :hint 
"")
+                                    (hydra-plist-get-default body-plist :hint 
"")
                                     (cddr h))))
-                 (setcdr (cddr h) `(:cmd-name ,cmd-name ,@(cl-cdddr h))))))))
+                 (setcdr (cddr h)
+                         `(:cmd-name
+                           ,(hydra--head-name h name body)
+                           ,@(cl-cdddr h))))))))
     (let ((doc (hydra--doc body-key body-name heads))
           (heads-nodup (hydra--delete-duplicates heads)))
       (mapc
@@ -917,52 +926,45 @@ result of `defhydra'."
          (define-key keymap (kbd (car x))
            (plist-get (cl-cdddr x) :cmd-name)))
        heads)
-      (when (and body-pre (symbolp body-pre))
-        (setq body-pre `(funcall #',body-pre)))
-      (when (and body-body-pre (symbolp body-body-pre))
-        (setq body-body-pre `(funcall #',body-body-pre)))
+      (hydra--make-funcall body-pre)
+      (hydra--make-funcall body-body-pre)
       (hydra--handle-nonhead keymap name body heads)
       `(progn
+         ;; create defuns
          ,@(mapcar
             (lambda (head)
               (hydra--make-defun name body doc head keymap
                                  body-pre body-post))
             heads-nodup)
+         ;; free up keymap prefix
          ,@(unless (or (null body-key)
-                       (null method)
-                       (hydra--callablep method))
-                   `((unless (keymapp (lookup-key ,method (kbd ,body-key)))
-                       (define-key ,method (kbd ,body-key) nil))))
+                       (null body-map)
+                       (hydra--callablep body-map))
+                   `((unless (keymapp (lookup-key ,body-map (kbd ,body-key)))
+                       (define-key ,body-map (kbd ,body-key) nil))))
+         ;; bind keys
          ,@(delq nil
-                 (cl-mapcar
+                 (mapcar
                   (lambda (head)
                     (let ((name (hydra--head-property head :cmd-name)))
                       (when (and (cadr head)
                                  (not (eq (cadr head) 'hydra-keyboard-quit))
-                                 (or body-key method))
-                        (let ((bind (hydra--head-property head :bind 'default))
+                                 (or body-key body-map))
+                        (let ((bind (hydra--head-property head :bind body-map))
                               (final-key
                                (if body-key
                                    (vconcat (kbd body-key) (kbd (car head)))
                                  (kbd (car head)))))
                           (cond ((null bind) nil)
-
-                                ((eq bind 'default)
-                                 (list
-                                  (if (hydra--callablep method)
-                                      'funcall
-                                    'define-key)
-                                  method
-                                  final-key
-                                  (list 'function name)))
-
                                 ((hydra--callablep bind)
-                                 `(funcall (function ,bind)
-                                           ,final-key
-                                           (function ,name)))
-
+                                 `(funcall ,bind ,final-key (function ,name)))
+                                ((and (symbolp bind)
+                                      (if (boundp bind)
+                                          (keymapp (symbol-value bind))
+                                        t))
+                                 `(define-key ,bind ,final-key (function 
,name)))
                                 (t
-                                 (error "Invalid :bind property %S" head)))))))
+                                 (error "Invalid :bind property `%S' for head 
%S" bind  head)))))))
                   heads))
          (defun ,(intern (format "%S/hint" name)) ()
            ,(hydra--message name body docstring heads))
@@ -972,9 +974,14 @@ result of `defhydra'."
            (or body-body-pre body-pre) body-post
            '(setq prefix-arg current-prefix-arg))))))
 
-(defmacro defhydradio (name body &rest heads)
+(defmacro hydra--make-funcall (sym)
+  "Transform SYM into a `funcall' that calls it."
+  `(when (and ,sym (symbolp ,sym))
+     (setq ,sym `(funcall #',,sym))))
+
+(defmacro defhydradio (name _body &rest heads)
   "Create radios with prefix NAME.
-BODY specifies the options; there are none currently.
+_BODY specifies the options; there are none currently.
 HEADS have the format:
 
     (TOGGLE-NAME &optional VALUE DOC)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]