大多数emacs模式都包含某种激活其功能的前缀。例如,当使用 GUD 时,“next”是“C-c C-n”。在这些模式中,许多模式提供了特殊的缓冲区,其中一个可以使用单个键来激活某些功能(例如,只需“n”或“p”来读取 GNUS 中的下一个/上一个邮件)。
然而,并非所有模式都提供这样的缓冲区,并且重复输入前缀可能很烦人。是否有一个众所周知的elisp位允许在一段时间内对所有输入进行特殊的前缀键规范? (例如,在点击ESC或其他一些受制裁的密钥之前)
答案 0 :(得分:15)
我同意Joe Casadonte的回答,即走法是定义自己的次要(或主要)模式。
话虽如此,你的问题很有意思。
这是一个解决方案,提示您输入一个键序列,并采用前缀击键并将该键盘映射提升到顶层。
e.g。假设以下键映射:
M-g ESC Prefix Command
M-g g goto-line
M-g n next-error
M-g p previous-error
当您运行M-x semi-modal-minor-mode
时,它会提示您进行一些击键。如果输入M-g n
,则会设置以下键绑定:
ESC Prefix Command (same as M-g ESC)
g goto-line
n next-error
p previous-error
所以现在n
不会自动插入,而是跳转到下一个错误。请参阅下面的代码。
注意:启用此次要模式时,<f12>
绑定到禁用次要模式的命令。这是因为键绑定可能会很好地禁用您的Emacs(例如,如果M-x
有新的键绑定,该怎么办)。
编辑添加这些想法:小模式变量最初是缓冲本地的,但除非你还制作次模式 - alist变量,否则这不起作用缓冲本地(duh)。但是,你也(可能)不想在迷你缓冲区中使用这些绑定...所以,我不打算测试它b / c它真的取决于你想要什么,但我已经添加了对代码的评论反映这种想法。
没有进一步的麻烦:
(defvar semi-modal-minor-mode-keymap (make-sparse-keymap)
"keymap holding the prefix key's keymapping, not really used")
(defvar semi-modal-minor-mode-disable-key (kbd "<f12>")
"key to disable the minor mode")
(defun semi-modal-minor-mode-disable ()
"disable the minor mode"
(interactive)
(semi-modal-minor-mode 0))
(define-minor-mode semi-modal-minor-mode
"local minor mode that prompts for a prefix key and promotes that keymap to the toplevel
e.g. If there are bindings like the following:
M-g ESC Prefix Command
M-g g goto-line
M-g n next-error
M-g p previous-error
And you enter 'M-g n' when prompted,
then the minor mode keymap has the bindings
g -> goto-line
n -> next-error
p -> previous-error
ESC -> Prefix Command (same as M-g ESC)
The variable semi-modal-minor-mode-disable-key is bound to disable the minor mode map.
This is provided because often the mappings make the keyboard unusable.
Use at your own risk."
nil " Semi" semi-modal-minor-mode-keymap
(make-local-variable 'semi-modal-minor-mode)
(make-local-variable 'minor-mode-map-alist)
(let ((pair-holding-keymap-to-modify (assq 'semi-modal-minor-mode minor-mode-map-alist)))
(setcdr pair-holding-keymap-to-modify (make-sparse-keymap))
(if semi-modal-minor-mode
(let (key
keymap)
;; all but last (b/c we want a prefix
(setq key (substring (read-key-sequence "Enter a full key combination, the prefix will be used: ") 0 -1))
(if (and (not (equal "" key))
(not (equal (kbd "C-g") key))
(let ((semi-modal-minor-mode nil))
(keymapp (setq keymap (key-binding key)))))
(progn
(setcdr pair-holding-keymap-to-modify (copy-keymap keymap))
(when semi-modal-minor-mode-disable-key
(define-key (cdr pair-holding-keymap-to-modify)
semi-modal-minor-mode-disable-key 'semi-modal-minor-mode-disable)))
(semi-modal-minor-mode 0))))))
答案 1 :(得分:1)
Emacs中键绑定的模式特定(模态?)部分是通过覆盖通用全局映射的各种本地映射来实现的。大多数主要和次要模式都定义了自己的本地地图;例如,有一个gud-mode-map。仅当当前缓冲区处于相应模式时,才会激活本地键映射中的键绑定。您可以通过模式的挂钩自定义特定于模式的键映射。例如,您可以将此代码段放入〜/ .emacs
中(add-hook 'gud-mode-hook (lambda () (local-set-key (kbd "C-n") (lookup-key (current-local-map) (kbd "C-c C-n")))))
有关键盘图的更多详细信息,请参阅Elisp reference manual。
答案 2 :(得分:1)
这里的基本问题是本身没有当前的键盘映射。有一个全局键映射被主模式的键映射覆盖,而键映射又被一个或多个次模式键映射覆盖(并且它们可以以某种定义的方式相互踩,我敢肯定)。定义新的主模式仍然会使次模式键起作用,定义新的次模式只会影响您在次模式键映射中定义的任何键。
例如,只要次要模式处于活动状态,您就可以定义一个可以执行所需操作的次要模式。您定义了一个新的次要模式my-gud-mode
,它将拥有自己的键盘映射。然后你必须为它定义所有的键映射(例如n,p等),你还必须定义你不想工作以绑定到函数{{1}的所有键。 }。这是真正的痛苦,重新映射所有其他键。不过,次要模式很容易打开和关闭;这是优势。
乍一看定义一个新的主要模式会更容易,因为它可以让你在一次拍摄中覆盖更多的“当前键盘图”。它应该注意缓冲区局部变量中的当前主要模式,以便稍后在临时主模式关闭时可以恢复它。但是你仍然会有其他次要模式侵入你的键盘映射,所以它不会是“纯粹的”。
在这种情况下我做的是定义一个更简单的前缀!对于我每天都在使用的东西,我每天都给他们一个功能键(例如我将F1作为我的jabber-mode键)。对于不那么直接有用的东西,我还有另外两个功能键,F3和F12(我确定我很久以前就选择了它们,但我不再记得原因)。 F3定义了始终可用的键,无论主要模式如何。 F12定义了与主模式相关的键。一些例子:
我已将F3-m-设置为切换主要模式的前缀(例如F3-mp切换到cperl模式)和F3-M-作为次模式的前缀(例如F3-Mv切换视图模式) 。这些都是可用的,因此您可以执行类似绑定F3-g-的操作作为您的gud前缀,并为之前的类型输入F3-g-p等等。
我的F12键与模式有关。因此,在直接模式下,F12-e将在当前文件上调用ignore
,在emacs-lisp模式下,F12-e将调用dired-nt-open-in-excel
。不知怎的,我从来没有让他们感到困惑。
如果您需要帮助来定义这样的键盘映射,请告诉我。
答案 3 :(得分:0)
Viper模式允许您在可视模式下使用“esc”键输入命令到键或键序列。返回插入模式“i”。
请查看viper-in-more-modes.el其使用viper-modify-major-mode
我还想使用viper-vi-global-user-map:来自我的.emacs文件的snippet。