Режимы Emacs:«Команда попыталась использовать минибуфер, находясь в минибуфере»
-
03-07-2019 - |
Вопрос
Сценарий:
- Я начинаю печатать 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
, и повторное размещение (изменение исходного буфера) для этой команды похоже на программирование с продолжением.то естьвы вызываете подпрограмму из местоположения X, но вместо того, чтобы вернуться в X после завершения, вы возвращаетесь в Y.Лично я думаю, что это создаст больше путаницы, чем решит.Но я понимаю разочарование (и знаю других, которые испытывают такое же разочарование).
Я не уверен, существует ли такая настройка, но я избегаю этого, нажимая Ctrl-г чтобы отменить команду, которую я писал в минибуфер.
Поскольку мой первый ответ не дает вам напрямую того, что вы хотите, я подумал, что найду реальное решение.Вот что у меня есть:
(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
в моем случае, потому что я не хотел проигрывать 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
.Кроме того, эта версия не поддерживает аргумент префикса.
Надеюсь, это то, чего вы хотите.
Может ли кто-нибудь улучшить следующее?
Я сдался и просто хочу установить \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
Ну вот:
;; 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)