Répétition d'une dernière commande (complexe ou non)

8

Emacs a repeatet repeat-complex-command, qui tirent différentes commandes de l'historique des commandes et sont liés à différentes clés. Comment répétez-vous une dernière commande - qu'elle soit complexe ou non - avec une seule touche? En d'autres termes, une telle commande répétée se comporterait comme repeat-complex-commandsi la dernière commande nécessitait une entrée, sinon elle se comporterait comme repeat.

EDIT : En d'autres termes, je cherche un moyen de lire la dernière commande, complexe ou non, puis d'appeler soit repeat-complex-commandou repeatdessus, selon ce qui est approprié. Par exemple, disons qu'une telle nouvelle commande est liée à <f8>. Alors:

  • (imitant C-x M-: (repeat-complex-command)avec M-z (zap-to-char)): C-u M-z a <f8> <f8>sera équivalent àC-u M-z a C-x M-: RET C-x M-: RET

  • (imitant C-x z (repeat)avec C-f (forward-char)): C-u C-f <f8> <f8>sera équivalent àC-u C-f C-x z z

Maintenant, repeat-complex-commandvous oblige à confirmer le formulaire Lisp qui sera exécuté. Pour permettre de répéter une commande complexe sans confirmation, j'ai écrit une version alternative de repeat-complex-command, appelée repeat-complex-command-no-confirm(voir ci-dessous pour l'implémentation). Le problème est que je ne comprends pas comment déterminer si je dois appeler repeatou repeat-complex-command-no-confirmquand j'appuie <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
la source

Réponses:

5

D'autres apporteront sans aucun doute des solutions différentes. Voici le mien, de la bibliothèque misc-cmds.el.

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

Ensuite, définissez simplement une nouvelle commande répétitive pour toute commande non répétitive et remappez les clés du non-répéteur au répéteur. Par exemple:

(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 particulier, vous pouvez l'utiliser pour répéter une commande qui se trouve sur une clé de préfixe. Par exemple, le remappage next-buffervers next-buffer-repeatsignifie que vous pouvez utiliser C-x <right> <right>.... La clé à laquelle elle est liée C-x <right>, n'a pas besoin d'être une clé répétitive (une clé que vous pouvez simplement maintenir enfoncée. Tout ce dont vous avez besoin est d'utiliser C-xune fois, puis de la maintenir enfoncée <right>.


Désolé, je viens de réaliser que vous souhaitez également répéter une "commande complexe". En fait (à mon humble avis), répéter une commande complexe est un terme impropre. Cela signifie simplement répéter une commande avec (par défaut) les mêmes arguments. Il vous permet délibérément d'éditer le sexp Lisp qui fera cela, de sorte que vous pouvez, par exemple, changer les arguments.

En somme, la commande repeat-complex-command(liée à C-x ESC ESC, par exemple) fait quelque chose de spécial et tout à fait différent de simplement répéter la dernière commande (c'est-à-dire du genre de chose que j'ai montré ci-dessus). On ne sait pas ce que la répétition répétée d'une "commande complexe" pourrait signifier ou à quoi elle servirait. IOW, la notion de répétition d'une commande, par exemple en maintenant enfoncée une touche à laquelle elle est liée, est très différente de l'utilisation repeat-complex-command, qui ouvre une boîte de dialogue qui vous permet de modifier puis d'appeler une commande spécifiant des valeurs d'argument particulières.

Donc, à moins que vous ne puissiez mieux décrire ce que vous avez en tête en combinant d'une manière ou d'une autre la répétition de commandes dans le sens habituel avec ce qui le repeat-complex-commandfait, je crains de ne pas pouvoir vous aider avec cette partie de votre question.


Mettre à jour après votre clarification.

C'est donc essentiellement ce que vous avez, pour répéter la dernière commande "complexe", c'est-à-dire la dernière commande qui lit l'entrée du mini-tampon. (Notez que vous devez supprimer repeat-complex-command-no-confirmde l'historique.)

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

Vous pouvez le lier à une clé répétable (par exemple, C-o'). Or you can define a repeatable command usingrépétition-commande répétition-commande (i.e., pass-complexe-non-confirmation 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`).

Mais lorsque vous utilisez une telle clé, en invoquant repeat-complex-command-no-confirm, vous répéterez la dernière commande qui a utilisé le mini-tampon, pas nécessairement la dernière commande.

Quoi qu'il en soit, vous pouvez utiliser quelque chose comme ce qui suit pour obtenir ce que vous voulez. La dernière ligne empêche my-repeatd'être la dernière commande, de sorte que sa réutilisation n'essaye pas de répéter my-repeatmais répète la dernière commande répétée.

(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
A dessiné
la source
Cette question a des réponses qui expliquent les différences entre la répétition et la répétition-commande-complexe .
Emacs User
@EmacsUser: Oui, comme vous pouvez le voir, cette question que vous avez liée est partout sur la carte - la question n'était pas claire, donc les réponses sont très variées. Ils sont tous pertinents pour une certaine interprétation de la question, mais ils sont mélangés. (Voir mon commentaire à cette réponse là-bas.)
Drew
oui, merci d'avoir clarifié. Cette réponse aide certainement quiconque à creuser plus profondément.
Emacs User
@Drew Merci pour votre réponse détaillée. J'ai élargi ma question et, espérons-le, elle est maintenant plus claire.
Elena