[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] master c049a33 16/72: Allow for Ruby-style Hydra docstrings
From: |
Oleh Krehel |
Subject: |
[elpa] master c049a33 16/72: Allow for Ruby-style Hydra docstrings |
Date: |
Fri, 06 Mar 2015 13:04:05 +0000 |
branch: master
commit c049a33c2c3b7ed949880943175d7e23d278bead
Author: Oleh Krehel <address@hidden>
Commit: Oleh Krehel <address@hidden>
Allow for Ruby-style Hydra docstrings
* hydra.el (hydra--unalias-var): New defun.
(hydra--format): New defun.
(hydra--message): Use `hydra-format' instead of a static string.
Update signature.
(defhydra): Add a warning the pink Hydras can't yet handle unbound
prefix, e.g. "C-x". Update arguments given to `hydra--message'.
* hydra-test.el: Update tests, only hint functions were slightly
affected.
Example of using the newfound functionality:
(defhydra hydra-toggle (:color pink)
"
_a_ abbrev-mode: %`abbrev-mode
_d_ debug-on-error: %`debug-on-error
_f_ auto-fill-mode: %`auto-fill-function
_g_ golden-ratio-mode: %`golden-ratio-mode
_t_ truncate-lines: %`truncate-lines
_w_ whitespace-mode: %`whitespace-mode
"
("a" abbrev-mode nil)
("d" toggle-debug-on-error nil)
("f" auto-fill-mode nil)
("g" golden-ratio-mode nil)
("t" toggle-truncate-lines nil)
("w" whitespace-mode nil)
("q" nil "cancel"))
(global-set-key (kbd "C-c C-v") 'hydra-toggle/body)
Here, "Foo %`abbrev-mode" becomes equivelent to:
(format "Foo %S" abbrev-mode).
And "_a_" becomes equivalent to:
(propertize "a" 'face 'hydra-face-pink).
The hints for all heads except "q" have been set to nil, since their
equivalent is already displayed in the docstring.
---
hydra-test.el | 30 ++++++++++++------
hydra.el | 96 +++++++++++++++++++++++++++++++++++++++++----------------
2 files changed, 89 insertions(+), 37 deletions(-)
diff --git a/hydra-test.el b/hydra-test.el
index 09eb6d0..429cf14 100644
--- a/hydra-test.el
+++ b/hydra-test.el
@@ -187,9 +187,12 @@ Call the head: `previous-error'."
(define-key global-map [134217831 107]
(function hydra-error/previous-error))
(defun hydra-error/hint nil
- (hydra--message #("error: [h]: first, [j]: next, [k]: prev." 8 9 (face
hydra-face-red)
- 20 21 (face hydra-face-red)
- 31 32 (face hydra-face-red))))
+ (if hydra-lv (lv-message (format #("error: [h]: first, [j]: next, [k]:
prev." 8 9 (face hydra-face-red)
+ 20 21 (face hydra-face-red)
+ 31 32 (face hydra-face-red))))
+ (message (format #("error: [h]: first, [j]: next, [k]: prev." 8 9
(face hydra-face-red)
+ 20 21 (face hydra-face-red)
+ 31 32 (face hydra-face-red))))))
(defun hydra-error/body nil "Create a hydra with a \"M-g\" body and the
heads:
\"h\": `first-error',
@@ -305,10 +308,14 @@ Call the head: `nil'."
(hydra-cleanup)
(catch (quote hydra-disable)))
(defun hydra-toggle/hint nil
- (hydra--message #("toggle: [t]: truncate, [f]: fill, [a]: abbrev, [q]:
cancel." 9 10 (face hydra-face-blue)
- 24 25 (face hydra-face-blue)
- 35 36 (face hydra-face-blue)
- 48 49 (face hydra-face-blue))))
+ (if hydra-lv (lv-message (format #("toggle: [t]: truncate, [f]: fill,
[a]: abbrev, [q]: cancel." 9 10 (face hydra-face-blue)
+ 24 25 (face hydra-face-blue)
+ 35 36 (face hydra-face-blue)
+ 48 49 (face hydra-face-blue))))
+ (message (format #("toggle: [t]: truncate, [f]: fill, [a]: abbrev,
[q]: cancel." 9 10 (face hydra-face-blue)
+ 24 25 (face hydra-face-blue)
+ 35 36 (face hydra-face-blue)
+ 48 49 (face hydra-face-blue))))))
(defun hydra-toggle/body nil "Create a hydra with no body and the heads:
\"t\": `toggle-truncate-lines',
@@ -503,9 +510,12 @@ Call the head: `nil'."
(catch (quote hydra-disable)
(set-cursor-color "#ffffff")))
(defun hydra-vi/hint nil
- (hydra--message #("vi: j, k, [q]: quit." 4 5 (face
hydra-face-amaranth)
- 7 8 (face hydra-face-amaranth)
- 11 12 (face hydra-face-blue))))
+ (if hydra-lv (lv-message (format #("vi: j, k, [q]: quit." 4 5 (face
hydra-face-amaranth)
+ 7 8 (face hydra-face-amaranth)
+ 11 12 (face hydra-face-blue))))
+ (message (format #("vi: j, k, [q]: quit." 4 5 (face
hydra-face-amaranth)
+ 7 8 (face hydra-face-amaranth)
+ 11 12 (face hydra-face-blue))))))
(defun hydra-vi/body nil "Create a hydra with no body and the heads:
\"j\": `next-line',
diff --git a/hydra.el b/hydra.el
index ff03722..bdd2570 100644
--- a/hydra.el
+++ b/hydra.el
@@ -101,7 +101,8 @@ It's the only other way to quit it besides though a blue
head.
It's possible to set this to nil.")
(defcustom hydra-lv t
- "When non-nil, `lv-message' will be used to display hints instead of
`message'."
+ "When non-nil, `lv-message' will be used to display hints
+instead of `message'."
:type 'boolean)
(defface hydra-face-red
@@ -287,12 +288,44 @@ It's intended for the echo area, when a Hydra is active."
(setq emulation-mode-map-alists
(cdr emulation-mode-map-alists))))))
-(defun hydra--message (format-str &rest args)
- "Forward to (`message' FORMAT-STR ARGS).
-Or to `lv-message' if `hydra-lv' is non-nil."
- (if hydra-lv
- (apply #'lv-message format-str args)
- (apply #'message format-str args)))
+(defun hydra--unalias-var (str prefix)
+ "Return the symbol named STR if it's bound as a variable.
+Otherwise, add PREFIX to the symbol name."
+ (let ((sym (intern-soft str)))
+ (if (boundp sym)
+ sym
+ (intern (concat prefix "/" str)))))
+
+(defun hydra--format (str name heads body-color)
+ "Generate a `format' statement from STR.
+\"%`...\" expressions are extracted into \"%S\".
+NAME, HEADS and BODY-COLOR are parameters of `defhydra'.
+The expressions can be auto-expanded according to NAME."
+ (let ((prefix (symbol-name name))
+ (start 0)
+ varlist)
+ (while (setq start (string-match "%`\\([a-z-A-Z/0-9]+\\)" str start))
+ (push (hydra--unalias-var (match-string 1 str) prefix) varlist)
+ (setq str (replace-match "%S" nil nil str 0)))
+ (setq start 0)
+ (while (setq start (string-match "_\\([a-z-A-Z]+\\)_" str start))
+ (let* ((key (match-string 1 str))
+ (head (assoc key heads)))
+ (if head
+ (setq str (replace-match
+ (propertize key 'face (hydra--face head body-color))
+ nil nil str))
+ (error "Unrecognized key: _%s_" key))))
+ `(format ,str ,@(nreverse varlist))))
+
+(defun hydra--message (str name heads body-color)
+ "Generate code to display STR in the preferred echo area.
+Set `hydra-lv' to choose the echo area.
+NAME, HEADS and BODY-COLOR are parameters of `defhydra'."
+ (let ((format-expr (hydra--format str name heads body-color)))
+ `(if hydra-lv
+ (lv-message ,format-expr)
+ (message ,format-expr))))
(defun hydra--doc (body-key body-name heads)
"Generate a part of Hydra docstring.
@@ -377,9 +410,9 @@ CMD is a callable expression: either an interactive function
name, or an interactive lambda, or a single sexp (it will be
wrapped in an interactive lambda).
-HINT is a short string that identifies its head. It will be
+HINT is a short string that identifies its head. It will be
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
+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
@@ -396,8 +429,8 @@ except a blue head can stop the Hydra state.
- 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
-generated NAME/body command. This command is also the return
+want to bind anything. In that case, typically you will bind the
+generated NAME/body command. This command is also the return
result of `defhydra'."
(declare (indent defun))
(unless (stringp docstring)
@@ -443,22 +476,29 @@ result of `defhydra'."
(when (cl-some `(lambda (h)
(eq (hydra--color h ',body-color) 'red))
heads)
- (warn "%S body color: upgrading all red heads to %S" body-color
body-color))
+ (warn
+ "%S body color: upgrading all red heads to %S"
+ body-color body-color))
(define-key keymap [t]
`(lambda ()
(interactive)
- ,@(if (eq body-color 'amaranth)
- '((message "An amaranth Hydra can only exit through a
blue head"))
- '((let ((kb (key-binding (this-command-keys))))
- (if kb
- (call-interactively kb)
- (message "A pink Hydra can only exit through a
blue head")))))
+ ,@(if
+ (eq body-color 'amaranth)
+ '((message "An amaranth Hydra can only exit through a blue
head"))
+ '((let ((kb (key-binding (this-command-keys))))
+ (if kb
+ (if (commandp kb)
+ (call-interactively kb)
+ (error "Pink Hydra can't currently handle
prefixes, aboring"))
+ (message "A pink Hydra can only exit through a blue
head")))))
(hydra-set-transient-map hydra-curr-map t)
(when hydra-is-helpful
(unless hydra-lv
(sit-for 0.8))
(,hint-name)))))
- (error "An %S Hydra must have at least one blue head in order to exit"
body-color))
+ (error
+ "An %S Hydra must have at least one blue head in order to exit"
+ body-color))
(when hydra-keyboard-quit
(define-key keymap hydra-keyboard-quit
`(lambda ()
@@ -470,7 +510,8 @@ result of `defhydra'."
,@(cl-mapcar
(lambda (head name)
(hydra--make-defun
- name (hydra--make-callable (cadr head)) (hydra--color head
body-color)
+ name (hydra--make-callable
+ (cadr head)) (hydra--color head body-color)
(format "%s\n\nCall the head: `%S'." doc (cadr head))
hint-name keymap
body-color body-pre body-post))
@@ -485,9 +526,10 @@ result of `defhydra'."
(lambda (head name)
(when (or body-key method)
(let ((bind (hydra--head-property head :bind 'default))
- (final-key (if body-key
- (vconcat (kbd body-key) (kbd (car
head)))
- (kbd (car head)))))
+ (final-key
+ (if body-key
+ (vconcat (kbd body-key) (kbd (car head)))
+ (kbd (car head)))))
(cond ((null bind) nil)
((eq bind 'default)
@@ -508,13 +550,13 @@ result of `defhydra'."
(error "Invalid :bind property %S" head))))))
heads names))
(defun ,hint-name ()
- (hydra--message ,hint))
+ ,(hydra--message hint name heads body-color))
,(hydra--make-defun body-name nil nil doc hint-name keymap
body-color body-pre body-post
'(setq prefix-arg current-prefix-arg)))))
(defmacro defhydradio (name body &rest heads)
- "Create toggles with prefix NAME.
+ "Create radios with prefix NAME.
BODY specifies the options; there are none currently.
HEADS have the format:
@@ -522,7 +564,7 @@ HEADS have the format:
TOGGLE-NAME will be used along with NAME to generate a variable
name and a function that cycles it with the same name. VALUE
-should be an array. The first element of VALUE will be used to
+should be an array. The first element of VALUE will be used to
inialize the variable.
VALUE defaults to [nil t].
DOC defaults to TOGGLE-NAME split and capitalized."
@@ -534,7 +576,7 @@ DOC defaults to TOGGLE-NAME split and capitalized."
heads))))
(defun hydra--radio (parent head)
- "Generate a hydradio from HEAD."
+ "Generate a hydradio with PARENT from HEAD."
(let* ((name (car head))
(full-name (intern (format "%S/%S" parent name)))
(val (or (cadr head) [nil t]))
- [elpa] master f3c4dd7 02/72: hydra.el (hydra--hint): allow duplicate functions in heads, (continued)
- [elpa] master f3c4dd7 02/72: hydra.el (hydra--hint): allow duplicate functions in heads, Oleh Krehel, 2015/03/06
- [elpa] master 62f9b05 01/72: Allow some heads with no hints, Oleh Krehel, 2015/03/06
- [elpa] master f04f14c 14/72: hydra.el (defhydra): Update doc, Oleh Krehel, 2015/03/06
- [elpa] master 2086614 10/72: hydra.el (defhydradio): New macro, Oleh Krehel, 2015/03/06
- [elpa] master d04ef9b 12/72: hydra.el (hydra-cleanup): reorder, Oleh Krehel, 2015/03/06
- [elpa] master 926d9a4 15/72: Add pink body color, Oleh Krehel, 2015/03/06
- [elpa] master d25e560 03/72: Fix head color for heads with nil as HINT, Oleh Krehel, 2015/03/06
- [elpa] master abb76e8 13/72: lv.el (lv-message): Don't deactivate mark, Oleh Krehel, 2015/03/06
- [elpa] master 81ffca0 20/72: Update faces, Oleh Krehel, 2015/03/06
- [elpa] master 9769143 25/72: hydra-examples.el: Add example 7, Oleh Krehel, 2015/03/06
- [elpa] master c049a33 16/72: Allow for Ruby-style Hydra docstrings,
Oleh Krehel <=
- [elpa] master 688e8fd 23/72: hydra.el (hydra--head-color): fix for teal color, Oleh Krehel, 2015/03/06
- [elpa] master 0cda4ce 26/72: Fix typos, Oleh Krehel, 2015/03/06
- [elpa] master caf114a 11/72: Fix unintentional recursion in Emacs 25, Oleh Krehel, 2015/03/06
- [elpa] master c7281e9 17/72: Minor refactoring, Oleh Krehel, 2015/03/06
- [elpa] master 06b35f7 08/72: Remove obsoletes, Oleh Krehel, 2015/03/06
- [elpa] master 806e04b 09/72: Don't clutter Echo Area, Oleh Krehel, 2015/03/06
- [elpa] master 4f0ef62 27/72: hydra.el (hydra-pink-fallback): Add, Oleh Krehel, 2015/03/06
- [elpa] master 4aa8826 18/72: hydra.el (hydra--message): Take same arguments as `defhydra', Oleh Krehel, 2015/03/06
- [elpa] master b81d078 29/72: Generate a global resetter in `defhydradio', Oleh Krehel, 2015/03/06
- [elpa] master 42cb833 21/72: hydra.el (hydra--hint): Take same arguments as `defhydra', Oleh Krehel, 2015/03/06