From 557b790e0a3fcb2cd4196a3119da3e92647f8def Mon Sep 17 00:00:00 2001 From: Stefan Kangas Date: Sat, 24 Aug 2019 01:02:04 +0200 Subject: [PATCH] Add new help command describe-keymap * lisp/help-fns.el (describe-keymap): New command to show key bindings for a given keymap. (Bug#30660) * doc/emacs/help.texi (Misc Help): Document the new command. * doc/lispref/keymaps.texi (Scanning Keymaps): Add a cross-reference to the above documentation. * etc/NEWS: Announce the new command. * test/lisp/help-fns-tests.el (help-fns-test-describe-keymap/symbol) (help-fns-test-describe-keymap/value) (help-fns-test-describe-keymap/not-keymap) (help-fns-test-describe-keymap/let-bound) (help-fns-test-describe-keymap/dynamically-bound-no-file): New tests. Co-authored-by: Drew Adams --- doc/emacs/help.texi | 5 ++++ doc/lispref/keymaps.texi | 7 +++-- etc/NEWS | 5 ++++ lisp/help-fns.el | 59 +++++++++++++++++++++++++++++++++++++ test/lisp/help-fns-tests.el | 28 ++++++++++++++++++ 5 files changed, 102 insertions(+), 2 deletions(-) diff --git a/doc/emacs/help.texi b/doc/emacs/help.texi index fce6720b934..49c53c5cbc0 100644 --- a/doc/emacs/help.texi +++ b/doc/emacs/help.texi @@ -601,6 +601,11 @@ is @key{ESC}, because @kbd{@key{ESC} C-h} is actually @kbd{C-M-h}, which marks a defun. However, @w{@kbd{@key{ESC} @key{F1}}} and @w{@kbd{@key{ESC} ?}} work fine.) +@findex describe-keymap +Finally, @kbd{M-x describe-keymap} prompts for the name of a keymap, +with completion, and displays a listing of all key bindings in that +keymap. + @node Help Files @section Help Files diff --git a/doc/lispref/keymaps.texi b/doc/lispref/keymaps.texi index 259efea3248..4d513132e9f 100644 --- a/doc/lispref/keymaps.texi +++ b/doc/lispref/keymaps.texi @@ -1846,8 +1846,11 @@ local map. @cindex scanning keymaps @cindex keymaps, scanning - This section describes functions used to scan all the current keymaps -for the sake of printing help information. + This section describes functions used to scan all the current +keymaps for the sake of printing help information. To display the +bindings in a particular keymap, you can use the +@code{describe-keymap} command (@pxref{Misc Help, , Other Help +Commands, emacs, The GNU Emacs Manual}) @defun accessible-keymaps keymap &optional prefix This function returns a list of all the keymaps that can be reached (via diff --git a/etc/NEWS b/etc/NEWS index 1fbcd43ab00..de8e20e2de4 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -85,6 +85,11 @@ shows equivalent key bindings for all commands that have them. * Changes in Specialized Modes and Packages in Emacs 28.1 +** Help + ++++ +*** New command 'describe-keymap' describes keybindings in a keymap. + --- ** The old non-SMIE indentation of 'sh-mode' has been removed. diff --git a/lisp/help-fns.el b/lisp/help-fns.el index 0e2ae6b3c3c..017bb3ae748 100644 --- a/lisp/help-fns.el +++ b/lisp/help-fns.el @@ -1562,6 +1562,65 @@ BUFFER should be a buffer or a buffer name." (insert "\nThe parent category table is:") (describe-vector table 'help-describe-category-set)))))) +;;;###autoload +(defun describe-keymap (keymap) + "Describe key bindings in KEYMAP. +When called interactively, prompt for a variable that has a +keymap value." + (interactive (list + (intern (completing-read "Keymap: " obarray + (lambda (m) + (and (boundp m) + (keymapp (symbol-value m)))) + t nil 'variable-name-history)))) + (let (used-gentemp) + (unless (and (symbolp keymap) + (boundp keymap) + (keymapp (symbol-value keymap))) + (when (not (keymapp keymap)) + (if (symbolp keymap) + (error "Not a keymap variable: %S" keymap) + (error "Not a keymap"))) + (let ((sym nil)) + (unless sym + (setq sym (cl-gentemp "KEYMAP OBJECT (no variable) ")) + (setq used-gentemp t) + (set sym keymap)) + (setq keymap sym))) + ;; Follow aliasing. + (setq keymap (or (ignore-errors (indirect-variable keymap)) keymap)) + (help-setup-xref (list #'describe-keymap keymap) + (called-interactively-p 'interactive)) + (let* ((name (symbol-name keymap)) + (doc (documentation-property keymap 'variable-documentation)) + (file-name (find-lisp-object-file-name keymap 'defvar))) + (with-help-window (help-buffer) + (with-current-buffer standard-output + (unless used-gentemp + (princ (format-message "%S is a keymap variable" keymap)) + (if (not file-name) + (princ ".\n\n") + (princ (format-message + " defined in `%s'.\n\n" + (if (eq file-name 'C-source) + "C source code" + (file-name-nondirectory file-name)))) + (save-excursion + (re-search-backward (substitute-command-keys + "`\\([^`']+\\)'") + nil t) + (help-xref-button 1 'help-variable-def + keymap file-name)))) + (when (and (not (equal "" doc)) doc) + (princ "Documentation:\n") + (princ (format-message "%s\n\n" doc))) + ;; Use `insert' instead of `princ', so control chars (e.g. \377) + ;; insert correctly. + (insert (substitute-command-keys (concat "\\{" name "}")))))) + ;; Cleanup. + (when used-gentemp + (makunbound keymap)))) + ;;; Replacements for old lib-src/ programs. Don't seem especially useful. diff --git a/test/lisp/help-fns-tests.el b/test/lisp/help-fns-tests.el index ef42d4bda29..1d6c062979f 100644 --- a/test/lisp/help-fns-tests.el +++ b/test/lisp/help-fns-tests.el @@ -123,4 +123,32 @@ Return first line of the output of (describe-function-1 FUNC)." (goto-char (point-min)) (should (looking-at "^font-lock-comment-face is ")))) + +;;; Tests for describe-keymap +(ert-deftest help-fns-test-describe-keymap/symbol () + (describe-keymap 'minibuffer-local-must-match-map) + (with-current-buffer "*Help*" + (should (looking-at "^minibuffer-local-must-match-map is")))) + +(ert-deftest help-fns-test-describe-keymap/value () + (describe-keymap minibuffer-local-must-match-map) + (with-current-buffer "*Help*" + (should (looking-at "^key")))) + +(ert-deftest help-fns-test-describe-keymap/not-keymap () + (should-error (describe-keymap nil)) + (should-error (describe-keymap emacs-version))) + +(ert-deftest help-fns-test-describe-keymap/let-bound () + (let ((foobar minibuffer-local-must-match-map)) + (describe-keymap foobar) + (with-current-buffer "*Help*" + (should (looking-at "^key"))))) + +(ert-deftest help-fns-test-describe-keymap/dynamically-bound-no-file () + (setq help-fns-test--describe-keymap-foo minibuffer-local-must-match-map) + (describe-keymap 'help-fns-test--describe-keymap-foo) + (with-current-buffer "*Help*" + (should (looking-at "^help-fns-test--describe-keymap-foo is")))) + ;;; help-fns-tests.el ends here -- 2.39.5