如何在Emacs中为自定义次要模式创建快捷键绑定

15

问题:

如何为次要模式创建自定义按键绑定?类似于这样

以下是我目前的代码。我正在尝试让一个自定义按键绑定起作用:

(define-minor-mode num-mode
       "Toggle the Num pad keys.
     With no argument, this command toggles the mode.
     Non-null prefix argument turns on the mode.
     Null prefix argument turns off the mode.

     When Num mode is enabled, the num pad inserts the
     keys you see on the pad. This may over ried existing
     definitions, and is probably only usefule if you aref
     running Emacs through a terminal."
      ;; The initial value.
      nil
      ;; The indicator for the mode line.
      " NumPad"
      ;; The minor mode bindings.
      ;; This doesn't work right now!!!!
       '(((kbd "<kp-1>") . "a"))
      :global 1
)

调用自定义小模式"num-mode"并在 mini buffer 中验证其打开后,当我在数字键盘上按下 "1" 键时,我收到错误信息 "<kp-1> 未定义"。我想要的是在按下 "<kp-1>" 键时,将 a 打印出来。 (仅作测试)
背景:通常我使用数字键盘在不同的缓存区之间移动(箭头键让我朝着相应的方向移动)。这是全局设置。我想创建一个可以在需要时使用数字键盘简单输入数字的小模式。
默认情况下,我的数字键盘上的键没有定义。我使用 <kp-0><kp-9> 来为数字键定义按键绑定。
我可以创建一个可以调用的小模式,但我无法绑定任何按键。这对所有按键绑定都适用,包括未在其他地方定义的按键绑定。
感谢任何帮助!
3个回答

23

简短回答

问题行:

'(((kbd "<kp-1>") . "a"))

解决方法(强制宏的评估):

;; Single quote changed to back-quote and added a comma
`((,(kbd "<kp-1>") . "a"))

长答案

define-minor-mode宏允许您相对轻松地创建次要模式(就Emacs而言)。

我将先展示如何完成,然后解释其工作原理:

一般形式为:

(define-minor-mode NAME-mode
  "DOCUMENTATION"
  INIT-VALUE
  "LIGHTER"
  ;; keymap
  '(
    (KEY-SEQUENCE . DEFINITION)
    (KEY-SEQUENCE . DEFINITION)
    ... ETC ...
   )
  ;; other options
  :KEYWORD-ARG VALUE
  :KEYWORD-ARG VALUE
  ... ETC ...       
)

强制求值 alist 中宏的具体示例:

;; Custom Minor Mode
(define-minor-mode custom-mode
  "Doc description, yada yada yada."
  ;; The initial value - Set to 1 to enable by default
  nil
  ;; The indicator for the mode line.
  " CustomMode"
  ;; The minor mode keymap
  `(
    (,(kbd "C-c C-a") . some-command)
    (,(kbd "C-c C-b") . other-command)
    ("\C-c\C-c" . "This works too")
   )
   ;; Make mode global rather than buffer local
   :global 1
)

如果您希望使用变量作为键映射表,另一种选择是在次要模式声明之前定义键映射变量和键映射表可以像这样进行:

(defvar custom-mode-keymap (make-keymap) "num-mode keymap.")
(define-key custom-mode-keymap (kbd "C-c C-a") 'some-command)

然后,在您的较小模式定义中,只需简单地列出键位图的变量名称,而不是alist

(define-key custom-mode-keymap (kbd "C-c C-b") 'other-command)
;; Num pad enable
(define-minor-mode custom-mode
...

      ;; The minor mode bindings.
      custom-mode-keymap

工作原理

从上到下,紧接着 define-minor-mode 我们定义了一个命令名称来切换次要模式。在这种情况下是 custom-mode(使用 M-x custom-mode 命令来切换模式)。这也定义了同名的变量。

在命令名称之后,我们用引号列出了次要模式的文档字符串。这可以很长。

接下来有几个选择。最简单的选择是仅列出三个内容和任何附加选项。下面三个必须按照以下顺序列出:

  1. 次要模式变量的初始化值。如果为 nil,则默认将模式关闭。除 nil 以外的其他值都将默认打开模式。

  2. 较轻的方式。当次要模式启用时,在底部的模式行中显示。这应该很简短,通常以空格开头会有帮助。

  3. 键映射。键映射可以定义为变量或关联列表(alist)。由于使用 alist 更简单和更短,因此我在示例中使用了它。关联列表应该采用以下形式 (key-sequence . definition)

如果将键映射定义为关联列表,则需要注意一些问题,特别是如果您习惯于定义全局按键绑定。首先,不要在命令名称中加引号。其次,如果要使用宏,必须强制它求值 (在SO上)。这可以用反引号(而不是单引号)和逗号的组合来完成。您可以在示例中看到如何使用 kbd 宏进行此操作。如果您不使用 kbd 宏,则还包括一个按键定义。如果您只是在键映射中引用字符串,则在按下定义的键组合时会打印出该字符串(就像定义全局键绑定一样)。

如果您没有使用反引号和逗号的组合强制求值 kbd 宏,则键映射将无法使用 kbd 宏。 就像这样:

`((,(kbd "C-c C-a") . some-command))

最后,您可以使用形式为:blah的关键字参数添加其他选项。在我的例子中,我使用了:global。我们可以使用关键字参数定义整个模式,但是只列出初始化值、轻量级和正确顺序的keymap更短。


3
你需要在你的小模式定义中添加类似这样的代码:
(defvar your-mode-map
  (let ((map (make-sparse-keymap)))
    (set-keymap-parent map parent-mode-shared-map)
    (define-key map "\C-c\C-a" 'some-defun)
    (define-key map "\C-c\C-b" 'some-other-sexp)
    map)

(use-local-map your-mode-map)

你可以查看EmacsWiki中提供的众多模式作为参考。

我试图使用类似这里的格式:http://www.gnu.org/software/emacs/elisp/html_node/Defining-Minor-Modes.html 中的示例。如果您能展示该格式的完整定义,那就太好了。 - Peter Ajtai
1
clojure-mode 使用这种风格来设置本地按键绑定 - 在这里查看它的源代码 - http://github.com/jochu/clojure-mode/blob/master/clojure-mode.el - Bozhidar Batsov
嗯...是的,我猜所有这些例子都使用了不同的格式。我试图使用更紧凑的格式,在其中将keymap简单地列在define-minor-mode中的alist中。但我无法让kbd宏在alist中工作。 - Peter Ajtai

2
请看一下这个(仅用于了解按键绑定):

http://www.gnu.org/software/emacs/manual/html_node/emacs/Key-Bindings.html#Key-Bindings

http://www.gnu.org/software/emacs/manual/html_node/emacs/Local-Keymaps.html#Local-Keymaps

链接
良好编写的主模式将在末尾运行挂钩。因此,您可以使用挂钩来定义键绑定。次要模式通常没有挂钩。在这种情况下,您可以首先调用“(require ‹minor mode feature symbol›)” ,然后定义您的键绑定。
另外,您可能需要查看: http://www.cs.utah.edu/dept/old/texinfo/emacs19/emacs_35.html#SEC347 也许这里接受的答案也能帮助您。

谢谢您提供的上一个答案链接,它给了我所需的提示。 - Peter Ajtai

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