Add a shortcut to supply a head's eval-able docstring

* hydra.el (hydra--hint): Return "" if body's :hint is nil.
(hydra--format): Extend the regex from e.g. _a_ to [_?]a[_?].
Add another cond branch for quoted docs.

Example:

(defhydra hydra-org-agenda-view (:hint nil)
  "
_d_: ?d? day        _g_: time grid=?g?  _a_: arch-trees
_w_: ?w? week       _[_: inactive       _A_: arch-files
_t_: ?t? fortnight  _f_: follow=?f?     _r_: clock report=?r?
_m_: ?m? month      _e_: entry text=?e? _D_: include diary=?D?
_y_: ?y? year       _q_: quit           _L__l__c_: log = ?l?"
  ("SPC" org-agenda-reset-view)
  ("d" org-agenda-day-view (if (eq 'day (org-agenda-cts)) "[x]" "[ ]"))
  ("w" org-agenda-week-view (if (eq 'week (org-agenda-cts)) "[x]" "[ ]"))
  ("t" org-agenda-fortnight-view (if (eq 'fortnight (org-agenda-cts)) "[x]" "[ ]"))
  ("m" org-agenda-month-view (if (eq 'month (org-agenda-cts)) "[x]" "[ ]"))
  ("y" org-agenda-year-view (if (eq 'year (org-agenda-cts)) "[x]" "[ ]"))
  ("l" org-agenda-log-mode (format "% -3S" org-agenda-show-log))
  ("L" (org-agenda-log-mode '(4)))
  ("c" (org-agenda-log-mode 'clockcheck))
  ("f" org-agenda-follow-mode (format "% -3S" org-agenda-follow-mode))
  ("a" org-agenda-archives-mode)
  ("A" (org-agenda-archives-mode 'files))
  ("r" org-agenda-clockreport-mode (format "% -3S" org-agenda-clockreport-mode))
  ("e" org-agenda-entry-text-mode (format "% -3S" org-agenda-entry-text-mode))
  ("g" org-agenda-toggle-time-grid (format "% -3S" org-agenda-use-time-grid))
  ("D" org-agenda-toggle-diary (format "% -3S" org-agenda-include-diary))
  ("!" org-agenda-toggle-deadlines)
  ("[" (let ((org-agenda-include-inactive-timestamps t))
         (org-agenda-check-type t 'timeline 'agenda)
         (org-agenda-redo)
         (message "Display now includes inactive timestamps as well")))
  ("q" (message "Abort") :exit t))

While e.g. "_d_" quotes the key, "?d?" will quote the docstring.
Remember that the docstrings for each head are actually sexps, not plain
strings. With a simple trick like (format "% -3S", in order to have "nil"
and "t" have the same width, everything is neatly arranged.
master
Oleh Krehel 10 years ago
parent 69529aded3
commit 5be27f4b61
  1. 127
      hydra.el

@ -467,60 +467,62 @@ Return DEFAULT if PROP is not in H."
(defun hydra--hint (body heads)
"Generate a hint for the echo area.
BODY, and HEADS are parameters to `defhydra'."
(let (alist)
(dolist (h heads)
(let ((val (assoc (cadr h) alist))
(pstr (hydra-fontify-head h body)))
(unless (null (cl-caddr h))
(if val
(setf (cadr val)
(concat (cadr val) " " pstr))
(push
(cons (cadr h)
(cons pstr (cl-caddr h)))
alist)))))
(let ((keys (nreverse (mapcar #'cdr alist)))
(n-cols (plist-get (cddr body) :columns))
res)
(setq res
(if n-cols
(let ((n-rows (1+ (/ (length keys) n-cols)))
(max-key-len (apply #'max (mapcar (lambda (x) (length (car x))) keys)))
(max-doc-len (apply #'max (mapcar (lambda (x)
(length (hydra--to-string (cdr x)))) keys))))
`(concat
"\n"
(mapconcat #'identity
(mapcar
(lambda (x)
(mapconcat
(lambda (y)
(and y
(funcall hydra-key-doc-function
(car y)
,max-key-len
(hydra--to-string (cdr y))
,max-doc-len))) x ""))
',(hydra--matrix keys n-cols n-rows))
"\n")))
`(concat
(mapconcat
(lambda (x)
(let ((str (hydra--to-string (cdr x))))
(format
(if (> (length str) 0)
(concat hydra-head-format str)
"%s")
(car x))))
',keys
", ")
,(if keys "." ""))))
(if (cl-every #'stringp
(mapcar 'cddr alist))
(eval res)
res))))
(if (null (hydra-plist-get-default (cddr body) :hint 1))
""
(let (alist)
(dolist (h heads)
(let ((val (assoc (cadr h) alist))
(pstr (hydra-fontify-head h body)))
(unless (null (cl-caddr h))
(if val
(setf (cadr val)
(concat (cadr val) " " pstr))
(push
(cons (cadr h)
(cons pstr (cl-caddr h)))
alist)))))
(let ((keys (nreverse (mapcar #'cdr alist)))
(n-cols (plist-get (cddr body) :columns))
res)
(setq res
(if n-cols
(let ((n-rows (1+ (/ (length keys) n-cols)))
(max-key-len (apply #'max (mapcar (lambda (x) (length (car x))) keys)))
(max-doc-len (apply #'max (mapcar (lambda (x)
(length (hydra--to-string (cdr x)))) keys))))
`(concat
"\n"
(mapconcat #'identity
(mapcar
(lambda (x)
(mapconcat
(lambda (y)
(and y
(funcall hydra-key-doc-function
(car y)
,max-key-len
(hydra--to-string (cdr y))
,max-doc-len))) x ""))
',(hydra--matrix keys n-cols n-rows))
"\n")))
`(concat
(mapconcat
(lambda (x)
(let ((str (hydra--to-string (cdr x))))
(format
(if (> (length str) 0)
(concat hydra-head-format str)
"%s")
(car x))))
',keys
", ")
,(if keys "." ""))))
(if (cl-every #'stringp
(mapcar 'cddr alist))
(eval res)
res)))))
(defvar hydra-fontify-head-function nil
"Possible replacement for `hydra-fontify-head-default'.")
@ -592,9 +594,22 @@ The expressions can be auto-expanded according to NAME."
offset)
(while (setq start
(string-match
"\\(?:%\\( ?-?[0-9]*s?\\)\\(`[a-z-A-Z/0-9]+\\|(\\)\\)\\|\\(?:_\\( ?-?[0-9]*?\\)\\(\\[\\|]\\|[-[:alnum:] ~.,;:/|?<>={}*+#%@!&^]+?\\)_\\)"
"\\(?:%\\( ?-?[0-9]*s?\\)\\(`[a-z-A-Z/0-9]+\\|(\\)\\)\\|\\(?:[_?]\\( ?-?[0-9]*?\\)\\(\\[\\|]\\|[-[:alnum:] ~.,;:/|?<>={}*+#%@!&^]+?\\)[_?]\\)"
docstring start))
(cond ((eq ?_ (aref (match-string 0 docstring) 0))
(cond ((eq ?? (aref (match-string 0 docstring) 0))
(let* ((key (match-string 4 docstring))
(head (assoc key heads)))
(if head
(progn
(push (nth 2 head) varlist)
(setq docstring
(replace-match
(or
hydra-key-format-spec
(concat "%" (match-string 3 docstring) "s"))
t nil docstring)))
(warn "Unrecognized key: ?%s?" key))))
((eq ?_ (aref (match-string 0 docstring) 0))
(let* ((key (match-string 4 docstring))
(key (if (equal key "β") "_" key))
(head (assoc key heads)))

Loading…
Cancel
Save