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

Сценарий:

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

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

Это происходит со мной несколько раз в день при использовании emacs, и не только в этом сценарии. Это поведение в высшей степени враждебно для пользователя (см. Джеф Раскин, Джеф Раскин, «Режимы и псевдо-моды»

)

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

Ответы [ 6 ]

7 голосов
/ 01 мая 2009

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

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

5 голосов
/ 01 мая 2009

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

4 голосов
/ 26 октября 2011

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

http://trey -jackson.blogspot.com / 2010/04 / Emacs-зонд-36-прерывань-Минибуфер-when.html

4 голосов
/ 01 мая 2009

Поскольку мой первый ответ напрямую не дает вам то, что вы хотите, я подумал, что нашел бы реальное решение. Вот что у меня есть:

(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. Кроме того, эта версия не поддерживает префиксный аргумент.

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

2 голосов
/ 24 сентября 2016

Вот, пожалуйста:

;; 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)
2 голосов
/ 04 мая 2009

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

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