+(defun notmuch-documentation-first-line (symbol)
+ "Return the first line of the documentation string for SYMBOL."
+ (let ((doc (documentation symbol)))
+ (if doc
+ (with-temp-buffer
+ (insert (documentation symbol))
+ (goto-char (point-min))
+ (let ((beg (point)))
+ (end-of-line)
+ (buffer-substring beg (point))))
+ "")))
+
+(defun notmuch-substitute-one-command-key (binding)
+ "For a key binding, return a string showing a human-readable representation
+of the key as well as the first line of documentation from the bound function.
+
+For a mouse binding, return nil."
+ (let ((key (car binding)))
+ (if (mouse-event-p key)
+ nil
+ (concat (format-kbd-macro (vector key))
+ "\t"
+ (notmuch-documentation-first-line (cdr binding))))))
+
+(defun notmuch-substitute-command-keys (doc)
+ "Like `substitute-command-keys' but with documentation, not function names."
+ (let ((beg 0))
+ (while (string-match "\\\\{\\([^}[:space:]]*\\)}" doc beg)
+ (let ((map (substring doc (match-beginning 1) (match-end 1))))
+ (setq doc (replace-match (mapconcat 'notmuch-substitute-one-command-key
+ (cdr (symbol-value (intern map))) "\n") 1 1 doc)))
+ (setq beg (match-end 0)))
+ doc))
+
+(defun notmuch-help ()
+ "Display help for the current notmuch mode."
+ (interactive)
+ (let ((mode major-mode))
+ (with-help-window (help-buffer)
+ (princ (notmuch-substitute-command-keys (documentation mode t))))))
+