如何使用带有read-string的minibuffer-exit-hook

时间:2014-01-23 03:58:51

标签: emacs elisp minibuffer

我无法让minibuffer-exit-hookread-string玩得很开心。据我所知,在完成read-string之后我不应再进入迷你缓冲区。但是,条件(minibufferp)表示即使read-string完成,我仍然在迷你缓冲区中。 read-string是用C语言编写的,所以我不能在那里添加钩子(即在read-string函数的尾端)。

文档[minibuffer-exit-hook]:在退出迷你缓冲区后,正常挂钩只运行

[在考虑了一点之后,我很确定这是一个错误 - 所以我提交了一个错误报告:bug#16524。随着我了解更多,我将更新此主题。

(defun test ()
  (interactive)
  (read-string "Prompt: " "testing"))

(add-hook 'minibuffer-exit-hook (lambda ()
  (cond
    ((minibufferp)
      (message "Focus is still in the minibuffer:  %s" (buffer-name)))
    (t (message "Contragulations -- focus is now in: %s." (buffer-name))))))

2 个答案:

答案 0 :(得分:3)

doc字符串不准确;就这样。在迷你缓冲区中输入文本(不再可能)时,将运行挂钩。运行时当前的缓冲区仍然是迷你缓冲区。 (这就是应该的方式,FWIW。)

请注意,Elisp手册略有不同(但同样,不是非常精确):

 This is a normal hook that is run whenever the minibuffer is
 entered.

(“Whenever”,意思是同一时间,不一定是在之后。)

如果您想在代码中每次使用read-string后执行某些操作,请定义执行以下操作的函数:首先(read-string...),然后是您接下来要执行的任何操作。并使用该功能。

如果您还需要影响read-string的其他调用,除了您在代码中编写的调用之外,还建议函数read-string在vanilla代码完成后执行任何操作。

例如:

(defadvice read-string (after fooness activate)
   (message "buffer: %S" (current-buffer)))

[注意:是的,你可以建议原语(用C编写的函数)。你曾经甚至能够建议特殊形式,但他们倒退了这个特征。]

答案 1 :(得分:1)

在你真正退出迷你缓冲区之后运行一个钩子是没有意义的:你可以处于任何类型的缓冲区(因为迷你缓冲区的使用可以从任何地方触发),因此你对当前的上下文知之甚少(除非你使用缓冲区) - 本地退出钩子,我想)。

如果要在所选窗口更改时运行挂钩,那么最佳选择可能是使用post-command-hook将当前所选窗口存储在辅助变量中并使用它与之前选择的窗口进行比较-window。