Wiederholen eines letzten Befehls (komplex oder nicht)

8

Emacs hat repeatund repeat-complex-command, die verschiedene Befehle aus dem Befehlsverlauf ziehen und an verschiedene Schlüssel gebunden sind. Wie können Sie einen letzten Befehl - ob komplex oder nicht - mit einer einzigen Taste wiederholen ? Mit anderen Worten, ein solcher sich wiederholender Befehl würde sich so verhalten, als repeat-complex-commandob der letzte Befehl eine Eingabe erfordern würde, andernfalls würde er sich so verhalten repeat.

EDIT : Mit anderen Worten, ich suche nach einer Möglichkeit, den letzten Befehl zu lesen, ob komplex oder nicht, und dann entweder repeat-complex-commandoder darauf aufzurufen repeat, je nachdem, was angemessen ist. Nehmen wir zum Beispiel an, dass ein solcher neuer Befehl an gebunden ist <f8>. Dann:

  • (imitiert C-x M-: (repeat-complex-command)mit M-z (zap-to-char)): C-u M-z a <f8> <f8>entspricht äquivalent zuC-u M-z a C-x M-: RET C-x M-: RET

  • (imitiert C-x z (repeat)mit C-f (forward-char)): C-u C-f <f8> <f8>entspricht äquivalent zuC-u C-f C-x z z

Jetzt repeat-complex-commandmüssen Sie das Lisp-Formular bestätigen, das ausgeführt wird. Um das Wiederholen eines komplexen Befehls ohne Bestätigung zu ermöglichen, habe ich eine alternative Version von geschrieben repeat-complex-command, die aufgerufen wird repeat-complex-command-no-confirm(siehe unten für die Implementierung). Das Problem ist, dass ich nicht verstehen kann, wie ich bestimmen soll, ob ich anrufen soll repeatoder repeat-complex-command-no-confirmwann ich drücke <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
quelle

Antworten:

5

Andere werden zweifellos andere Lösungen anbieten. Hier ist meine aus der Bibliothek misc-cmds.el.

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

Definieren Sie dann einfach einen neuen, sich wiederholenden Befehl für einen sich nicht wiederholenden Befehl und ordnen Sie die Schlüssel vom Nicht-Repeater dem Repeater neu zu. Zum Beispiel:

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

Damit können Sie insbesondere einen Befehl wiederholen, der sich auf einem Präfixschlüssel befindet. Zum Beispiel bedeutet Neuzuordnung next-bufferzu next-buffer-repeat, dass Sie verwenden können C-x <right> <right>.... Der Schlüssel, an den es gebunden ist C-x <right>, muss kein sich wiederholender Schlüssel sein (einer, den Sie einfach gedrückt halten können. Sie müssen ihn nur C-xeinmal verwenden und dann gedrückt halten <right>.


Entschuldigung, ich habe gerade festgestellt, dass Sie auch einen "komplexen Befehl" wiederholen möchten. Tatsächlich (IMHO) ist das Wiederholen eines komplexen Befehls eine falsche Bezeichnung. Es bedeutet nur, einen Befehl mit (standardmäßig) denselben Argumenten zu wiederholen. Sie können damit gezielt das Lisp-Sexp bearbeiten, das dies tut, sodass Sie beispielsweise die Argumente ändern können.

In der Summe macht der Befehl repeat-complex-command( C-x ESC ESCzum Beispiel gebunden ) etwas Besonderes und ganz anderes, als nur den letzten Befehl zu wiederholen (dh von dem, was ich oben gezeigt habe). Es ist nicht klar, was das wiederholte Wiederholen eines "komplexen Befehls" bedeuten könnte oder welchen Nutzen es haben würde. IOW, der Gedanke, einen Befehl zu wiederholen, z. B. indem Sie einen Schlüssel gedrückt halten, an den er gebunden ist, unterscheidet sich erheblich von der Verwendung repeat-complex-command, bei der ein Dialogfeld initiiert wird, in dem Sie einen Befehl bearbeiten und dann aufrufen können, der bestimmte Argumentwerte angibt.

Wenn Sie also nicht besser beschreiben können, was Sie vorhaben, indem Sie die Befehlswiederholung im üblichen Sinne mit dem kombinieren, was repeat-complex-commandich tue, kann ich leider bei diesem Teil Ihrer Frage nicht helfen.


Update nach Ihrer Klarstellung.

Dies ist also im Wesentlichen das, was Sie haben, um den letzten "komplexen" Befehl zu wiederholen, dh den letzten Befehl, der Eingaben aus dem Minibuffer liest. (Beachten Sie, dass Sie repeat-complex-command-no-confirmaus dem Verlauf entfernen müssen .)

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

Sie können dies an einen wiederholbaren Schlüssel binden (z. B. C-o'). Or you can define a repeatable command usingWiederholungsbefehl (i.e., passWiederholungskomplex-Befehl-Nein-Bestätigung 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`).

Wenn Sie jedoch beim Aufrufen einen solchen Schlüssel verwenden, repeat-complex-command-no-confirmwiederholen Sie den letzten Befehl, der den Minibuffer verwendet hat, nicht unbedingt den letzten Befehl.

Auf jeden Fall können Sie Folgendes verwenden, um das zu erhalten, was Sie möchten. Die letzte Zeile verhindert my-repeat, dass es sich um den letzten Befehl handelt, sodass bei erneuter Verwendung nicht versucht wird, my-repeatden zuletzt wiederholten Befehl zu wiederholen, sondern wiederholt wird.

(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
Drew
quelle
Diese Frage enthält Antworten, die die Unterschiede zwischen Wiederholungs- und Wiederholungskomplexbefehl erklären .
Emacs User
@EmacsUser: Ja, wie Sie sehen können, ist die von Ihnen verknüpfte Frage überall auf der Karte zu finden. Die Frage war unklar, daher sind die Antworten weitreichend. Sie sind alle für eine Interpretation der Frage relevant, aber sie sind eine gemischte Tasche. (Siehe meinen Kommentar zu dieser Antwort dort.)
Drew
Ja, danke für die Klarstellung. Diese Antwort hilft sicherlich jedem, tiefer zu graben.
Emacs User
@Drew Danke für deine ausführliche Antwort. Ich habe meine Frage erweitert und hoffentlich ist es jetzt klarer.
Elena