Show Keys In Emacs Keymap Value
Asked Answered
C

6

39

When I query the current value of the keymap, eg with M-: (current-local-map), it shows me something along these lines:

Value: 
(keymap
 (S-mouse-2 . muse-follow-name-at-mouse-other-window)
 (mouse-2 . muse-follow-name-at-mouse)
 (33554445 . muse-follow-name-at-point-other-window)
 (S-return . muse-follow-name-at-point-other-window)
 (13 . muse-follow-name-at-point)
 (return . muse-follow-name-at-point)
 keymap
 (67108924 . muse-decrease-list-item-indentation)
 (67108926 . muse-increase-list-item-indentation)
 (M-return . muse-insert-list-item)
 (33554441 . muse-previous-reference)
 (S-iso-lefttab . muse-previous-reference)
 (S-tab . muse-previous-reference)
 (S-mouse-2 . muse-follow-name-at-mouse-other-window)
 (mouse-2 . muse-follow-name-at-mouse)
 (33554445 . muse-follow-name-at-point-other-window)
 (9 . muse-next-reference)
 (tab . muse-next-reference)
 (3 keymap
    (19 . muse-search)
    (2 . muse-find-backlinks)
    (tab . muse-insert-thing)
    (9 . muse-insert-thing)
    (16 . muse-project-publish)
    (6 . muse-project-find-file)
    (61 . muse-what-changed)
    (22 . muse-browse-result)
    (27 keymap
        (20 . muse-publish-this-file))
    (33554452 . muse-publish-this-file)
    (20 . muse-project-publish-this-file)
    (12 . font-lock-mode)
    (5 . muse-edit-link-at-point)
    (1 . muse-index))
 keymap
 (27 keymap
     (9 . ispell-complete-word)))

I want instead of numbers see something more meaningful like (control ?c) return for example. How do I do that ?

Contractive answered 13/8, 2010 at 19:38 Comment(1)
Cross-referencing with duplicate question emacs.stackexchange.com/questions/24105/…Rb
S
27

This is what you need: library help-fns+.el.

That gives you, as C-h M-k, command describe-keymap, which gives you a human-readable description of any keymap bound to a variable. E.g.:

C-h M-k dired-mode-map


    dired-mode-map
    --------------



    For more information check the manuals.

    Local keymap for `dired-mode' buffers.

    key             binding
    ---             -------

    e .. f      dired-find-file

    RET     dired-find-file
    C-o     dired-display-file
    C-t     Prefix Command
    ESC     Prefix Command
    SPC     dired-next-line
    !       dired-do-shell-command
    #       dired-flag-auto-save-files
    $       dired-hide-subdir
    %       Prefix Command
    &       dired-do-async-shell-command
    *       Prefix Command
    +       dired-create-directory
    -       negative-argument
    .       dired-clean-directory
    0 .. 9      digit-argument
    :       Prefix Command
           dired-next-dirline
    ?       dired-summary
    A       dired-do-search
    B       dired-do-byte-compile
    C       dired-do-copy
    D       dired-do-delete
    G       dired-do-chgrp
    H       dired-do-hardlink
    L       dired-do-load
    M       dired-do-chmod
    O       dired-do-chown
    P       dired-do-print
    Q       dired-do-query-replace-regexp
    R       dired-do-rename
    S       dired-do-symlink
    T       dired-do-touch
    U       dired-unmark-all-marks
    X       dired-do-shell-command
    Z       dired-do-compress
    ^       dired-up-directory
    a       dired-find-alternate-file
    d       dired-flag-file-deletion
    g       revert-buffer
    h       describe-mode
    i       dired-maybe-insert-subdir
    j       dired-goto-file
    k       dired-do-kill-lines
    l       dired-do-redisplay
    m       dired-mark
    n       dired-next-line
    o       dired-find-file-other-window
    p       dired-previous-line
    q       quit-window
    s       dired-sort-toggle-or-edit
    t       dired-toggle-marks
    u       dired-unmark
    v       dired-view-file
    w       dired-copy-filename-as-kill
    x       dired-do-flagged-delete
    y       dired-show-file-type
    z       kill-this-buffer
    ~       dired-flag-backup-files
    DEL     dired-unmark-backward
       mouse-face
       dired-mouse-find-file-other-window
         ??

    C-t C-t     image-dired-dired-toggle-marked-thumbs
    C-t .       image-dired-display-thumb
    C-t a       image-dired-display-thumbs-append
    C-t c       image-dired-dired-comment-files
    C-t d       image-dired-display-thumbs
    C-t e       image-dired-dired-edit-comment-and-tags
    C-t f       image-dired-mark-tagged-files
    C-t i       image-dired-dired-display-image
    C-t j       image-dired-jump-thumbnail-buffer
    C-t r       image-dired-delete-tag
    C-t t       image-dired-tag-files
    C-t x       image-dired-dired-display-external

    C-M-d       dired-tree-down
    C-M-n       dired-next-subdir
    C-M-p       dired-prev-subdir
    C-M-u       dired-tree-up
    M-$     dired-hide-all
    M-=     dired-backup-diff
    M-s     Prefix Command
    M-{     dired-prev-marked-file
    M-}     dired-next-marked-file
    M-DEL       dired-unmark-all-files

    M-s a       Prefix Command
    M-s f       Prefix Command

    % &     dired-flag-garbage-files
    % C     dired-do-copy-regexp
    % H     dired-do-hardlink-regexp
    % R     dired-do-rename-regexp
    % S     dired-do-symlink-regexp
    % d     dired-flag-files-regexp
    % g     dired-mark-files-containing-regexp
    % l     dired-downcase
    % m     dired-mark-files-regexp
    % r     dired-do-rename-regexp
    % u     dired-upcase

    * C-n       dired-next-marked-file
    * C-p       dired-prev-marked-file
    * !     dired-unmark-all-marks
    * %     dired-mark-files-regexp
    * *     dired-mark-executables
    * /     dired-mark-directories
    * ?     dired-unmark-all-files
    * @     dired-mark-symlinks
    * c     dired-change-marks
    * m     dired-mark
    * s     dired-mark-subdir-files
    * t     dired-toggle-marks
    * u     dired-unmark
    * DEL       dired-unmark-backward

    : d     epa-dired-do-decrypt
    : e     epa-dired-do-encrypt
    : s     epa-dired-do-sign
    : v     epa-dired-do-verify

        dired-undo
          dired-next-line
          dired-previous-line
       dired-toggle-read-only
               dired-undo

    M-s f C-s   dired-isearch-filenames
    M-s f ESC   Prefix Command

    M-s a C-s   dired-do-isearch
    M-s a ESC   Prefix Command

    M-s f C-M-s dired-isearch-filenames-regexp

    M-s a C-M-s dired-do-isearch-regexp

Say answered 21/8, 2011 at 1:13 Comment(7)
Whoever: Care to explain why you downvoted this answer?Say
I've installed (via package-install) help+ and help-fns+, but neither C-h M-k or C-h C-k are defined, nor is there a describe-keymap command.Shortstop
@VladimirPanteleev: Sounds like you have (or code that you load has) moved keymap help-map from C-h. Is <f1> still bound to it? E.g. <f1> M-k. However you normally consult help, that's the prefix key where these commands are bound. E.g. (define-key help-map "\M-k" 'describe-keymap). But if M-x describe-keymap is not even recognized then you must not have loaded ("installed") the files ("packages") properly. What does M-: (featurep 'help-fns+) tell you?Say
It worked after I explicitly loaded it. I thought installing the package would do that.Shortstop
Your answer still refers to C-h C-k, I assume that should be C-h M-k?Shortstop
@VladimirPanteleev: Thx - I edited to correct the key binding. Installing the package installs it, but you also need to do (package-initialize) - dunno whether you did that. And you might need to explicitly add ~/.emacs.d (or wherever you are installing packages) to your load-path: (add-to-list 'load-path (expand-file-name "~/.emacs.d")). See how to install and load packages.Say
Except don't actually put ~/.emacs.d itself in your load-path. Use some sub-directory, such as ~/.emacs.d/lisp. Refer to emacs.stackexchange.com/q/9877Rb
W
31
  • Did you know the command C-h m (describe-mode), which usually shows a description of the current major and minor modes, usually with their keymaps?

  • (substitute-command-keys "\\{foo-map}") is what describe-mode uses internally to generate the user-friendly description of the keymap foo-map.

  • If you'd like to have something closer to the keymap structure, the API is documented in "Classifying Events" in the Emacs Lisp manual. For example,
        (event-modifiers 33554445) ==> (shift control)
        (format "%c" (event-basic-type 33554445)) ==> "m"

Withershins answered 13/8, 2010 at 21:18 Comment(2)
This is a nice simple answer! (Simply evaluate (substitute-command-keys "\\{foo-map}"); why haven't I thought of this!)Pinot
ido-mode is probably an example of a mode, for which describe-mode doesn't list keymaps.Silverman
S
27

This is what you need: library help-fns+.el.

That gives you, as C-h M-k, command describe-keymap, which gives you a human-readable description of any keymap bound to a variable. E.g.:

C-h M-k dired-mode-map


    dired-mode-map
    --------------



    For more information check the manuals.

    Local keymap for `dired-mode' buffers.

    key             binding
    ---             -------

    e .. f      dired-find-file

    RET     dired-find-file
    C-o     dired-display-file
    C-t     Prefix Command
    ESC     Prefix Command
    SPC     dired-next-line
    !       dired-do-shell-command
    #       dired-flag-auto-save-files
    $       dired-hide-subdir
    %       Prefix Command
    &       dired-do-async-shell-command
    *       Prefix Command
    +       dired-create-directory
    -       negative-argument
    .       dired-clean-directory
    0 .. 9      digit-argument
    :       Prefix Command
           dired-next-dirline
    ?       dired-summary
    A       dired-do-search
    B       dired-do-byte-compile
    C       dired-do-copy
    D       dired-do-delete
    G       dired-do-chgrp
    H       dired-do-hardlink
    L       dired-do-load
    M       dired-do-chmod
    O       dired-do-chown
    P       dired-do-print
    Q       dired-do-query-replace-regexp
    R       dired-do-rename
    S       dired-do-symlink
    T       dired-do-touch
    U       dired-unmark-all-marks
    X       dired-do-shell-command
    Z       dired-do-compress
    ^       dired-up-directory
    a       dired-find-alternate-file
    d       dired-flag-file-deletion
    g       revert-buffer
    h       describe-mode
    i       dired-maybe-insert-subdir
    j       dired-goto-file
    k       dired-do-kill-lines
    l       dired-do-redisplay
    m       dired-mark
    n       dired-next-line
    o       dired-find-file-other-window
    p       dired-previous-line
    q       quit-window
    s       dired-sort-toggle-or-edit
    t       dired-toggle-marks
    u       dired-unmark
    v       dired-view-file
    w       dired-copy-filename-as-kill
    x       dired-do-flagged-delete
    y       dired-show-file-type
    z       kill-this-buffer
    ~       dired-flag-backup-files
    DEL     dired-unmark-backward
       mouse-face
       dired-mouse-find-file-other-window
         ??

    C-t C-t     image-dired-dired-toggle-marked-thumbs
    C-t .       image-dired-display-thumb
    C-t a       image-dired-display-thumbs-append
    C-t c       image-dired-dired-comment-files
    C-t d       image-dired-display-thumbs
    C-t e       image-dired-dired-edit-comment-and-tags
    C-t f       image-dired-mark-tagged-files
    C-t i       image-dired-dired-display-image
    C-t j       image-dired-jump-thumbnail-buffer
    C-t r       image-dired-delete-tag
    C-t t       image-dired-tag-files
    C-t x       image-dired-dired-display-external

    C-M-d       dired-tree-down
    C-M-n       dired-next-subdir
    C-M-p       dired-prev-subdir
    C-M-u       dired-tree-up
    M-$     dired-hide-all
    M-=     dired-backup-diff
    M-s     Prefix Command
    M-{     dired-prev-marked-file
    M-}     dired-next-marked-file
    M-DEL       dired-unmark-all-files

    M-s a       Prefix Command
    M-s f       Prefix Command

    % &     dired-flag-garbage-files
    % C     dired-do-copy-regexp
    % H     dired-do-hardlink-regexp
    % R     dired-do-rename-regexp
    % S     dired-do-symlink-regexp
    % d     dired-flag-files-regexp
    % g     dired-mark-files-containing-regexp
    % l     dired-downcase
    % m     dired-mark-files-regexp
    % r     dired-do-rename-regexp
    % u     dired-upcase

    * C-n       dired-next-marked-file
    * C-p       dired-prev-marked-file
    * !     dired-unmark-all-marks
    * %     dired-mark-files-regexp
    * *     dired-mark-executables
    * /     dired-mark-directories
    * ?     dired-unmark-all-files
    * @     dired-mark-symlinks
    * c     dired-change-marks
    * m     dired-mark
    * s     dired-mark-subdir-files
    * t     dired-toggle-marks
    * u     dired-unmark
    * DEL       dired-unmark-backward

    : d     epa-dired-do-decrypt
    : e     epa-dired-do-encrypt
    : s     epa-dired-do-sign
    : v     epa-dired-do-verify

        dired-undo
          dired-next-line
          dired-previous-line
       dired-toggle-read-only
               dired-undo

    M-s f C-s   dired-isearch-filenames
    M-s f ESC   Prefix Command

    M-s a C-s   dired-do-isearch
    M-s a ESC   Prefix Command

    M-s f C-M-s dired-isearch-filenames-regexp

    M-s a C-M-s dired-do-isearch-regexp

Say answered 21/8, 2011 at 1:13 Comment(7)
Whoever: Care to explain why you downvoted this answer?Say
I've installed (via package-install) help+ and help-fns+, but neither C-h M-k or C-h C-k are defined, nor is there a describe-keymap command.Shortstop
@VladimirPanteleev: Sounds like you have (or code that you load has) moved keymap help-map from C-h. Is <f1> still bound to it? E.g. <f1> M-k. However you normally consult help, that's the prefix key where these commands are bound. E.g. (define-key help-map "\M-k" 'describe-keymap). But if M-x describe-keymap is not even recognized then you must not have loaded ("installed") the files ("packages") properly. What does M-: (featurep 'help-fns+) tell you?Say
It worked after I explicitly loaded it. I thought installing the package would do that.Shortstop
Your answer still refers to C-h C-k, I assume that should be C-h M-k?Shortstop
@VladimirPanteleev: Thx - I edited to correct the key binding. Installing the package installs it, but you also need to do (package-initialize) - dunno whether you did that. And you might need to explicitly add ~/.emacs.d (or wherever you are installing packages) to your load-path: (add-to-list 'load-path (expand-file-name "~/.emacs.d")). See how to install and load packages.Say
Except don't actually put ~/.emacs.d itself in your load-path. Use some sub-directory, such as ~/.emacs.d/lisp. Refer to emacs.stackexchange.com/q/9877Rb
R
10

I just wrote the following based on Gilles' answer, so I figured I'd post it.

I see that Drew's describe-keymap has a very similar basis, but also covers various other use-cases, so offhand I'm inclined to suggest using that one as a more complete solution; but FWIW:

(defun my-describe-keymap (keymap)
  "Describe a keymap using `substitute-command-keys'."
  (interactive
   (list (completing-read
          "Keymap: " (let (maps)
                       (mapatoms (lambda (sym)
                                   (and (boundp sym)
                                        (keymapp (symbol-value sym))
                                        (push sym maps))))
                       maps)
          nil t)))
  (with-output-to-temp-buffer (format "*keymap: %s*" keymap)
    (princ (format "%s\n\n" keymap))
    (princ (substitute-command-keys (format "\\{%s}" keymap)))
    (with-current-buffer standard-output ;; temp buffer
      (setq help-xref-stack-item (list #'my-describe-keymap keymap)))))
Rb answered 3/5, 2016 at 2:10 Comment(3)
Phenomenal function.Affinitive
(SO keeps me from undoing/editing my edit proposal, so i'll say here that i think the blank line needs to be deleted, and/or the line I added needs to be indented)Gilbertegilbertian
Cross-referencing with emacs.stackexchange.com/a/59507/454 which lists all named (by a variable) keymaps in this way, in a single buffer.Rb
K
6

For a more modern approach, use the which-key-show-full-keymap command from the which-key package. It will ask you for a keymap and then show you all the bindings from that keymap, exactly like it would if you press a prefix key (if which-key-mode is enabled). That is, in the minibuffer, nice and clean.

From the documentation:

which-key-show-full-keymap is an interactive autoloaded compiled Lisp function in ‘which-key.el’.

(which-key-show-full-keymap KEYMAP)

Show all bindings in KEYMAP using which-key. KEYMAP is selected interactively from all available keymaps.

Kiangsi answered 17/9, 2019 at 10:21 Comment(1)
for anyone using Spacemacs or Doom this is the best answerArchaeopteryx
F
5

Here's a poor-man's implementation what describe-bindings (C-h b) gives you, but restricted to a particular keymap. The formatting isn't great, but should get you started:

(defun describe-keymap (keymap &optional prefix)
  (pop-to-buffer "Keymap description")
  (erase-buffer)
  (describe-keymap-impl keymap prefix))

(defun describe-keymap-impl (keymap &optional prefix)
  "show a description of keymap"
  (let (keymaps-to-process)
    (mapc (lambda (partofkeymap)
            (when prefix
              (insert (concat prefix " ")))
            (insert (key-description (list partofkeymap)))
            (insert "                ")
            (cond ((atom partofkeymap))
                  ((listp (cdr partofkeymap))
                   (insert "prefix-key")
                   (if (eq 'keymap (cadr partofkeymap))
                       (setq keymaps-to-process (cons partofkeymap keymaps-to-process))))
                  (t 
                   (insert (symbol-name (cdr partofkeymap)))))
            (insert "\n"))
          (if (and (symbolp keymap) (boundp keymap))
              (symbol-value keymap)
            keymap))
    (while keymaps-to-process
      (insert "\n\n")
      (describe-keymap-impl (cddar keymaps-to-process) (concat prefix (key-description (list (caar keymaps-to-process)))))
      (setq keymaps-to-process (cdr keymaps-to-process))))
  nil)

I tested by evaluating both:

(describe-keymap emacs-lisp-mode-map)
(describe-keymap 'emacs-lisp-mode-map)
France answered 13/8, 2010 at 21:30 Comment(3)
But you shouldn't need to re-implement describe-bindings. Just the available function -- describe-bindings -- should be able to do what is needed for any arbitrary keymap. Consider describe-mode': it prints out keymaps specified by expressions of the form \{MAPVAR} inside the documentation in human readable form. Its output is the documentation string of the mode function formatted by documentation' function; in its turn, the documentation' function uses substitute-command-keys', which in its turn calls exactly `describe-bindings' to format \{MAPVAR} expressions in the source doc string.Pinot
After studying the Elisp source, I discovered that contrary to what I have written above and what can be inferred from the documentation, describe-bindings' doesn't take a keymap as an argument. :( But the documentation for substitute-command-keys' clearly supposes this: "Substrings of the form \{MAPVAR} are replaced by summaries (made by describe-bindings') of the value of MAPVAR, taken as a keymap." Perhaps, one can overcome this by installing the interesting keymap as a local keymap in a temporary buffer, and running the standard describe-bindings' there...Pinot
That is exactly what describe-keymap, in help-fns+.el does. See my answer, above.Say
P
2

You can also use helpful-variable function from helpful package available in Melpa. Here is sample output:

projectile-command-map is a variable defined in projectile.el.

Value
!        projectile-run-shell-command-in-root
&        projectile-run-async-shell-command-in-root
4 C-o    projectile-display-buffer
4 D      projectile-dired-other-window
4 a      projectile-find-other-file-other-window
....

vs. standard output:

projectile-command-map is a variable defined in ‘projectile.el’.
Its value is shown below.

Keymap for Projectile commands after ‘projectile-keymap-prefix’.
  This variable may be risky if used as a file-local variable.

Value:
(keymap
 (33 . projectile-run-shell-command-in-root)
 (38 . projectile-run-async-shell-command-in-root)
 (53 keymap
     (68 . projectile-dired-other-window)
     (15 . projectile-display-buffer)
...
Pilferage answered 25/9, 2021 at 5:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.