--- /dev/null
+Return-Path: <amdragon@mit.edu>\r
+X-Original-To: notmuch@notmuchmail.org\r
+Delivered-To: notmuch@notmuchmail.org\r
+Received: from localhost (localhost [127.0.0.1])\r
+ by olra.theworths.org (Postfix) with ESMTP id 03A7A431FDA\r
+ for <notmuch@notmuchmail.org>; Tue, 3 Sep 2013 14:45:53 -0700 (PDT)\r
+X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
+X-Spam-Flag: NO\r
+X-Spam-Score: -0.7\r
+X-Spam-Level: \r
+X-Spam-Status: No, score=-0.7 tagged_above=-999 required=5\r
+ tests=[RCVD_IN_DNSWL_LOW=-0.7] autolearn=disabled\r
+Received: from olra.theworths.org ([127.0.0.1])\r
+ by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)\r
+ with ESMTP id lRayjVe1V9xl for <notmuch@notmuchmail.org>;\r
+ Tue, 3 Sep 2013 14:45:48 -0700 (PDT)\r
+Received: from dmz-mailsec-scanner-4.mit.edu (dmz-mailsec-scanner-4.mit.edu\r
+ [18.9.25.15])\r
+ by olra.theworths.org (Postfix) with ESMTP id 84802431FDB\r
+ for <notmuch@notmuchmail.org>; Tue, 3 Sep 2013 14:45:33 -0700 (PDT)\r
+X-AuditID: 1209190f-b7fa58e000000953-7a-5226587c7b59\r
+Received: from mailhub-auth-2.mit.edu ( [18.7.62.36])\r
+ by dmz-mailsec-scanner-4.mit.edu (Symantec Messaging Gateway) with SMTP\r
+ id 16.F3.02387.C7856225; Tue, 3 Sep 2013 17:45:32 -0400 (EDT)\r
+Received: from outgoing.mit.edu (outgoing-auth-1.mit.edu [18.9.28.11])\r
+ by mailhub-auth-2.mit.edu (8.13.8/8.9.2) with ESMTP id r83LjUlV019873; \r
+ Tue, 3 Sep 2013 17:45:30 -0400\r
+Received: from drake.dyndns.org (26-4-182.dynamic.csail.mit.edu [18.26.4.182])\r
+ (authenticated bits=0)\r
+ (User authenticated as amdragon@ATHENA.MIT.EDU)\r
+ by outgoing.mit.edu (8.13.8/8.12.4) with ESMTP id r83LjRTO026859\r
+ (version=TLSv1/SSLv3 cipher=AES256-SHA bits=256 verify=NOT);\r
+ Tue, 3 Sep 2013 17:45:28 -0400\r
+Received: from amthrax by drake.dyndns.org with local (Exim 4.77)\r
+ (envelope-from <amdragon@mit.edu>)\r
+ id 1VGyPe-0004y3-VT; Tue, 03 Sep 2013 17:45:26 -0400\r
+From: Austin Clements <amdragon@MIT.EDU>\r
+To: notmuch@notmuchmail.org\r
+Subject: [PATCH v2 7/9] emacs: Make notmuch-help work with arbitrary keymaps\r
+Date: Tue, 3 Sep 2013 17:45:23 -0400\r
+Message-Id: <1378244725-18846-8-git-send-email-amdragon@mit.edu>\r
+X-Mailer: git-send-email 1.7.10.4\r
+In-Reply-To: <1378244725-18846-1-git-send-email-amdragon@mit.edu>\r
+References: <1378244725-18846-1-git-send-email-amdragon@mit.edu>\r
+X-Brightmail-Tracker:\r
+ H4sIAAAAAAAAA+NgFjrKIsWRmVeSWpSXmKPExsUixG6nolsToRZksH6voUXTdGeL1XN5LK7f\r
+ nMnswOyxc9Zddo9b91+zezxbdYs5gDmKyyYlNSezLLVI3y6BK+PKar6C+1IVGybdYmtg3Cba\r
+ xcjJISFgIrG36R8LhC0mceHeerYuRi4OIYF9jBJdfw8xQTgbGCXmTj7MAuEcZpLo+HiVEcKZ\r
+ yyjx/f8JJpB+NgENiW37lzOC2CIC0hI7785mBbGZBaIljlyewQZiCwv4SMxpuwpWzyKgKrHq\r
+ 3jKw3bwCDhLtt2YyQtyhKNH9bAJYPaeAo0TvgkXsILYQUE3TysvsExj5FzAyrGKUTcmt0s1N\r
+ zMwpTk3WLU5OzMtLLdI10cvNLNFLTSndxAgKLU5J/h2M3w4qHWIU4GBU4uFdcV81SIg1say4\r
+ MvcQoyQHk5Io75FQtSAhvqT8lMqMxOKM+KLSnNTiQ4wSHMxKIrwJPkA53pTEyqrUonyYlDQH\r
+ i5I477OnZwOFBNITS1KzU1MLUotgsjIcHEoSvOXhQI2CRanpqRVpmTklCGkmDk6Q4TxAw3+G\r
+ gQwvLkjMLc5Mh8ifYlSUEudNB2kWAElklObB9cJi/xWjONArwrz+IFU8wLQB1/0KaDAT0OC0\r
+ z6ogg0sSEVJSDYztKx43J36RWJmwQLn3kuY5ydyPrXGB3Vc6Lmd9uL8sffOCDVtSGJ5lJdQm\r
+ PlItnRJw5fVPPeWpunksm/of+9W8mCEntrdFwLHzwqyjPh8X5Mqz7Z7jtYAzJ1TkWvwLL2ad\r
+ tTttnZnv26S1fZuksUkid7tNZ4fO28YTfqaRYR6T2450fpu/Q0KJpTgj0VCLuag4EQAOyyc1\r
+ 2AIAAA==\r
+X-BeenThere: notmuch@notmuchmail.org\r
+X-Mailman-Version: 2.1.13\r
+Precedence: list\r
+List-Id: "Use and development of the notmuch mail system."\r
+ <notmuch.notmuchmail.org>\r
+List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
+ <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
+List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
+List-Post: <mailto:notmuch@notmuchmail.org>\r
+List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
+List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
+ <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
+X-List-Received-Date: Tue, 03 Sep 2013 21:45:53 -0000\r
+\r
+This converts notmuch-help to use map-keymap for all keymap traversal.\r
+This generally cleans up and simplifies construction of keymap\r
+documentation, and also makes notmuch-help support anything that can\r
+be in a keymap, including more esoteric stuff like multiple\r
+inheritance.\r
+---\r
+ emacs/notmuch.el | 58 +++++++++++++++++++++---------------------------------\r
+ 1 file changed, 22 insertions(+), 36 deletions(-)\r
+\r
+diff --git a/emacs/notmuch.el b/emacs/notmuch.el\r
+index 80446be..0304096 100644\r
+--- a/emacs/notmuch.el\r
++++ b/emacs/notmuch.el\r
+@@ -140,48 +140,34 @@ This is basically just `format-kbd-macro' but we also convert ESC to M-."\r
+ "M-"\r
+ (concat desc " "))))\r
+ \r
+-;; I would think that emacs would have code handy for walking a keymap\r
+-;; and generating strings for each key, and I would prefer to just call\r
+-;; that. But I couldn't find any (could be all implemented in C I\r
+-;; suppose), so I wrote my own here.\r
+-(defun notmuch-substitute-one-command-key-with-prefix (prefix binding)\r
+- "For a key binding, return a string showing a human-readable\r
+-representation of the prefixed key as well as the first line of\r
+-documentation from the bound function.\r
+-\r
+-For a mouse binding, return nil."\r
+- (let ((key (car binding))\r
+- (action (cdr binding)))\r
+- (if (mouse-event-p key)\r
+- nil\r
+- (if (keymapp action)\r
+- (let ((substitute (apply-partially 'notmuch-substitute-one-command-key-with-prefix (notmuch-prefix-key-description key)))\r
+- (as-list))\r
+- (map-keymap (lambda (a b)\r
+- (push (cons a b) as-list))\r
+- action)\r
+- (mapconcat substitute as-list "\n"))\r
+- (concat prefix (format-kbd-macro (vector key))\r
+- "\t"\r
+- (notmuch-documentation-first-line action))))))\r
+-\r
+-(defun notmuch-substitute-command-keys-one (key)\r
+- ;; A `keymap' key indicates inheritance from a parent keymap - the\r
+- ;; inherited mappings follow, so there is nothing to print for\r
+- ;; `keymap' itself.\r
+- (when (not (eq key 'keymap))\r
+- (notmuch-substitute-one-command-key-with-prefix nil key)))\r
++(defun notmuch-describe-keymap (keymap &optional prefix tail)\r
++ "Return a list of strings, each describing one key in KEYMAP.\r
++\r
++Each string gives a human-readable description of the key and the\r
++first line of documentation for the bound function."\r
++ (map-keymap\r
++ (lambda (key binding)\r
++ (cond ((mouse-event-p key) nil)\r
++ ((keymapp binding)\r
++ (setq tail\r
++ (notmuch-describe-keymap\r
++ binding (notmuch-prefix-key-description key) tail)))\r
++ (t\r
++ (push (concat prefix (format-kbd-macro (vector key)) "\t"\r
++ (notmuch-documentation-first-line binding))\r
++ tail))))\r
++ keymap)\r
++ tail)\r
+ \r
+ (defun notmuch-substitute-command-keys (doc)\r
+ "Like `substitute-command-keys' but with documentation, not function names."\r
+ (let ((beg 0))\r
+ (while (string-match "\\\\{\\([^}[:space:]]*\\)}" doc beg)\r
+ (let* ((keymap-name (substring doc (match-beginning 1) (match-end 1)))\r
+- (keymap (symbol-value (intern keymap-name))))\r
+- (setq doc (replace-match\r
+- (mapconcat #'notmuch-substitute-command-keys-one\r
+- (cdr keymap) "\n")\r
+- 1 1 doc)))\r
++ (keymap (symbol-value (intern keymap-name)))\r
++ (desc-list (notmuch-describe-keymap keymap))\r
++ (desc (mapconcat #'identity desc-list "\n")))\r
++ (setq doc (replace-match desc 1 1 doc)))\r
+ (setq beg (match-end 0)))\r
+ doc))\r
+ \r
+-- \r
+1.7.10.4\r
+\r