首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Emacs如何将命令绑定到所有密钥,用少数几个密钥免责?

Emacs如何将命令绑定到所有密钥,用少数几个密钥免责?
EN

Stack Overflow用户
提问于 2011-12-19 01:32:43
回答 4查看 442关注 0票数 5

我想创建一个有其键映射(foo-mode-map)的次模式(foo-mode),但是当用户按下(foo-mode-map)之外的任何键时,次模式应该退出。如何绑定所有其他密钥的turn-off-foo-mode

编辑:这是我根据选择的答案提出的解决方案。它也接受数字输入。

代码语言:javascript
复制
(defalias 'foo-electric-delete 'backward-kill-word)

(defun foo-mode-quit (&optional arg)
  (interactive)
  (let ((global-binding (lookup-key (current-global-map)
                                    (single-key-description last-input-event))))
    (unless (eq last-input-event ?\C-g)
      (push last-input-event unread-command-events))
    (unless (memq global-binding
                  '(negative-argument digit-argument))
      (foo-mode -1))))

(defvar foo-mode-map
  (let ((map (make-keymap)))
    (set-char-table-range (nth 1 map) t 'foo-mode-quit)
    (define-key map "-" 'negative-argument)
    (dolist (k (number-sequence ?0 ?9))
      (define-key map (char-to-string k) 'digit-argument))
    (define-key map [backspace] 'foo-electric-delete)
    map))

(define-minor-mode foo-mode
  "Toggle Foo mode.
     With no argument, this command toggles the mode.
     Non-null prefix argument turns on the mode.
     Null prefix argument turns off the mode.

     When Foo mode is enabled, the control delete key
     gobbles all preceding whitespace except the last.
     See the command \\[foo-electric-delete]."
  ;; The initial value.
  :init-value nil
  ;; The indicator for the mode line.
  :lighter " Foo"
  ;; The minor mode bindings.
  :keymap foo-mode-map
  :group 'foo)
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2011-12-19 06:01:48

我已经包含了一个完整的工作示例,用于创建具有您想要的行为的次要模式;关键是在由make-keymap创建的键映射上使用set-char-table-range,这将创建一个具有完整char-table的密集键映射;在使用make-sparse-keymap创建的稀疏键映射上使用它将不起作用。

代码语言:javascript
复制
(defalias 'foo-electric-delete 'backward-kill-word)

(defun foo-mode-quit (&optional arg)
  (interactive)
  (foo-mode -1))

(defvar foo-mode-map
  (let (map (make-keymap))
    (set-char-table-range (nth 1 map) t 'foo-mode-quit)
    (define-key map [backspace] 'foo-electric-delete)
    map))

(define-minor-mode foo-mode
  "Toggle Foo mode.
     With no argument, this command toggles the mode.
     Non-null prefix argument turns on the mode.
     Null prefix argument turns off the mode.

     When Foo mode is enabled, the control delete key
     gobbles all preceding whitespace except the last.
     See the command \\[foo-electric-delete]."
  ;; The initial value.
  :init-value nil
  ;; The indicator for the mode line.
  :lighter " Foo"
  ;; The minor mode bindings.
  :keymap foo-mode-map
  :group 'foo)

(defvar major-baz-mode-map '(keymap (t . major-baz-mode-default-function)))

为主模式映射设置默认绑定更容易,我在这里包含了这个示例,但正如我在上面提到的,这种备用键映射不适用于次模式:

代码语言:javascript
复制
(defvar major-baz-mode-map '(keymap (t . major-baz-mode-default-function)))

Format of Keymaps的文档中讨论了这一点,文档中写道:

代码语言:javascript
复制
(t . binding)

This specifies a default key binding; any event not bound by other
elements of the keymap is given binding as its binding. Default
bindings allow a keymap to bind all possible event types without
having to enumerate all of them. A keymap that has a default binding
completely masks any lower-precedence keymap, except for events
explicitly bound to nil (see below).
票数 4
EN

Stack Overflow用户

发布于 2011-12-19 02:18:36

你必须决定的一件事是,当用户按下另一个键时,你是否应该简单地退出你的模式,或者你是否应该运行绑定到相关键的命令(就像在incremental-search中一样)。

一种方法是使用pre-command-hook检查this-command是否为您的命令之一,如果不是,则关闭您的模式。

票数 4
EN

Stack Overflow用户

发布于 2011-12-19 03:44:15

解决方案2:您可以使用set-char-table-range来设置地图中的所有字符。例如:

代码语言:javascript
复制
(defvar foo-mode-map
  (let ((map (make-keymap)))
    (set-char-table-range (nth 1 map) t 'foo-turn-off-foo-mode)
    ...
    map))
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8553432

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档