如何在emacs中编写密钥绑定以便于重复?

如何在emacs中编写密钥绑定以便于重复?,emacs,elisp,Emacs,Elisp,假设我将密钥绑定到某个函数,如下所示: (global-set-key (kbd "C-c =") 'function-foo) 现在,我希望密钥绑定的工作方式为: 在我第一次按下C-C=之后,如果我想重复函数foo,我不需要再次按下C-C,只需重复按下=。然后,在我调用函数foo足够多次后,我可以只按除=(或显式按C-g)以外的键退出 如何执行此操作?您希望您的函数foo使用设置临时覆盖图这可能就是您要查找的内容: (defun function-foo () (interactive)

假设我将密钥绑定到某个函数,如下所示:

(global-set-key (kbd "C-c =") 'function-foo)
现在,我希望密钥绑定的工作方式为:
在我第一次按下
C-C=
之后,如果我想重复函数foo,我不需要再次按下
C-C
,只需重复按下
=
。然后,在我调用函数foo足够多次后,我可以只按除
=
(或显式按
C-g
)以外的键退出


如何执行此操作?

您希望您的
函数foo
使用
设置临时覆盖图

这可能就是您要查找的内容:

(defun function-foo ()
  (interactive)
  (do-your-thing)
  (set-temporary-overlay-map
    (let ((map (make-sparse-keymap)))
      (define-key map (kbd "=") 'function-foo)
      map)))
有一个软件包正好满足你的需要。文档有点稀少,但是通过查看github上的大量emacs配置,您可以了解如何使用它。例如(摘自):

(需要“smartrep”)
(smartrep定义密钥)
全局映射“C-q”(“n.”(滚动其他窗口1))
(“p”。(滚动其他窗口-1))
(“N.”滚动其他窗口)
(“P”。(滚动其他窗口'-))
(“a”。(缓冲区其他窗口0的开头)
(“e”。(缓冲区结束其他窗口0)))

这就是我使用的。我喜欢它,因为您不必指定重复键

(require 'repeat)
(defun make-repeatable-command (cmd)
  "Returns a new command that is a repeatable version of CMD.
The new command is named CMD-repeat.  CMD should be a quoted
command.

This allows you to bind the command to a compound keystroke and
repeat it with just the final key.  For example:

  (global-set-key (kbd \"C-c a\") (make-repeatable-command 'foo))

will create a new command called foo-repeat.  Typing C-c a will
just invoke foo.  Typing C-c a a a will invoke foo three times,
and so on."
  (fset (intern (concat (symbol-name cmd) "-repeat"))
        `(lambda ,(help-function-arglist cmd) ;; arg list
           ,(format "A repeatable version of `%s'." (symbol-name cmd)) ;; doc string
           ,(interactive-form cmd) ;; interactive form
           ;; see also repeat-message-function
           (setq last-repeatable-command ',cmd)
           (repeat nil)))
  (intern (concat (symbol-name cmd) "-repeat")))

除了@juanleon建议的使用
set temporary overlay map
,这里还有一个我经常使用的替代方法。它使用标准库
repeat.el

;; This function builds a repeatable version of its argument COMMAND.
(defun repeat-command (command)
  "Repeat COMMAND."
 (interactive)
 (let ((repeat-previous-repeated-command  command)
       (last-repeatable-command           'repeat))
   (repeat nil)))
使用该选项定义不同的可重复命令。例如:

(defun backward-char-repeat ()
  "Like `backward-char', but repeatable even on a prefix key."
  (interactive)
  (repeat-command 'backward-char))
然后将这样的命令绑定到具有可重复后缀的键,例如,
C-C=
(对于
C-C==


有关更多信息,请参阅。

您熟悉
repeat
命令吗?它绑定到
C-x z
,您可以使用它重复前面的命令。每次你按下
z
@mk1时,它都会重复这个命令。我知道C-x z,我只是想知道我是否可以用这种方式制作我自己的键绑定……无论如何,感谢你的评论
C-x e
,因为执行键盘宏具有所需的行为。如果该绑定的实现在某个地方的elisp中,那么这可能是编写您自己的绑定的一个开始。我非常喜欢这一点,但请注意,必须已经加载CMD(自动加载是不够的),否则arglist和交互式表单查询将失败。(实际上后者会触发自动加载,但前面的arglist会出错)。它似乎没有在任何地方明确说明,但我发现'C-g'退出重复模式。