14

设想:

  • 我开始输入 Mx 来输入命令
  • 我切换到另一个 emacs 窗口/缓冲区,因为我意识到我在错误的窗口中执行命令
  • 我开始再次输入 Mx 以在正确的窗口中执行命令

结果:我得到可怕的“命令试图在 minibuffer 中使用 minibuffer”

这在我使用 emacs 时每天会发生多次,而不仅仅是在这种情况下。这种行为是高度用户敌对的(参考The Humane InterfaceJef Raskin 的 Modes and Pseudo-modes)

有没有办法自定义 emacs 行为,而不是给出这个错误,它只是取消第一个 minibuffer 并用新的 minibuffer 替换它?

4

6 回答 6

8

您可以设置变量enable-recursive-minibuffers,这将防止出现该错误消息。但它只是启用对 minibuffer 的多次调用 - 它不会将当前 minibuffer 的命令重定向到新缓冲区。您可以尝试一下,但我认为它会更加混乱,因为原始操作仍在等待中......

M-x绑定到'execute-extended-command,并且为该命令重新托管(更改原始缓冲区)有点像继续编程。即,您从位置 X 调用子例程,但完成后不是返回 X,而是返回 Y。我个人认为这会带来更多的混乱,而不是解决问题。但我理解这种挫败感(并且知道其他人也有同样的挫败感)。

于 2009-05-01T17:50:41.287 回答
6

确实,这个 emacs “功能”具有侵略性且令人讨厌。我发现这是问题的正确答案。很可能您失去了对 minibuffer 的关注,因为您使用鼠标而不是 minibuffer 命令切换窗口。因此,每当您使用鼠标失去焦点时,都会清除迷你缓冲区。检查这篇文章。它对我有用,而且比递归的 minibuffers 好得多,这会导致头痛

http://trey-jackson.blogspot.com/2010/04/emacs-tip-36-abort-minibuffer-when.html

于 2011-10-25T21:28:44.150 回答
5

我不确定是否有这样的自定义,但我避免这种情况的方法是取消我正在编写的迷你缓冲区中的命令ctrlg

于 2009-05-01T16:41:18.037 回答
4

由于我的第一个答案并没有直接给你你想要的,我想我会想出一个真正的解决方案。这就是我所拥有的:

(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):

  1. 从显示缓冲区 A 的窗口:F10 isearch-for
  2. 从 minibuffer 切换到显示 A 的窗口:C-x o
  3. 从显示 A 的窗口切换到显示 B 的窗口:C-x o
  4. “重新托管”来自缓冲区 B 的命令:F10
  5. 现在回到迷你缓冲区,完成命令ward RET

当我开始输入搜索词时,搜索应用到缓冲区 B。

这只会替换M-x功能,而不是从 调用的命令M-x。此外,此版本不支持前缀参数。

希望这是你想要的。

于 2009-05-01T18:39:05.163 回答
2

任何人都可以改进以下内容吗?

我已经放弃了,只想设置 \Cw 在打开一个新的之前取消任何以前的 minibuffer(比如做 \Cg\Cw)

到目前为止,感谢 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
于 2009-05-04T13:30:57.143 回答
2

干得好:

;; 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)
于 2016-09-24T03:36:30.763 回答