【问题标题】:Show Keys In Emacs Keymap Value在 Emacs 键映射值中显示键
【发布时间】:2019-01-06 04:14:51
【问题描述】:

当我查询键盘映射的当前值时,例如使用M-: (current-local-map),它向我显示了以下内容:

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)))

我希望看到更有意义的东西而不是数字,例如 (control ?c) return。我怎么做 ?

【问题讨论】:

标签: emacs elisp


【解决方案1】:

您还可以使用 Melpa 中 helpful 包中的 helpful-variable 函数。 这是示例输出:

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
....

对比标准输出:

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)
...

【讨论】:

    【解决方案2】:

    对于更现代的方法,请使用 which-key 包中的 which-key-show-full-keymap 命令。它会要求您提供一个键盘映射,然后向您显示该键盘映射中的所有绑定,就像您按下前缀键时一样(如果启用了which-key-mode)。也就是说,在 minibuffer 中,干净整洁。

    来自文档:

    which-key-show-full-keymap 是一个交互式自动加载编译 Lisp 'which-key.el' 中的函数。

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

    使用 which-key 显示 KEYMAP 中的所有绑定。已选择 KEYMAP 从所有可用的键盘映射中交互。

    【讨论】:

    • 对于任何使用 Spacemacs 或 Doom 的人来说,这是最好的答案
    【解决方案3】:

    我只是根据 Gilles 的回答写了以下内容,所以我想我会发布它。

    我看到 Drew 的 describe-keymap 具有非常相似的基础,但也涵盖了各种其他用例,因此我倾向于建议将其用作更完整的解决方案;但是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)))))
    

    【讨论】:

    • 现象级函数。
    • (所以让我无法撤消/编辑我的编辑建议,所以我会在这里说我认为需要删除空白行,和/或我添加的行需要缩进)
    【解决方案4】:

    这就是你需要的:库help-fns+.el

    这给了你,作为 C-h M-k,命令describe-keymap,它给你一个人类可读的描述绑定到一个变量的任何键映射。例如:

    C-h M-k dired-mode-map

    定向模式映射 -------------- 有关更多信息,请查看手册。 `dired-mode' 缓冲区的本地键盘映射。 键绑定 --- -------- e .. f 目录查找文件 RET 目录查找文件 C-o 显示文件 C-t 前缀命令 ESC 前缀命令 SPC 直接下线 ! dired-do-shell 命令 #dired-flag-auto-save-files $dired-hide-subdir % 前缀命令 & dired-do-async-shell-command * 前缀命令 + 目录创建目录 - 否定论点 . dired-clean 目录 0 .. 9 位参数 : 前缀命令 dired-next-dirline ?目录摘要 直接搜索 Bdired-do-byte-compile C 直接复制 D 直接删除 G dired-do-chgrp H dired-do-hardlink L 直接加载 M dired-do-chmod O dired-do-chown 印刷品 Q dired-do-query-replace-regexp Rdired-do-rename Sdired-do-symlink 直接触摸 U dired-unmark-all-marks X dired-do-shell-command Z dired-do-compress ^ 目录 一个dired-find-alternate-file d dired-flag-file-deletion g 恢复缓冲区 h 描述模式 我dired-maybe-insert-subdir j dired-goto 文件 k dired-do-kill-lines l dired-do-redisplay m 定向标记 n 直接下一行 o dired-find-file-other-window p 上一行 q 退出窗口 s dired-sort-toggle-or-edit t 切换标记 你没有标记 v 目录视图文件 w dired-copy-filename-as-kill x dired-do-flag-delete y dired-show-file-type z kill-this-buffer 〜dired-flag-backup-files DEL dired-unmark-backward 鼠标脸 dired-mouse-find-file-other-window ?? C-t C-t image-dired-dired-toggle-marked-thumbs C-吨。图像定向显示拇指 C-t 图像-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 目录树向上 M-$ dired-hide-all M-= 目录备份差异 M-s 前缀命令 M-{ dired-prev-marked-file M-} dired-next-marked-file M-DEL dired-unmark-all-files M-s 前缀命令 M-s f 前缀命令 % & dired-flag-garbage-files %C 直接复制正则表达式 % H dired-do-hardlink-regexp % R dired-do-rename-regexp % S dired-do-symlink-regexp % d dired-标志文件-正则表达式 % g 目录标记文件包含正则表达式 % l 直接向下大小写 % m dired-mark-files-regexp % r dired-do-rename-regexp % u 大写 * 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-symlinks * c 目录更改标记 * m 指示标记 * s 目录标记子目录文件 * t dired-toggle-marks *你没有标记 * DEL dired-unmark-backward : d epa-dired-do-decrypt : e epa-dired-do-encrypt : s epa-dired-do-sign : v epa-dired-do-verify 直接撤消 直接下一行 上一条线 目录切换只读 直接撤消 M-s f C-s dired-isearch-文件名 M-s f ESC 前缀命令 M-s a C-s dired-do-isearch M-s ESC 前缀命令 M-s f C-M-s dired-isearch-filenames-regexp M-s 一个 C-M-s dired-do-isearch-regexp

    【讨论】:

    • 谁:愿意解释一下你为什么不赞成这个答案吗?
    • 我已经安装了(通过package-installhelp+help-fns+,但没有定义C-h M-kC-h C-k,也没有describe-keymap 命令。
    • @VladimirPanteleev:听起来您已经(或您加载的代码)将键盘映射 help-mapC-h 移动了。 <f1> 还绑定它吗?例如。 <f1> M-k。但是,您通常会咨询帮助,这是绑定这些命令的前缀键。例如。 (define-key help-map "\M-k" 'describe-keymap)。但是如果M-x describe-keymap 甚至无法识别,那么您一定没有正确加载(“安装”)文件(“包”)。 M-: (featurep 'help-fns+) 告诉你什么?
    • 在我明确加载它之后它工作了。我认为安装软件包可以做到这一点。
    • 你的答案仍然是C-h C-k,我认为应该是C-h M-k
    【解决方案5】:

    这是describe-bindings (C-h b) 为您提供的穷人实现,但仅限于特定的键盘映射。格式不是很好,但应该可以帮助您入门:

    (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)
    

    我通过评估两者进行了测试:

    (describe-keymap emacs-lisp-mode-map)
    (describe-keymap 'emacs-lisp-mode-map)
    

    【讨论】:

    • 但是您不需要重新实现描述绑定。只有可用的功能——describe-bindings——应该能够完成任何任意键映射所需的操作。考虑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'函数;反过来,documentation' function uses substitute-command-keys' 又准确地调用 `describe-bindings' 来格式化源文档字符串中的 \{MAPVAR} 表达式。
    • 在研究了 Elisp 源代码之后,我发现与我上面写的以及从文档中可以推断出的内容相反,describe-bindings' doesn't take a keymap as an argument. :( But the documentation for substitute-command-keys' 显然是这样假设的:“表格 \{MAPVAR} 被摘要替换(由 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' 制作......
    • 这正是describe-keymap, in help-fns+.el 所做的。请参阅上面的答案。
    【解决方案6】:
    • 您知道命令C-h m (describe-mode),它通常显示当前主要和次要模式的描述,通常带有它们的键盘映射?

    • (substitute-command-keys "\\{foo-map}")describe-mode 在内部用于生成键盘映射 foo-map 的用户友好描述。

    • 如果您想要更接近键映射结构的东西,API 记录在 Emacs Lisp 手册的“分类事件”中。例如,
      (event-modifiers 33554445) ==> (shift control)
      (format "%c" (event-basic-type 33554445)) ==> "m"

    【讨论】:

    • 这是一个不错的简单答案! (只需评估 (substitute-command-keys "\\{foo-map}");我为什么没有想到这个!)
    • ido-mode 可能是一种模式的例子,describe-mode 没有列出键盘映射。
    猜你喜欢
    • 2010-10-05
    • 2013-12-18
    • 1970-01-01
    • 2011-03-12
    • 1970-01-01
    • 1970-01-01
    • 2019-07-23
    • 2013-12-24
    相关资源
    最近更新 更多