Emacs 如何将命令绑定到所有键,免除几个键?

eve*_*_jr 5 emacs elisp mode key-bindings

我想制作一个具有其键映射(foo-mode-map)的次要模式(foo-mode),但是当用户按下不在(foo-mode-map)中的任何键时,次要模式应该退出。如何绑定turn-off-foo-mode所有其他键?

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

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

acu*_*ich 4

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

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

为主要模式映射设置默认绑定更容易,我在此处包含此示例,但正如我上面指出的,这种备用键盘映射不适用于次要模式:

(defvar major-baz-mode-map '(keymap (t . major-baz-mode-default-function)))
Run Code Online (Sandbox Code Playgroud)

这在键盘映射格式的文档中进行了讨论,其中写道:

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