emacs - 手动退出临时覆盖图

标签 emacs closures elisp key-bindings

在 emacs 24 中,set-temporary-overlay-map激活一个键映射,一旦用户按下该键映射中未定义的键,该键映射就会变为非激活状态。

我需要手动停用覆盖键映射,但没有提供特别执行此操作的功能。我已经查看了源代码:

(defun set-temporary-overlay-map (map &optional keep-pred)
  "Set MAP as a temporary keymap taking precedence over most other keymaps.
Note that this does NOT take precedence over the \"overriding\" maps
`overriding-terminal-local-map' and `overriding-local-map' (or the
`keymap' text property).  Unlike those maps, if no match for a key is
found in MAP, the normal key lookup sequence then continues.

Normally, MAP is used only once.  If the optional argument
KEEP-PRED is t, MAP stays active if a key from MAP is used.
KEEP-PRED can also be a function of no arguments: if it returns
non-nil then MAP stays active."
  (let* ((clearfunsym (make-symbol "clear-temporary-overlay-map"))
         (overlaysym (make-symbol "t"))
         (alist (list (cons overlaysym map)))
         (clearfun
          ;; FIXME: Use lexical-binding.
          `(lambda ()
             (unless ,(cond ((null keep-pred) nil)
                            ((eq t keep-pred)
                             `(eq this-command
                                  (lookup-key ',map
                                              (this-command-keys-vector))))
                            (t `(funcall ',keep-pred)))
               (set ',overlaysym nil)   ;Just in case.
               (remove-hook 'pre-command-hook ',clearfunsym)
               (setq emulation-mode-map-alists
                     (delq ',alist emulation-mode-map-alists))))))
    (set overlaysym overlaysym)
    (fset clearfunsym clearfun)
    (add-hook 'pre-command-hook clearfunsym)
    ;; FIXME: That's the keymaps with highest precedence, except for
    ;; the `keymap' text-property ;-(
    (push alist emulation-mode-map-alists)))

我收集到停用当前覆盖键映射的机制如下:
  • 一个函数clearfun定义为在每个命令之前运行,检查调用的上一个命令是否在映射中。
  • 如果它不在 map 中,则执行以下代码:

  • (为什么这种格式不正确?好的,现在可以了)
    (set ',overlaysym nil)   ;Just in case.
                   (remove-hook 'pre-command-hook ',clearfunsym)
                   (setq emulation-mode-map-alists
                         (delq ',alist emulation-mode-map-alists))
    

    因此,我真正想要的是使用适当的变量执行上面的代码。但是这段代码是闭包的一部分,我无法确定像 overlaysym 这样的值, clearfunsym , alist封闭内。我试着寻找 clearfunsym通过 eval -ing pre-command-hook ,但奇怪的是什么都没有(除了另一个不相关的钩子(Hook))。

    我尝试重新评估函数定义并对其进行调试,但在 (add-hook 'pre-command-hook clearfunsym) 之后我注意到了, pre-command-hook仍然是 nil ,这让我很困惑。我将继续深入研究源代码,也许我会重写我自己的这个函数版本来额外生成一个 force-clear我可以稍后调用的函数,但也许有人可以看到更清洁的解决方案。

    最佳答案

    您写道:“我无法确定像 overlaysym 这样的值”
    但是,overlaysym 被评估。它具有值(生成符号“t”)。
    它是一个名为 t 的符号。这使得访问它变得困难,但并非不可能。
    对以下行的评估给出了注释掉的结果:

    (setq mysym (make-symbol "t"))
    ;; t
    (set mysym 'test)
    ;; test
    (symbol-value mysym)
    ;; test
    

    这同样适用于计算为 clear-temporary-overlay-map 的 clearfunsym。

    还有一条评论:当您调试 set-temporary-overlay-map 时,您正在按下键。可能是这些击键调用 clear-temporary-overlay-map 和 clear pre-command-hook 吗?

    试试看:
    (defadvice set-temporary-overlay-map (after test activate)
      (setq test-pre-command-hook pre-command-hook))
    

    然后输入 text-scale-mode (C-+) 并查看 test-pre-command-hook。例如评估 test-pre-command-hook在我的电脑上给了我以下列表:

    ( clear-temporary-overlay-map tooltip-hide)。

    让我们对 emulation-mode-map-alists 做同样的事情.然后我们得到:
    (((t keymap (67108912 . #[0 "\301\302\300!!\207" [1 text-scale-adjust abs] 3 "
    ...
    
    (fn)" nil]) (45 . #[0 "\301\302\300!!\207" [1 text-scale-adjust abs] 3 "
    (fn)" nil]))))
    

    特别要注意 t 一开始。这意味着您可以通过搜索带有符号 t 的列表来找到覆盖图。一开始。

    类似以下代码片段的内容应该足以删除覆盖图:
    (when (assoc-string "t" (car emulation-mode-map-alists))
      (setq emulation-mode-map-alists (cdr emulation-mode-map-alists)))
    
    when只是一种保护。 (也许,以前有其他东西杀死了 map ?)临时 map 应该总是在前面(因为 push 中的 set-temporary-overlay-map )。有什么机会在它前面放另一个键盘映射吗?也许,时间控制的东西?然后你需要搜索 emulation-mode-map-alists对于带有 (make-symbol "t") 的 alist键盘映射。

    关于emacs - 手动退出临时覆盖图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19309750/

    相关文章:

    emacs - 评估名称存储在字符串中的变量

    emacs - 使 emacs 下一个缓冲区跳过 *Messages* 缓冲区

    emacs - 在 emacs 主要模式下正确突出显示

    html - 在 emacs HTML 模式下禁用自动回车

    emacs - 如何找到/设置暂存缓冲区位置?

    javascript - Javascript 中闭包的替代语法 : possible drawbacks?

    Javascript/Node : Passed in object seems to overwrite "self" - closure issue?

    emacs - 以编程方式从 elisp 函数发送电子邮件

    emacs - 从 emacs 回答/询问 SO 问题。?

    closures - 为什么嵌套迭代器闭包不会从外部范围复制值