emacs: Make notmuch-help work with arbitrary keymaps

This converts notmuch-help to use map-keymap for all keymap traversal.
This generally cleans up and simplifies construction of keymap
documentation, and also makes notmuch-help support anything that can
be in a keymap, including more esoteric stuff like multiple
inheritance.
This commit is contained in:
Austin Clements 2013-09-03 17:45:23 -04:00 committed by David Bremner
parent 21474f0e09
commit 69c52c56f2

View file

@ -140,48 +140,34 @@ This is basically just `format-kbd-macro' but we also convert ESC to M-."
"M-" "M-"
(concat desc " ")))) (concat desc " "))))
;; I would think that emacs would have code handy for walking a keymap (defun notmuch-describe-keymap (keymap &optional prefix tail)
;; and generating strings for each key, and I would prefer to just call "Return a list of strings, each describing one key in KEYMAP.
;; that. But I couldn't find any (could be all implemented in C I
;; suppose), so I wrote my own here.
(defun notmuch-substitute-one-command-key-with-prefix (prefix binding)
"For a key binding, return a string showing a human-readable
representation of the prefixed key as well as the first line of
documentation from the bound function.
For a mouse binding, return nil." Each string gives a human-readable description of the key and the
(let ((key (car binding)) first line of documentation for the bound function."
(action (cdr binding))) (map-keymap
(if (mouse-event-p key) (lambda (key binding)
nil (cond ((mouse-event-p key) nil)
(if (keymapp action) ((keymapp binding)
(let ((substitute (apply-partially 'notmuch-substitute-one-command-key-with-prefix (notmuch-prefix-key-description key))) (setq tail
(as-list)) (notmuch-describe-keymap
(map-keymap (lambda (a b) binding (notmuch-prefix-key-description key) tail)))
(push (cons a b) as-list)) (t
action) (push (concat prefix (format-kbd-macro (vector key)) "\t"
(mapconcat substitute as-list "\n")) (notmuch-documentation-first-line binding))
(concat prefix (format-kbd-macro (vector key)) tail))))
"\t" keymap)
(notmuch-documentation-first-line action)))))) tail)
(defun notmuch-substitute-command-keys-one (key)
;; A `keymap' key indicates inheritance from a parent keymap - the
;; inherited mappings follow, so there is nothing to print for
;; `keymap' itself.
(when (not (eq key 'keymap))
(notmuch-substitute-one-command-key-with-prefix nil key)))
(defun notmuch-substitute-command-keys (doc) (defun notmuch-substitute-command-keys (doc)
"Like `substitute-command-keys' but with documentation, not function names." "Like `substitute-command-keys' but with documentation, not function names."
(let ((beg 0)) (let ((beg 0))
(while (string-match "\\\\{\\([^}[:space:]]*\\)}" doc beg) (while (string-match "\\\\{\\([^}[:space:]]*\\)}" doc beg)
(let* ((keymap-name (substring doc (match-beginning 1) (match-end 1))) (let* ((keymap-name (substring doc (match-beginning 1) (match-end 1)))
(keymap (symbol-value (intern keymap-name)))) (keymap (symbol-value (intern keymap-name)))
(setq doc (replace-match (desc-list (notmuch-describe-keymap keymap))
(mapconcat #'notmuch-substitute-command-keys-one (desc (mapconcat #'identity desc-list "\n")))
(cdr keymap) "\n") (setq doc (replace-match desc 1 1 doc)))
1 1 doc)))
(setq beg (match-end 0))) (setq beg (match-end 0)))
doc)) doc))