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

Pet*_*tai 11 emacs elisp keyboard-shortcuts minor-mode

题:

如何为次要模式创建自定义键绑定?像这样的东西.

这是我到目前为止所拥有的.我试图让一个自定义键绑定工作:

(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
)
Run Code Online (Sandbox Code Playgroud)

当我在调用我的自定义次要模式后点击数字键盘上的"1","num-mode"并验证它在迷你缓冲区中是否打开时,我收到错误<kp-1> is undefined.我想要发生a的是在我击中​​时指针所在的位置打印出来<kp-1>.(只是一个测试)

语境:

所以,我通常使用我的数字键盘在缓冲区之间移动(箭头键移动我适当的方向).这是全球设定的.我想创建一个次要模式,当我想使用我的数字键盘输入数字时,我可以调用它.

默认情况下,我的num-pad上的键未定义.我使用<kp-0><kp-9>定义键绑定的数字键盘键.

我可以创建一个我可以调用的次模式,但是我不能附加任何键绑定.对于所有键绑定都是如此,包括未在其他任何位置定义的键绑定.

谢谢你的帮助!

Pet*_*tai 20

简答

问题线:

'(((kbd "<kp-1>") . "a"))
Run Code Online (Sandbox Code Playgroud)

解决方案(强制评估宏):

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

答案很长

定义小调模式宏,您可以相对容易地创建次要模式(尽可能的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 ...       
)
Run Code Online (Sandbox Code Playgroud)

在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
)
Run Code Online (Sandbox Code Playgroud)

另一种方法是,如果您希望为键映射使用变量,则可以在次模式声明之前定义键映射变量和键映射,如下所示:

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

然后,在您的次要模式定义中,简单列出键映射的变量名称,而不是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
Run Code Online (Sandbox Code Playgroud)

一切如何运作

从上到下,在define-minor-mode之后,我们定义一个命令名来切换次要模式.custom-mode在这种情况下(M-x custom-mode切换模式).这也定义了同名变量.

在命令名称后面,我们在引号中列出次要模式的文档字符串.这可以和你想要的一样长.

接下来我们有几个选择.最简单的选择是简单列出三件事,然后列出任何其他选项.这三件事必须按以下顺序列出.这三件事是:

  1. 次要模式变量的初始化值.nil将默认关闭模式.除了nil默认情况下会有其他东西.

  2. 打火机.打火机就是当您的次要模式打开时底部模式行中显示的内容.这应该很短,并且在格式化方面,它通常有助于用空格启动它.

  3. 键盘图.键映射可以定义为变量或alist(关联列表).由于使用alist更简单,更短,这就是我在示例中使用的.alist应该是这种形式(key-sequence . definition).

如果将键映射定义为alist,则需要注意一些事项,特别是如果您习惯于定义全局键绑定.首先,不引用命令名称.其次,如果你想使用宏,你必须强制它进行评估(和SO).这是通过反引号(不是单引号)和逗号的组合来完成的.您可以在使用kbd宏的示例中看到这是如何完成的.如果你不使用kbd宏,我还包括一个击键定义.如果您只是在键盘映射中引用一个字符串,那么在按下定义的键组合时会打印出来(就像定义全局键绑定一样).

如果不强制使用后引号和逗号的组合来评估kbd宏,则键映射将无法与kbd宏一起使用.像这样:

`((,(kbd "C-c C-a") . some-command))
Run Code Online (Sandbox Code Playgroud)

最后,您可以使用表单的keyword-args添加其他选项:blah.在我使用的例子中:global.我们可以使用keyword-args定义整个模式,但只需按正确的顺序列出init值,light和keymap就可以了.