【问题标题】:How to write a key bindings in emacs for easy repeat?如何在 emacs 中编写键绑定以便于重复?
【发布时间】:2013-06-16 14:34:32
【问题描述】:

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

(global-set-key (kbd "C-c =") 'function-foo)

现在,我希望键绑定如下:
在我第一次按C-c =后,如果我想重复function-foo,我不需要再次按C-c,而只需重复按=。然后,在我调用 function-foo 足够的时间后,我可以只按= 以外的键(或显式按C-g)退出。

如何做到这一点?

【问题讨论】:

  • 您熟悉repeat 命令吗?它绑定到C-x z,您可以使用它重复上一个命令。每次按 z 时,它都会重复该命令。
  • @mk1 我知道 C-x z,我只是想知道我是否可以制作自己的键绑定,以这种方式工作......无论如何,感谢您的 cmets
  • C-x e 用于执行键盘宏具有所需的行为。如果该绑定的实现在某个地方的 elisp 中,那可能是编写自己的绑定的开始。

标签: emacs elisp


【解决方案1】:

您希望您的function-foo 使用set-temporary-overlay-map

【讨论】:

    【解决方案2】:

    这可能是您正在寻找的东西:

    (defun function-foo ()
      (interactive)
      (do-your-thing)
      (set-temporary-overlay-map
        (let ((map (make-sparse-keymap)))
          (define-key map (kbd "=") 'function-foo)
          map)))
    

    【讨论】:

      【解决方案3】:

      有一个smartrep.el 包可以满足您的需要。文档有点稀缺,但您可以通过查看 github 上的大量 emacs 配置来了解它应该如何使用。例如(取自here):

      (require 'smartrep)
      (smartrep-define-key
          global-map "C-q" '(("n" . (scroll-other-window 1))
                             ("p" . (scroll-other-window -1))
                             ("N" . 'scroll-other-window)
                             ("P" . (scroll-other-window '-))
                             ("a" . (beginning-of-buffer-other-window 0))
                             ("e" . (end-of-buffer-other-window 0))))
      

      【讨论】:

      • 似乎没有明确说明,但我发现`C-g'退出了重复模式。
      【解决方案4】:

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

      (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")))
      

      【讨论】:

      • 我很喜欢这个,但是注意CMD必须已经加载(自动加载是不够的),否则arglist和interactive-form查询会失败。 (实际上后者触发自动加载,但它之前的 arglist 会出错)。
      【解决方案5】:

      除了@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 = = = =...)

      更多信息请参见this SO post

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-05-30
        • 1970-01-01
        • 1970-01-01
        • 2017-09-26
        • 1970-01-01
        • 2013-02-01
        • 2014-11-08
        相关资源
        最近更新 更多