Emacs模式:“命令试图在迷你缓冲区中使用迷你缓冲区”

时间:2009-05-01 16:37:00

标签: emacs elisp modal-dialog

情景:

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

结果:我得到了可怕的“命令试图在迷你缓冲区中使用迷你缓冲区”

在使用emacs时,每天都会发生这种情况,而不仅仅是在这种情况下。此行为是高度用户敌意的(参考模式和杰夫拉斯金The Humane Interface中的伪模式)

有没有办法自定义emacs行为,这样它就会取消第一个迷你缓冲区并用新的迷你缓冲区替换它而不是给出这个错误?

6 个答案:

答案 0 :(得分:7)

您可以设置变量enable-recursive-minibuffers,这将阻止该错误消息出现。但它只允许多次调用迷你缓冲区 - 它不会将当前的迷你缓冲区命令重定向到新缓冲区。你可以尝试一下,但我认为它会更加混乱,因为原来的行动还在等待......

M-x绑定到'execute-extended-command,并且为该命令重新托管(更改原始缓冲区)就像使用continuation编程一样。即你从位置X调用一个子程序,但是在完成后不再返回X,而是返回Y.我个人认为它会比它解决更多的混乱。但我理解挫折感(并且知道其他人也有同样的挫折感)。

答案 1 :(得分:5)

我不确定是否有这样的自定义,但是我避免这种情况的方法是按 ctrl - g 来取消我在中间的命令写在迷你缓冲区。

答案 2 :(得分: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. 从迷你缓冲区切换到显示A:C-x o
  3. 的窗口
  4. 从显示A的窗口切换到显示B的窗口:C-x o
  5. 从缓冲区B“重新托管”命令:F10
  6. 现在回到迷你缓冲区,完成命令ward RET
  7. 当我开始输入搜索词时,搜索应用于缓冲区B.

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

    希望这就是你想要的。

答案 3 :(得分:4)

事实上,这个emacs“功能”是积极和恼人的。 我发现这是问题的正确答案。很可能你失去了迷你缓冲区的焦点,因为你用鼠标切换窗口而不是迷你缓冲区命令。因此,每当您使用鼠标失去焦点时,迷你缓冲区将被清除。查看这篇文章。它适用于我,它比递归迷你服务器更好,这将导致头痛

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

答案 4 :(得分:2)

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

我已经放弃了,只想设置\ 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

答案 5 :(得分: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)