Repetir cualquier último comando (complejo o no)

8

Emacs tiene repeaty repeat-complex-command, que dibujan diferentes comandos del historial de comandos y están vinculados a diferentes teclas. ¿Cómo repite cualquier último comando, ya sea complejo o no, con una sola tecla? En otras palabras, tal comando repetitivo se comportaría como repeat-complex-commandsi el último comando requiriera entrada, de lo contrario se comportaría como repeat.

EDITAR : en otras palabras, estoy buscando una forma de leer el último comando, complejo o no, y luego llamarlo repeat-complex-commando repeathacerlo, según sea apropiado. Por ejemplo, supongamos que un nuevo comando está obligado a hacerlo <f8>. Entonces:

  • (imitando C-x M-: (repeat-complex-command)con M-z (zap-to-char)): C-u M-z a <f8> <f8>será equivalente aC-u M-z a C-x M-: RET C-x M-: RET

  • (imitando C-x z (repeat)con C-f (forward-char)): C-u C-f <f8> <f8>será equivalente aC-u C-f C-x z z

Ahora, repeat-complex-commandrequiere que confirme el formulario Lisp que se ejecutará. Para permitir la repetición de un comando complejo sin confirmación, he escrito una versión alternativa de repeat-complex-command, llamada repeat-complex-command-no-confirm(ver más abajo para la implementación). El problema es que no puedo entender cómo determinar si debo llamar repeato repeat-complex-command-no-confirmal presionar <f8>.

-

(defun repeat-complex-command-no-confirm (arg)
  "Like `repeat-complex-command' but does not require confirmation."
  ;; Adapted from `repeat-complex-command' of Emacs 24.5.1.
  (interactive "p")
  (let ((elt (nth (1- arg) command-history))
        newcmd)
    (if elt
        (progn
          (setq newcmd elt)

          ;; If command to be redone does not match front of history,
          ;; add it to the history.
          (or (equal newcmd (car command-history))
              (setq command-history (cons newcmd command-history)))
          (unwind-protect
              (progn
                ;; Trick called-interactively-p into thinking that `newcmd' is
                ;; an interactive call (bug#14136).
                (add-hook 'called-interactively-p-functions
                          #'repeat-complex-command--called-interactively-skip)
                (eval newcmd))
            (remove-hook 'called-interactively-p-functions
                         #'repeat-complex-command--called-interactively-skip)))
      (if command-history
          (error "Argument %d is beyond length of command history" arg)
        (error "There are no previous complex commands to repeat")))))
Elena
fuente

Respuestas:

5

Otros sin duda proporcionarán diferentes soluciones. Aquí está el mío, de la biblioteca misc-cmds.el.

(defun repeat-command (command)
  "Repeat COMMAND."
  (let ((repeat-message-function  'ignore))
    (setq last-repeatable-command  command)
    (repeat nil)))

Luego, simplemente defina un nuevo comando repetitivo para cualquier comando que no se repita y vuelva a asignar las teclas del no repetidor al repetidor. Por ejemplo:

(defun next-buffer-repeat ()
  "Switch to the next buffer in the selected window.
You can repeat this by hitting the last key again..."
  (interactive)
  (require 'repeat)
  (repeat-command 'next-buffer))

(global-set-key [remap next-buffer] 'next-buffer-repeat)

En particular, puede usar esto para repetir un comando que está en una tecla de prefijo. Por ejemplo, reasignar next-buffera next-buffer-repeatsignifica que puede usar C-x <right> <right>.... La tecla a la que está destinada C-x <right>no necesita ser una tecla de repetición (una que pueda mantener presionada. Todo lo que necesita es usar C-xuna vez y luego mantener presionada <right>.


Lo siento, me acabo de dar cuenta de que también quieres repetir un "comando complejo". En realidad (en mi humilde opinión), repetir un comando complejo es un nombre inapropiado. Simplemente significa repetir un comando con (por defecto) los mismos argumentos. A propósito, le permite editar el sexp de Lisp que lo hará, por lo que puede, por ejemplo, cambiar los argumentos.

En resumen, el comando repeat-complex-command(obligado C-x ESC ESC, por ejemplo) hace algo especial y bastante diferente de simplemente repetir el último comando (es decir, del tipo de cosas que mostré anteriormente). No está claro qué podría significar repetir repetidamente un "comando complejo" o qué uso tendría. IOW, la noción de repetir un comando, por ejemplo, manteniendo presionada una tecla a la que está vinculada, es bastante diferente del uso repeat-complex-command, que inicia un diálogo que le permite editar y luego invocar un comando que especifica valores de argumentos particulares.

Entonces, a menos que pueda describir mejor lo que tiene en mente combinando de alguna manera la repetición de comandos en el sentido habitual con lo que repeat-complex-commandhace, me temo que no puedo ayudar con esa parte de su pregunta.


Actualización después de su aclaración.

Entonces, esto es esencialmente lo que tiene, para repetir el último comando "complejo", es decir, el último comando que lee la entrada del minibúfer. (Tenga en cuenta que debe eliminarlo repeat-complex-command-no-confirmdel historial).

(defun repeat-complex-command-no-confirm ()
  "..."
  (interactive)
  (let* ((hist  command-history)
         newcmd)
    (while (eq 'repeat-complex-command-no-confirm (caar hist))
      (setq hist  (cdr hist)))
    (setq newcmd  (car hist))
    (if newcmd
        (apply #'funcall-interactively (car newcmd)
               (mapcar (lambda (ee) (eval ee t)) (cdr newcmd)))
      (error "There are no previous complex commands to repeat"))))

Puede vincular eso a una tecla repetible (por ejemplo, C-o'). Or you can define a repeatable command usingrepetir-comando (i.e., passrepetir-complejo-comando-no-confirmar to it), to be able to have it work when bound to a repeatable key that is on a prefix key (e.g.C-x o`).

Pero cuando use dicha clave, invocando repeat-complex-command-no-confirm, repetirá el último comando que utilizó el minibúfer, no necesariamente el último comando.

De todos modos, puede usar algo como lo siguiente para obtener lo que dice que quiere. La última línea evita que my-repeatsea ​​el último comando, por lo que usarla nuevamente no intenta repetir my-repeatsino que repite el último comando repetido.

(defun my-repeat ()
  "..."
  (interactive)
  (if (eq last-command (caar command-history))
      (repeat-complex-command-no-confirm)
    (call-interactively last-command))
  (setq this-command  last-command))

(global-set-key "\C-o" 'my-repeat) ; Bind it to a repeatable key
Dibujó
fuente
Esta pregunta tiene respuestas que explican las diferencias entre la repetición y el comando complejo-repetición .
Usuario de Emacs
@EmacsUser: Sí, como puedes ver, esa pregunta que vinculaste está en todo el mapa; la pregunta no estaba clara, por lo que las respuestas son de gran alcance. Todos son pertinentes para alguna interpretación de la pregunta, pero son una mezcla. (Vea mi comentario a esta respuesta allí.)
Drew
Sí, gracias por aclarar. Esa respuesta ciertamente ayuda a cualquiera a cavar más profundo.
Usuario de Emacs
@Drew Gracias por tu respuesta detallada. He ampliado mi pregunta y, con suerte, ahora está más clara.
Elena