From 3a24ecd11256014e53c464bf8c181239b443c7cd 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): * doc/lispref/keymaps.texi (Scanning Keymaps): Document it. * etc/NEWS: Announce it. * 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 | 6 ++++ etc/NEWS | 3 ++ lisp/help-fns.el | 59 +++++++++++++++++++++++++++++++++++++ test/lisp/help-fns-tests.el | 29 ++++++++++++++++++ 5 files changed, 101 insertions(+), 1 deletion(-) diff --git a/doc/emacs/help.texi b/doc/emacs/help.texi index 4851659b8b..ce40a15abe 100644 --- a/doc/emacs/help.texi +++ b/doc/emacs/help.texi @@ -581,6 +581,7 @@ Misc Help @findex describe-bindings @kindex C-h s @findex describe-syntax +@findex describe-keymap @kbd{C-h b} (@code{describe-bindings}) and @kbd{C-h s} (@code{describe-syntax}) show other information about the current environment within Emacs. @kbd{C-h b} displays a list of all the key @@ -589,7 +590,9 @@ Misc Help finally the global bindings (@pxref{Key Bindings}). @kbd{C-h s} displays the contents of the syntax table, with explanations of each character's syntax (@pxref{Syntax Tables,, Syntax Tables, elisp, The -Emacs Lisp Reference Manual}). +Emacs Lisp Reference Manual}). Finally, @kbd{M-x describe-keymap} +prompts for the name of a keymap variable and displays a listing of +all key bindings in that keymap. @findex describe-prefix-bindings You can get a list of subcommands for a particular prefix key by diff --git a/doc/lispref/keymaps.texi b/doc/lispref/keymaps.texi index 8ff329bdac..9fc0420b7e 100644 --- a/doc/lispref/keymaps.texi +++ b/doc/lispref/keymaps.texi @@ -2010,6 +2010,12 @@ Scanning Keymaps instead of the current buffer's. @end deffn +@deffn Command describe-keymap keymap &optional search-symbols +This function creates a listing of all key bindings in variable +@var{keymap}, and displays it in a buffer named @file{*Help*}. When +called interactively, prompt for a variable that has a keymap value. +@end deffn + @node Menu Keymaps @section Menu Keymaps @cindex menu keymaps diff --git a/etc/NEWS b/etc/NEWS index 4134f7bb5f..6609bd3111 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1461,6 +1461,9 @@ killed when pdbtracking session is finished. ** Help ++++ +*** New command 'describe-keymap' describes keybindings in a keymap. + --- *** Description of variables and functions give an estimated first release. diff --git a/lisp/help-fns.el b/lisp/help-fns.el index 14dea7de9b..333eda0aac 100644 --- a/lisp/help-fns.el +++ b/lisp/help-fns.el @@ -1561,6 +1561,65 @@ describe-categories (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 da4d25d0a6..3921b59f2c 100644 --- a/test/lisp/help-fns-tests.el +++ b/test/lisp/help-fns-tests.el @@ -123,4 +123,33 @@ help-fns-test-describe-symbol (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.20.1