使用挂钩设置主要模式键与将其添加到模式图之间的区别


13

假设我已经下载了一个名为的主模式magical-mode,它有自己的神奇键盘映射magical-mode-map。此模式还提供了一个钩子magical-mode-hook,该钩子每次magical-mode成为缓冲区的主要模式时都会运行。现在,我想修改我的初始化文件,以添加一些自定义键绑定以在该模式下使用。

似乎有(至少)两种方法来为设置自定义键绑定magical-mode。我最常看到的是:

(defun my-magical-keys ()
  (local-set-key (kbd "C-i") 'previous-line)
  (local-set-key (kbd "C-k") 'next-line)
  (local-set-key (kbd "C-j") 'backward-char)
  (local-set-key (kbd "C-l") 'forward-char))
(add-hook 'magical-mode-hook 'my-magical-keys)

但是也可以这样进行:

(define-key magical-mode-map (kbd "C-i") 'previous-line)
(define-key magical-mode-map (kbd "C-k") 'next-line)
(define-key magical-mode-map (kbd "C-j") 'backward-char)
(define-key magical-mode-map (kbd "C-l") 'forward-char)

第二种方法对我来说似乎更干净。 一种方法比另一种方法有任何优势吗?


基本运动命令使用相同的键。请注意:这是一场艰苦的战斗,您可能需要在开始执行此操作之前对键绑定有更多的了解。
tarsius

@tarsius确实是一场艰苦的战斗。我已经下来之前,这条道路,但现在我回来了良好的醇” C-nC-p。该示例只是伪代码。我想提出一些非常简单的示例模式和示例绑定,以使绑定本身不会分散问题的实际目的。
nispio 2014年

Answers:


15

第二种方法是可取的,因为它只修改一次模式的键盘映射。

如果使用模式的挂钩进行操作,则每次在某些缓冲区中启用该模式时都会调用该挂钩。通常,再次执行此操作实际上不会产生任何效果,因为这些键只是再次绑定到它们已经绑定的对象上。主模式键映射是主模式的“本地”,而不是使用该模式的单个缓冲区,因此,如果使用更改这些缓冲区之一的绑定,local-set-key则会影响具有相同主模式的所有缓冲区。

local-set-key主要旨在用作命令。确定要永久define-key保留某些更改后,将模式keymap用作第一个参数。

如果您使用钩子一遍又一遍地修改键盘映射,则可能与的预期用途冲突local-set-key。说您使用过,M-x local-set-key RET C-i fancy-previous-line RET因为您想试用的该变体previous-line。如果现在打开一个使用相同主模式的新缓冲区,则该钩子将再次运行并覆盖使用该主模式的所有缓冲区中的临时绑定,包括您之前使用的缓冲区local-set-key


我喜欢这个答案,但是如果自动加载模式会怎样?
remvee 2014年

2
您可以延迟加载任何代码,直到加载了一些库之后:(eval-after-load 'magical '(progn (define-key magical-mode-map ...) ...))
tarsius 2014年

4

使用(define-key my-magical-mode-map …)是正常的方式。

当您使用钩子和时local-set-key,每次您在某些缓冲区中进入“我的魔法”模式时,都会添加键。这很奇怪,因为local-set-key会影响处于相同模式的所有缓冲区(更常见的是,所有使用相同键映射的缓冲区)。因此,如果您对键盘映射进行了任何更改,则每次您在缓冲区中进入“我的魔法”模式时,它们都会被覆盖。

如果您在不同位置自定义按键映射,则第二种方法也可能会造成混淆。挂钩的执行顺序与添加挂钩的顺序相反,直到第一次执行挂钩时,您都看不到自定义的任何痕迹。


2

您显然不是在询问定义主模式键映射,而是在询问用户代码以在现有的主模式键映射中添加或更改一些键绑定。您说的是“习惯”,这暗示了这一点,但我们也最好将其弄清楚。

可以肯定的是,您最常看到的不是通常用于定义主模式键盘映射的内容。例如,它不是在Emacs源代码中找到的。这不是 Elisp手册(节点Major Mode Conventions)中推荐的内容。

只是想摆脱它,让其他人清楚:您通常不想使用模式挂钩来定义主模式映射。


对于您有关用户键自定义的问题-

无论如何,并不是local-set-key您应该在模式挂钩中使用它。只需define-key与第一个示例中的主模式键盘映射一起使用即可。@tarsius已经很好地解释了这一点。

除此之外,答案是:总的来说,是一次绑定所有键(define-key与模式映射一起使用),还是每次进入模式时都使用钩子将它们绑定,这没有什么区别。

但是,如果映射中的绑定发生更改,可能会有所不同-例如,通过加载其他更改绑定的代码。在这种情况下,将绑定放在主模式钩子上可确保在进入模式时将建立绑定。也就是说,它确保将它们制成,但是不能确保之后没有其他更改(例如,同一钩子上的另一个函数,此后调用)。请记住,您对钩子上运行的内容和时间几乎没有控制权-除非,当然,除非您确定只有自己的代码会使它弄乱。

我能想到的是,这是唯一的效果差异。让您决定何时将差异视为一种或另一种方法的优势。FWIW,看看我自己的代码,我想我从来没有在模式挂钩上绑定过键。


谢谢。我修改了这个问题,以期希望澄清一个事实,即我没有创建主模式,只需将自己的键绑定添加到现有主模式即可。
nispio 2014年

0

您的命名有点混乱(我认为您应该my在问题的第二部分中删除)。

无论如何,假设my-magical-keys是的用户定制功能magical-mode,我看到一个明显的优势。轻松地一次移除(通过remove-hook)钩子。

第二个优点是功能的含义。我的意思是它们是可重用的。您可以将它们挂接到其他模式。

编辑:

正如@tarsius所指出的那样,删除钩子将无法恢复原始行为,而将功能转换为次要模式可能会更好。


我正在自定义一种称为的假设主要模式my-magical-mode。但是,如果my-前缀的使用令人困惑,我当然可以编辑问题。
nispio 2014年

是的,这样会更好,通常my-是为用户功能添加(至少在我看来是这样)。
kindahero 2014年

1
同意 我只是应用了,my-所以没有人会想到我正在问如何配置称为magical-mode(如果存在)的实模式。
nispio 2014年

1
不,删除钩子将无法恢复旧的绑定。至少直到重新启动Emacs为止,然后我才认为不必注释掉一行而不是四行,这是一个很大的改进。
tarsius

2
至于您提到的第二个优点:这里最好创建一个次要模式,然后可以为各种主要模式和/或仅使用特定主要模式的某些缓冲区启用次要模式。
tarsius
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.