2009-05-01 12 views
10

Escenario:Emacs Modos: "Comando intentado utilizar minibuffer mientras que en minibuffer"

  • comienzo a escribir Mx para escribir un comando
  • me cambio a otra ventana emacs/tampón porque se dan cuenta de que soy ejecutar el comando en la ventana equivocada
  • comienzo a escribir Mx nuevo para ejecutar el comando en la ventana correcta

Resultado: llego el temido "comando intentó utilizar minibuffer mientras que en minibuffer"

Esto me sucede varias veces al día durante el uso de emacs, y no solo en este escenario. Este comportamiento es altamente hostil al usuario (ref. Modos y modos de pseudo en The Humane Interface por Jef Raskin)

¿Hay alguna manera de personalizar el comportamiento de emacs para que en lugar de dar este error, simplemente cancele el primer minibúfer y lo reemplace? con uno nuevo?

+2

Otra forma de verlo es que es el flujo de trabajo anterior que está roto, no emacs. G-g fuera del minibúfer antes de cambiar los buffers para establecer una nueva región o lo que sea, en lugar de tratar de recurrir (como lo hace) – simon

+3

¡Hmm, parece que es más hostil con el usuario que emacs en este caso! Depende de la aplicación acomodar el flujo de trabajo de los usuarios, de lo contrario, ¿por qué implementar deshacer? Y no, esto no es recursividad en absoluto. – EoghanM

+0

Aunque aprecio que las prácticas de diseño modernas eviten la modalidad, emacs fue diseñado en un pasado lejano y tiene modos en abundancia. Si la modalidad de emacs es problemática, francamente recomendaría no usarla. Emacs * es * usuario hostil. Personalmente, lo superé y aprendí a usarlo y encontré mucha potencia disponible, pero eso fue cuando emacs fue el rey de la percha. Estos días rara vez me sumerjo en él. – Godeke

Respuesta

3

De hecho, este emacs "característica" es agresivo y molesto. He encontrado que esta es la respuesta correcta al problema. Lo más probable es que haya perdido el foco del minibúfer porque cambió las ventanas con el mouse y NO un comando de minibúfer. Por lo tanto, cada vez que pierdes el enfoque con el mouse, el minibúfer se borrará. Revisa esta publicación Funciona para mí y es mucho mejor que minibúferes recursivas que causarán un dolor de cabeza

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

+0

¡Gran solución! – EoghanM

4

no estoy seguro de si hay una personalización de este tipo, pero la forma evito esto está golpeando ctrl - g para cancelar el comando que estaba en el medio de la escritura en el minibúfer.

+1

Gracias, conozco ctrl-g y lo uso mucho, pero parece que no puedo incorporarlo a mi flujo de trabajo en este escenario. Creo que la razón es que no quiero cancelar el comando, solo redirigirlo a otra ventana. – EoghanM

6

Puede establecer la variable enable-recursive-minibuffers, lo que evitará que aparezca ese mensaje de error. Pero solo habilita múltiples llamadas al minibúfer: no redirige el comando del minibúfer actual al nuevo búfer. Puede probar esto, pero creo que va a ser más confuso porque la acción original todavía está pendiente ...

M-x está obligado a 'execute-extended-command y re-hosting (cambiando el búfer original) para ese comando es tipo de programación con continuación. es decir, usted llama a una subrutina desde la ubicación X, pero en lugar de volver a X cuando termina, regresa a Y. Personalmente creo que abriría más confusión de la que resolvería. Pero entiendo la frustración (y conozco a otros que tienen la misma frustración).

4

Como mi primera respuesta no le da directamente lo que desea, pensé que encontraría una solución real. Esto es lo que tengo:

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

Lo he probado de esta manera. Lo até a una llave (F10 en mi caso b/c No quería perder M-x). Luego, con dos ventanas abiertas, cada una mostrando un buffer diferente (por ejemplo A y B):

  1. Desde la ventana que muestra el tampón A: F10 isearch-for
  2. Cambiar de minibuffer a la ventana que muestra A: C-x o
  3. interruptor de la ventana Una muestra de que la muestra B: C-x o
  4. "re-host" el comando de tampón B: F10
  5. Ahora, de vuelta en el minibúfer, terminar el comando ward RET

Cuando comencé a escribir un término de búsqueda, la búsqueda se aplicaba al buffer B.

Esto solo reemplaza la funcionalidad M-x, no los comandos invocados desde M-x. Además, esta versión no admite el argumento de prefijo.

Espero que esto es lo que desea.

+0

Gracias Trey, ataré esto a M-x y veré cómo me llevo. Veo un problema inmediato que después de la ejecución del comando en el paso 5, el buffer A es reemplazado por el buffer B (así que ahora tengo dos B buffers en ambas ventanas). Tal vez eso es algo peculiar con mi configuración: me has dado lo suficiente como para seguir desarrollando una respuesta que me conviene. – EoghanM

+0

El cambio de buffer ocurre conmigo también, no sé de una manera de arreglar eso. Creo que el manejo de 'interactive' obliga al comando a originarse desde la ventana desde la cual se inicia. Pero eso es una suposición. No pude resolver ese problema con '' save-window-excursion' (que fue lo primero que se me ocurrió). –

2

¿Alguien puede mejorar lo siguiente?

que he dado y sólo quiero establecer \ Cw de cancelar cualquier minibuffer anterior antes de abrir una nueva (como hacer \ CG \ CW)

Hasta ahora, gracias a Trey Tengo:

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

¿Qué comando debo usar en lugar de exit-minibuffer arriba?

He intentado

keyboard-escape-quit 
exit-minibuffer 
keyboard-quit 
0

Aquí van:

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