为特定的Emacs模式设置自定义按键绑定

63

虽然我知道如何在Emacs中设置全局键绑定,但是我发现即使是在Google上搜索本地(特定于minor mode)的键绑定代码也很困难。例如,我在我的.emacs中有这样的代码:

;; PDFLaTeX from AucTeX
(global-set-key (kbd "C-c M-p")
        (lambda ()
          (interactive)
          (shell-command (concat "pdflatex " buffer-file-name))))

我不想全局设置。是否有类似 local-set-key 的函数?


越来越多的时候,我会去 Emacs Wiki 寻求帮助:http://www.emacswiki.org/emacs/KeyBindingDiscussion。在那里,它展示了如何将一个按键绑定到模式按键映射中,并且还展示了如何找到该映射。 - drysdam
是的... 我已经看到了那个,但我一直得到符号的值作为变量是空的:LaTeX-mode-map。嗯... - aL3xa
4个回答

53

我使用以下内容:

(add-hook 'LaTeX-mode-hook
          (lambda () (local-set-key (kbd "C-0") #'run-latexmk)))

仅为LaTeX模式定义绑定。


2
# 对我来说是多余的。 - doctorate
我不得不设置'latex-mode-hook(没有大写字母)。我还发现#是不必要的。 - hunse
11
关于 #' 符号引用的使用,建议养成良好习惯。请查阅 http://endlessparentheses.com/get-in-the-habit-of-using-sharp-quote.html 了解详情。 - codeasone

49
要在某个模式下绑定按键,您需要等待该模式加载后再定义按键。可以通过要求该模式或使用eval-after-load来实现。
   (eval-after-load 'latex 
                    '(define-key LaTeX-mode-map [(tab)] 'outline-cycle))

不要忘记 ' —— eval-after-load 不是一个宏,所以它需要它们。


10
如何以编程方式确定eval-after-load的第一个参数? - ealfonso
我认为只要提供任何属于该模式的函数即可 - 例如,使用 'LaTeX-mode 而不是 'latex 也可以。 - Artyom
对我来说,变量被称为latex-mode-map(全小写)。LaTeX-mode-map不存在。 - Anton Eliasson
2
[(tab)](kbd "TAB") 的旧语法。 - Lenar Hoyt
3
@LenarHoyt说:实际上,[(tab)][tab]是相同的,它们都是在GUI版本的Emacs中按下TAB键时发送的按键序列。而(kbd "TAB")则与[?\t]相同,在文本终端中按下相同的TAB键时发送该按键序列(这也是在按下C-i时发送的相同按键序列)。这两个选项通过function-key-map在Emacs内部进行“统一”,如果没有绑定到[tab],则将其重新映射到(kbd "TAB")。因此,如果您希望绑定在GUI和tty中均能起作用,最好使用(kbd "TAB") - Stefan

12
你需要确定该模式的键映射(例如,LaTeX-mode-map),并使用函数define-key。 作为示例,在LaTeX模式下激活outline-minor-mode时,我有以下内容:

你需要确定该模式的键映射(例如, LaTeX-mode-map),并使用define-key函数。例如,在LaTeX模式下激活outline-minor-mode的同时,我有:

  (define-key LaTeX-mode-map [(tab)] 'outline-cycle))
在这种情况下,主要模式(LaTeX)持有关键绑定,但也有一个 outline-minor-mode-map

4

其他答案都不能满足我的需求。因此,这可能会帮助其他人。如果我在Evil的正常模式下(基本上这意味着在Emacs中的任何地方),我希望Tab跳转到行的开头,但如果我在org-mode文档中,则希望它在org项目状态之间循环。

一个选择是在不同的绑定之间进行操作,并且每当我切换缓冲区时进行绑定重绑定(因为evil在其正常状态下仅允许每个键绑定一次)。

但更有效的选择是使Tab运行我的代码,该代码根据当前缓冲区使用的主要模式运行所需的函数。因此,如果我在org缓冲区中,此代码将运行org-cycle,否则它将在所有其他模式中运行evil-first-non-blank(转到行上的第一个非空格字符)。

我在这里使用的技术也可以通过调用您的自定义函数来使用global-set-key,适用于使用普通的非evil Emacs的人。

对于那些不了解Emacs lisp的人,"if"语句后的第一行是真实操作,而下一行是假操作。因此,如果major-mode等于org-mode,则我们运行org-cycle,否则我们在所有其他模式中运行evil-first-non-blank

  (defun my/tab-jump-or-org-cycle ()
    "jumps to beginning of line in all modes except org mode, where it cycles"
    (interactive)
    (if (equal major-mode 'org-mode)
        (org-cycle)
      (evil-first-non-blank))
    )
  (define-key evil-normal-state-map (kbd "<tab>") 'my/tab-jump-or-org-cycle)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接