Intercambie el comportamiento predeterminado del comando con el comportamiento Cu

7

Muchos comandos de Emacs alteran su comportamiento cuando se los llama con uno o más C-uprefijos. En algunos casos, el comportamiento predeterminado de un comando es menos útil para mí que el comportamiento que obtengo al prefijarlo C-u. Al mismo tiempo, no quiero deshacerme del comportamiento predeterminado por completo.

Para dar un ejemplo concreto, el quit-windowcomando (ligado a qen help-mode) se cierra la ventana y entierra el buffer está representada en ella por defecto actual. Cuando se llama con C-uél, mata el búfer en su lugar. Me gustaría que el comando elimine el búfer de forma predeterminada y lo entierre cuando se lo llame con un C-uprefijo.

P: ¿Cómo puedo decirle a Emacs que haga que un comando se comporte como si fuera invocado con un C-u prefijo por defecto mientras mueve el comportamiento predeterminado al C-u prefijo ?

Sé que podría abordar esto redefiniendo el comando original o envolviéndolo en un comando personalizado que pasa los argumentos de prefijo de acuerdo con mis preferencias. Pero prefiero hacer algo como esto:

(swap-args 'quit-window)
itsjeyd
fuente

Respuestas:

4

Algo como esto:

(defun swap-args (fun)
  (if (not (equal (interactive-form fun)
                  '(interactive "P")))
      (error "Unexpected")
    (advice-add
     fun
     :around
     (lambda (x &rest args)
       "Swap the meaning the universal prefix argument"
       (if (called-interactively-p 'any)
           (apply x (cons (not (car args)) (cdr args)))
         (apply x args))))))

Obviamente, solo funciona para (interactive "P"). Para otros tipos interactive, puede no tener sentido negar el primer argumento.

abo-abo
fuente
1
Podría ser un poco más simple de usar en :filter-argslugar de :around, creo.
npostavs
Gracias, swap-argsfunciona porque hace que el C-ucomportamiento sea el predeterminado al aplicarlo a un comando. Sin embargo, cuando llamo al comando con C-u, no obtengo el comportamiento original. Tal vez called-interactively-pes la culpa? Entiendo que con un argumento de 'any, esta función solo regresará nilsi el comando que contiene se llama desde Lisp, por lo que al invocar el comando recomendado a través de un enlace de teclas, no se puede alcanzar la rama else.
itsjeyd
'anyestaba bien, lo usé en funcalllugar de applypor error.
abo-abo
2
También debe agregar algo a la cadena de documentación, de lo contrario, esto puede ser confuso.
Gilles 'SO- deja de ser malvado'
1
De manera molesta, algunas funciones (p. Ej. org-insert-subheading) Verifican literalmente el argumento universal en bruto (aparentemente (4)) en lugar de una verificación de coerción de verdad.
olejorgenb
1

Otro método basado en el hecho de que una interactive-formpropiedad en el plist de la función anula la forma especificada en el código: ( ref )

(put 'org-insert-subheading
     'interactive-form
     '(interactive (progn (if current-prefix-arg
                              '(nil)
                            '((4))))))

Utilizando (interactive-form 'function)para obtener la especificación actual, también es posible manejar especificaciones más complejas.

Creo que la mejor solución (si es posible) es envolver la función con (let ((prefix-arg (not current-prefix-arg)))pesar

olejorgenb
fuente
0

No es tan fácil como el pensamiento. Sin embargo, como es trivial tener el comando intercambiado:

(defun my-quit-window-args-swapped (&optional bury window)
"Adapted docstring blah, blah "
  (interactive "P")
  (quit-restore-window window (if bury 'bury 'kill)))
Andreas Röhler
fuente
Gracias, pero como mencioné en mi pregunta, estoy buscando una solución genérica que pueda aplicar a diferentes comandos, no un contenedor específico para el quit-windowcomando.
itsjeyd
@itsjeyd No hay restricción finita WRT para el resultado y el empleo de un argumento. No se trata de "(swap-args ..." sino del uso y significado de args, que finalmente es gratis.
Andreas Röhler
1
Debería haber elegido mis palabras con más cuidado. No quise sugerir que su solución no se pueda adaptar para funcionar con otros comandos. Es una solución perfectamente buena para intercambiar valores predeterminados y C-ucomportamiento, ¡y estoy seguro de que otras personas que se encuentren con tu publicación recibirán ayuda! Personalmente, no lo voy a usar porque tengo varios comandos cuyo comportamiento quiero cambiar, y me gustaría evitar tener que definir varios contenedores.
itsjeyd
@itsjeyd AFAIU lo único que se define aquí es la forma en que el cuerpo recibe Cu. No hay un estándar en qué punto del cuerpo se usa el argumento, también hay muchas formas de usarlo, en un sentido booleano aquí. Claro, podrías emplear algún tipo de IA para cubrir y lidiar con todas estas posibilidades. :)
Andreas Röhler