Emacs 模式:“命令尝试在迷你缓冲区中使用迷你缓冲区”
-
03-07-2019 - |
题
设想:
- 我开始输入 M-x 来输入命令
- 我切换到另一个 emacs 窗口/缓冲区,因为我意识到我在错误的窗口中执行命令
- 我开始再次输入 M-x 以在正确的窗口中执行命令
结果:我收到可怕的“命令试图在迷你缓冲区中使用迷你缓冲区”
在我使用 emacs 时,这种情况每天都会发生多次,而且不仅仅是在这种情况下。这种行为是高度用户敌意的(参考。中的模式和伪模式 The Humane Interface
作者:杰夫·拉斯金)
有没有一种方法可以自定义 emacs 行为,这样它就不会给出此错误,而是取消第一个迷你缓冲区并用新的迷你缓冲区替换它?
解决方案
事实上,这个 emacs“功能”是咄咄逼人且令人讨厌的。我发现这是问题的正确答案。很可能您失去了迷你缓冲区的焦点,因为您使用鼠标而不是迷你缓冲区命令切换了窗口。因此,每当您使用鼠标失去焦点时,迷你缓冲区就会被清除。检查这个帖子。它对我有用,而且比递归迷你缓冲区要好得多,后者会引起头痛
http://trey-jackson.blogspot.com/2010/04/emacs-tip-36-abort-minibuffer-when.html
其他提示
您可以设置变量 enable-recursive-minibuffers
, ,这将防止出现该错误消息。但它只是启用对迷你缓冲区的多次调用 - 它不会将当前迷你缓冲区的命令重定向到新缓冲区。你可以尝试一下,但我认为这会更令人困惑,因为最初的行动仍然悬而未决......
M-x
一定会 'execute-extended-command
, ,并重新托管(更改原始缓冲区)该命令有点像连续编程。IE。您从位置 X 调用子例程,但完成后不是返回到 X,而是返回到 Y。我个人认为这会带来更多的混乱,而不是解决更多的混乱。但我理解这种挫败感(并且知道其他人也有同样的挫败感)。
我不确定是否有这样的定制,但我避免这种情况的方法是击中 控制键-G 要取消命令,我正在写入迷你缓冲区。
由于我的第一个答案并没有直接给你你想要的东西,我想我会想出一个真正的解决方案。这就是我所拥有的:
(defvar my-execute-extended-command-source-buffer nil
"var holding the buffer to which the extended-execute-command should apply")
(defvar in-my-execute-extended-command nil
"internal use - indicates whether we're in a 'recursive edit' of sorts")
(defun my-execute-extended-command (command)
"home-grown version of execute-extended-command that supports re-hosting the buffer"
(interactive (list (if in-my-execute-extended-command
nil
(let ((in-my-execute-extended-command t))
(setq my-execute-extended-command-source-buffer (current-buffer))
(completing-read "My-x " obarray 'commandp t nil 'extended-command-history nil nil)))))
(if in-my-execute-extended-command
(progn (setq my-execute-extended-command-source-buffer (current-buffer))
(select-window (minibuffer-window)))
(switch-to-buffer my-execute-extended-command-source-buffer)
(call-interactively (symbol-function (intern command)))))
我已经这样测试过。我将它绑定到一把钥匙(F10
就我而言 b/c 我不想输 M-x
)。然后,打开两个窗口,每个窗口显示不同的缓冲区(例如 A 和 B):
- 从显示缓冲区 A 的窗口:
F10 isearch-for
- 从迷你缓冲区切换到显示 A 的窗口:
C-x o
- 从显示 A 的窗口切换到显示 B 的窗口:
C-x o
- “重新托管”缓冲区 B 中的命令:
F10
- 现在回到迷你缓冲区,完成命令
ward RET
当我开始输入搜索词时,搜索将应用于缓冲区 B。
这仅取代 M-x
功能,而不是调用的命令 M-x
. 。此外,该版本不支持前缀参数。
希望这就是您想要的。
有人可以改进以下方面吗?
我已经放弃了,只想设置 \C-w 来取消任何以前的迷你缓冲区,然后再打开一个新的迷你缓冲区(就像做 \C-g\C-w 一样)
到目前为止,感谢 Trey,我已经得到了:
(defun cancel-completing-read ()
(if (> (minibuffer-depth) 0) (exit-minibuffer))
(completing-read "My-x " obarray 'commandp t nil 'extended-command-history nil nil))
(defun cancel-and-execute-command (command)
(interactive (list (cancel-completing-read)))
(call-interactively (symbol-function (intern command))))
(global-set-key "\M-x" 'cancel-and-execute-command)
我应该使用什么命令来代替 exit-minibuffer
多于?
我试过了
keyboard-escape-quit
exit-minibuffer
keyboard-quit
干得好:
;; automatically cancel the minibuffer when you switch to it, to avoid
;; "attempted to use minibuffer" error.
;; cy was here
(provide 'cancel-minibuffer)
(defun cancel-minibuffer-first (sub-read &rest args)
(let ((active (active-minibuffer-window)))
(if active
(progn
;; we have to trampoline, since we're IN the minibuffer right now.
(apply 'run-at-time 0 nil sub-read args)
(abort-recursive-edit))
(apply sub-read args))))
(advice-add 'read-from-minibuffer :around #'cancel-minibuffer-first)