Emacs模式:“;命令试图在minibuffer中使用minibuffer";

Emacs模式:“;命令试图在minibuffer中使用minibuffer";,emacs,elisp,modal-dialog,Emacs,Elisp,Modal Dialog,情景: 我开始键入M-x以键入命令 我切换到另一个emacs窗口/缓冲区,因为我意识到我在错误的窗口中执行命令 我再次开始键入M-x以在正确的窗口中执行命令 结果:我得到了可怕的“命令试图在minibuffer中使用minibuffer” 在使用emacs时,这种情况每天会发生多次,而不仅仅是在这种情况下。这种行为对用户非常有害(参考Jef Raskin的《人性化界面》中的模式和伪模式) 有没有一种方法可以自定义emacs行为,这样它就不用给出这个错误,而是取消第一个迷你缓冲区并用一个新的替

情景:

  • 我开始键入M-x以键入命令
  • 我切换到另一个emacs窗口/缓冲区,因为我意识到我在错误的窗口中执行命令
  • 我再次开始键入M-x以在正确的窗口中执行命令
结果:我得到了可怕的“命令试图在minibuffer中使用minibuffer”

在使用emacs时,这种情况每天会发生多次,而不仅仅是在这种情况下。这种行为对用户非常有害(参考Jef Raskin的《人性化界面》中的模式和伪模式)


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

我不确定是否有这样的自定义,但是我避免这样做的方法是点击CTRL G来取消我在MiBiffFER中写的命令。

< P>你可以设置变量<代码>允许递归的微布告器< /C> >,这将阻止错误消息的出现。但它只支持对minibuffer的多个调用—它不会将当前minibuffer的命令重定向到新的缓冲区。您可以尝试一下,但我认为它会更加混乱,因为原始操作仍在等待


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

因为我的第一个答案并没有直接给出你想要的,所以我想我会想出一个真正的解决办法。这就是我所拥有的:

(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
  • 从微型缓冲区切换到显示以下内容的窗口:
    C-x o
  • 从显示A的窗口切换到显示B的窗口:
    C-x o
  • 从缓冲区B“重新承载”命令:
    F10
  • 现在回到小缓冲区,完成命令
    ward RET
  • 当我开始键入搜索词时,搜索应用于缓冲区B

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


    希望这就是你想要的。

    有人能改进以下方面吗

    我已经放弃,只想在打开新的迷你缓冲区之前设置\C-w以取消以前的任何迷你缓冲区(如执行\C-g\C-w)

    到目前为止,多亏了特雷,我得到了:

    (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
    
    事实上,这个emacs“特性”是咄咄逼人和令人讨厌的。 我发现这是问题的正确答案。很可能是因为你用鼠标而不是minibuffer命令切换窗口,所以你失去了minibuffer的焦点。因此,每当您使用鼠标失去焦点时,小缓冲区将被清除。查看这篇文章。它对我来说很有效,而且比递归的迷你缓冲区要好得多,这会让人头疼

    给你:

    ;; 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)
    

    另一种看问题的方式是,上面的工作流被破坏了,而不是emacs。在更改缓冲区以设置新区域或其他任何内容之前,G-G退出minibuffer,而不是尝试递归(正如您所做的)嗯,在这种情况下,听起来您比emacs更具用户敌意!由应用程序来适应用户的工作流程,否则为什么要实施撤销?不,这根本不是递归。虽然我很欣赏现代设计实践避免了模态,但emacs是在遥远的过去设计的,具有丰富的模态。如果emacs的模式有问题,我坦率地建议不要使用它。Emacs对用户怀有敌意。就我个人而言,我克服了它,学会了使用它,并发现了很多可用的功能,但那是在emacs当之无愧的时候。这些天我很少接触它。如果什么东西坏了,那是工具,而不是用户(作为第一近似值)。EoghanM感到困惑是有原因的。在这种情况下,因为minibuffer总是可见的,所以它与缓冲区没有特别的关系,那么为什么M-x命令应该保留在它启动的缓冲区上呢?Emacs甚至没有指明该命令将应用于哪个缓冲区。谢谢伙计们-Godeke,你能在回答中推荐一个更好的编辑器吗?显然VI也是高度模态的。几年前我确实尝试过Archy,但我认为它已经死了。谢谢,我知道ctrl-g并经常使用它,但在这种情况下,我似乎无法将其纳入我的工作流中-我认为原因是我不想取消该命令,只需将其重定向到另一个窗口。谢谢Trey,我会将其绑定到m-x,然后看看我如何继续。我看到了一个直接的问题,即在第5步执行命令后,缓冲区A被缓冲区B替换(因此现在我在两个窗口中都有两个B缓冲区)。也许这是我的设置有点奇怪-你给了我足够的时间来继续开发适合我的答案。缓冲区的变化也发生在我身上,我不知道如何解决这个问题。我认为
    interactive
    的处理强制命令从您启动的窗口开始。但这只是猜测。我无法用
    的save-window-shiftion
    解决这个问题(这是我想到的第一件事)。这对我来说很有效