Elisp:从代码中调用keymap?

时间:2014-07-23 15:07:57

标签: emacs elisp

这是一个让事情顺利进行的最小代码:

(define-prefix-command 'foo)
(define-key foo "a" 'bar)
(define-key foo "b" 'baz)
(global-set-key (kbd "C-M-r") 'foo)

现在我可以"打电话"按 C-M-r 时的foo键映射。 但我想知道如何从代码中做到这一点,例如类似的东西:

(funcall (lambda-from-keymap 'foo))

在此次通话结束后,我预计焦点将集中在迷你缓冲区,期待其中任何一个 要输入 a b C-h 。 这样的事情可能吗?

3 个答案:

答案 0 :(得分:4)

您可以使用read-key-sequencelookup-key来实现此目的:

(defun call-keymap (map &optional prompt)
  "Read a key sequence and call the command it's bound to in MAP."
  ;; Note: MAP must be a symbol so we can trick `describe-bindings' into giving
  ;; us a nice help text.
  (let* ((overriding-local-map `(keymap (,map . ,map)))
         (help-form `(describe-bindings ,(vector map)))
         (key (read-key-sequence prompt))
         (cmd (lookup-key map key t)))
    (if (functionp cmd) (call-interactively cmd)
      (user-error "%s is undefined" key))))

如果你点击 C-h read-key-sequence仍然等着你完成序列。我想你可以模拟Emacs'通过使用read-key循环来表示正常行为,但它更复杂一些。

像这样使用:

(defun bar () (interactive) (message "you called bar"))
(defun baz () (interactive) (message "you called baz"))

(define-prefix-command 'foo)
(define-key foo "a" 'bar)
(define-key foo "b" 'baz)
(global-set-key (kbd "C-M-r") 'foo)

(defun call-foo ()
  (interactive)
  ;; Note: pass the symbol form of the keymap so we can give nice help
  (call-keymap 'foo "enter a foo command: "))

(global-set-key (kbd "C-c f") 'call-foo)

答案 1 :(得分:2)

如果键映射绑定到键序列,则可以通过设置unread-command-events来模拟确切的键序列来调用它:

(setq unread-command-events
      (mapcar (lambda (e) `(t . ,e))
              (listify-key-sequence (kbd "C-M-r"))

答案 2 :(得分:0)

您需要foo互动。我是这样做的:

(global-set-key (kbd "C-M-r") (lambda () (interactive) ( foo)))

这可以解决您的问题。