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

StackOverflow https://stackoverflow.com/questions/812135

  •  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):

  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)

На данный момент благодаря Трею у меня есть:

(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