特定于emacs模式的自定义键绑定:local-set-key vs define-key

时间:2012-03-22 07:51:45

标签: emacs elisp

在定制我的.emacs文件几年后,我发现我使用了两种不同的文件 用于设置主模式特定键绑定的各种构造:

1。使用挂钩和local-set-key。例如:

(defun my/bindkey-recompile ()
  "Bind <F5> to `recompile'."
  (local-set-key (kbd "<f5>") 'recompile))
(add-hook 'c-mode-common-hook 'my/bindkey-recompile)

我想说这个结构可以很容易地使用相同的键绑定 通过向所有相关的主模式添加相同的功能来实现不同的主要模式 钩子(换句话说,“我想要哪些键绑定”明显分开 来自“我想要的模式”)。但是,我不舒服 事实上,这样的自定义是在缓冲级别完成的,而我会这样做 认为他们属于主要模式。

2。使用define-key(通常与eval-after-load合并延迟   评估,直到加载相关的键映射)。例如:

(eval-after-load "cc-mode"
  '(progn
     (define-key c-mode-map   (kbd "C-c o") 'ff-find-other-file)
     (define-key c++-mode-map (kbd "C-c o") 'ff-find-other-file)))

相比之下,这个构造本身定制了主模式,但是更少 灵活:如果我想为另一种模式使用相同的键绑定,我会有 找到此模式的正确文件和键映射名称,几乎重复 eval-after-load表达式(虽然这可能是自动化的 一个函数/宏)。

问题:虽然两种构造类型都运行良好并产生结果I. 想要,它们在技术上是非常不同的,设置键绑定 不同时间的不同键盘图。所以我的问题是:在这两个中 构造,是否有“首选/更好”的做事方式? (或者也许是“最好的” 构造是第三个我不知道的吗?)

“首选/更好”,我的意思是:

  1. 不太容易破坏新的emacs版本
  2. 不太容易受到干扰/被主动小模式干扰
  3. 更加惯用/可读/可与他人共享

2 个答案:

答案 0 :(得分:21)

我相信你描述的两种方法与你想的不同。

请注意,local-set-key确实会评估(define-key map key command),其中map(current-local-map)的值,通常由主要模式设置。

所以虽然他们可以做不同的事情;大部分时间唯一真正的区别是,local-set-key调用的钩子函数将重复/冗余地设置相同的键,而另一种方法只设置一次。

您可以通过在模式挂钩中使用local-set-key,在使用它之后删除该挂钩函数,然后在相同的主模式下创建新缓冲区并测试绑定来自行演示。

  

不太容易破坏新的emacs版本

我想你可能会争辩说键盘图的名称将来可能会改变,因此不需要知道名称是一个优势,但你可以同样地说模式钩子的名称可能会改变。我不认为担心任何一个问题就足够了。

有一点需要注意的是,local-set-key即使主要模式没有建立current-local-map也会有效,我认为就广义方法而言,它会稍微强一些。

  

不太容易受到干扰/被主动小模式干扰

没有区别。所有次模式键盘映射都优先于所有主模式键盘映射,这两种方法都不会对minor-mode-map-alist的顺序产生任何影响(这决定了次模式键映射的优先级)。

  

更加惯用/可读/可与他人分享

它们在我的脑海里都是完全可读的,所以我也无法在这方面区分它们。

我说只要在每种情况下使用最适合您的方法。为了代码的一致性,我认为对大多数事情采用标准方法是好的,但我怀疑你选择哪一个很重要。显然,通过不必要地评估相同的代码可以节省几个CPU周期,但这应该是非常重要的,无论如何都无关紧要。

我认为最明显的情况就是你已经提到的那个 - 如果你想使用一个公共钩子将相同的绑定应用于多个模式(但不是所有模式 - 为此,我完全推荐creating a custom minor mode),然后在该钩子中的local-set-key绝对是可行的方法。

答案 1 :(得分:0)

我有很多自定义键盘命令,我无法用各种方式在Emacs中设置它们,而且所有这些键盘都相互覆盖,所以我按照bind-key安装了John Wiegley的my relevant answer

(require 'bind-key)
(bind-key "C-l" 'goto-line)