设想:

  • 我开始输入 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):

  1. 从显示缓冲区 A 的窗口: F10 isearch-for
  2. 从迷你缓冲区切换到显示 A 的窗口: C-x o
  3. 从显示 A 的窗口切换到显示 B 的窗口: C-x o
  4. “重新托管”缓冲区 B 中的命令: F10
  5. 现在回到迷你缓冲区,完成命令 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)
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top