Режимы Emacs: "Команда попыталась использовать минибуфер в минибуфере"

Сценарий:

  • Я начинаю вводить M-x для ввода команды
  • Я переключаюсь на другое окно/буфер emacs, потому что понимаю, что я выполняю команду в неправильном окне
  • Я снова начинаю вводить M-x для выполнения команды в правильном окне

Результат: я получаю страшную команду "Команда пыталась использовать минибуфер в минибуфере"

Это происходит со мной несколько раз в день при использовании emacs, а не только в этом сценарии. Это поведение очень враждебно-враждебно (Режимы и псевдорежимы в The Humane Interface от Jef Raskin)

Есть ли способ настроить поведение emacs, чтобы вместо того, чтобы давать эту ошибку, он просто отменяет первый минибуфер и заменяет его новым?

Ответ 1

Действительно, эта особенность emacs является агрессивной и раздражающей. Я нашел, что это правильный ответ на проблему. Вероятно, вы потеряли фокус минибуфера, потому что вы переключили окна с помощью мыши и НЕ команду минибуфера. Поэтому, когда вы теряете фокус с помощью мыши, минибуфер будет очищен. Проверьте этот пост. Это работает для меня, и это лучше, чем рекурсивные минибуферы, которые вызывают головную боль.

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

Ответ 2

Вы можете установить переменную enable-recursive-minibuffers, которая предотвратит появление этого сообщения об ошибке. Но он просто включает несколько вызовов минибуфера - он не перенаправляет текущую команду минибуфера в новый буфер. Вы можете попробовать, но я думаю, что это будет более запутанным, потому что исходное действие все еще ожидается...

M-x привязан к 'execute-extended-command, а повторный хостинг (изменение исходного буфера) для этой команды похож на программирование с продолжением. т.е. вы вызываете подпрограмму из местоположения X, но вместо того, чтобы вернуться к X, когда вы закончите, вы вернетесь к Y. Я лично считаю, что это откроет больше путаницы, чем это решит. Но я понимаю разочарование (и знаю других, у кого такое же расстройство).

Ответ 3

Я не уверен, есть ли такая настройка, но способ избежать этого - нажать ctrl - g, чтобы отменить команду, которую я был в середине записи в минибуфере.

Ответ 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):

  • Из окна, показывающего буфер A: F10 isearch-for
  • Переключение с минибуфера на окно с изображением A: C-x o
  • Переключиться из окна, показывающего A, с изображением B: C-x o
  • "повторить" команду из буфера B: F10
  • Теперь вернитесь в минибуфер, завершите команду ward RET

Когда я начал вводить поисковый запрос, поиск применялся к буферам B.

Это заменяет функциональность M-x, а не команды, вызываемые из M-x. Кроме того, эта версия не поддерживает аргумент префикса.

Надеюсь, это то, что вы хотите.

Ответ 5

Может ли кто-нибудь улучшить следующее:

Я отказался и просто хочу установить \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

Ответ 6

Здесь вы идете:

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