如何在Emacs中筛选特定前缀的已绑定快捷键命令(兼容ivy-mode)
在 Emacs + Ivy 中实现 M-x 仅展示带快捷键绑定的命令
核心思路
要实现输入命令前缀时仅显示有快捷键绑定的命令,我们需要:
- 从当前全局/局部 keymap 中提取所有绑定了快捷键的命令(与
describe-keymap实现原理一致) - 修改
counsel-M-x的候选列表,仅保留这些命令 - 兼容 Ivy 的前缀过滤逻辑,确保输入前缀时能精准筛选目标命令
实现代码
1. 编写命令提取函数
这个函数会遍历当前全局和局部 keymap,收集所有绑定了快捷键的命令:
(defun get-bound-commands () "获取当前全局与局部 keymap 中绑定了快捷键的命令列表" (let ((commands ()) (keymaps (list (current-global-map) (current-local-map)))) (dolist (km keymaps) (when km (map-keymap (lambda (_key def) (when (commandp def) (push def commands))) km))) (delete-dups commands)))
2. 实现带过滤的 counsel-M-x 变体
直接定义一个新命令,调用它时仅展示绑定了快捷键的命令:
(defun counsel-M-x-bound-only () "仅显示有快捷键绑定命令的 counsel-M-x 版本" (interactive) (let ((counsel-M-x-candidates (get-bound-commands))) (counsel-M-x)))
之后可以把这个命令绑定到常用快捷键,比如:
(global-set-key (kbd "M-X") #'counsel-M-x-bound-only)
3. 可选:添加开关功能(不替换原命令)
如果想保留默认counsel-M-x的功能,可通过开关控制是否仅显示绑定命令:
(defvar my-counsel-M-x-show-only-bound nil "控制 counsel-M-x 是否仅展示带快捷键绑定的命令") (defun toggle-counsel-M-x-bound-only () "切换 counsel-M-x 的绑定命令过滤状态" (interactive) (setq my-counsel-M-x-show-only-bound (not my-counsel-M-x-show-only-bound)) (message "counsel-M-x 仅显示绑定命令: %s" my-counsel-M-x-show-only-bound)) (advice-add 'counsel-M-x-candidates :filter-return (lambda (candidates) (if my-counsel-M-x-show-only-bound (intersection candidates (get-bound-commands) :test #'eq) candidates)))
使用时调用M-x toggle-counsel-M-x-bound-only即可开启/关闭过滤功能。
使用示例
比如在 Org Mode 中调用M-X(或开启开关后的M-x),输入org-table,此时只会列出带有快捷键绑定的 Org 表格相关命令,而非所有包含该前缀的命令。
内容的提问来源于stack exchange,提问作者aartist
相关产品推荐
相关产品推荐

