Ripetendo l'ultimo comando (complesso o no)


8

Emacs ha repeate repeat-complex-command, che disegnano comandi diversi dalla cronologia dei comandi e sono associati a chiavi diverse. Come si ripete ogni ultimo comando - se era complessa o meno - con una sola chiave? In altre parole, un tale comando ripetuto si comporterebbe come repeat-complex-commandse l'ultimo comando richiedesse un input, altrimenti si comporterebbe come repeat.

EDIT : In altre parole, sto cercando un modo per leggere l'ultimo comando, complesso o no, e quindi chiamare uno repeat-complex-commando repeatsu di esso, a seconda di quale sia appropriato. Ad esempio, supponiamo che sia associato un comando così nuovo <f8>. Poi:

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

  • (mimando C-x z (repeat)con C-f (forward-char)): C-u C-f <f8> <f8>sarà equivalente aC-u C-f C-x z z

Ora, repeat-complex-commandrichiede di confermare il modulo Lisp che verrà eseguito. Per consentire di ripetere un comando complesso senza conferma, ho scritto una versione alternativa di repeat-complex-command, chiamata repeat-complex-command-no-confirm(vedi sotto per l'implementazione). Il problema è che non riesco a capire come determinare se devo chiamare repeato repeat-complex-command-no-confirmquando premo <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")))))

Risposte:


5

Altri forniranno senza dubbio soluzioni diverse. Ecco il mio, dalla biblioteca misc-cmds.el.

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

Quindi basta definire un nuovo comando ripetuto per qualsiasi comando non ripetuto e rimappare i tasti dal non ripetitore al ripetitore. Per esempio:

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

In particolare, puoi usarlo per ripetere un comando che si trova su un tasto prefisso. Per esempio rimappatura next-bufferdi next-buffer-repeatmezzi che è possibile utilizzare C-x <right> <right>.... La chiave a cui è destinata, C-x <right>non deve necessariamente essere una chiave ripetuta (una che puoi semplicemente tenere premuta. Tutto ciò che ti serve è usare C-xuna volta e poi tenere premuto <right>.


Scusa, ho appena capito che vuoi anche ripetere un "comando complesso". In realtà (IMHO), ripetere un comando complesso è un termine improprio. Significa solo ripetere un comando con (di default) gli stessi argomenti. Ti permette intenzionalmente di modificare il sexp di Lisp che lo farà, quindi puoi, ad esempio, cambiare gli argomenti.

In breve, il comando repeat-complex-command(associato C-x ESC ESC, ad esempio) fa qualcosa di speciale e abbastanza diverso dal solo ripetere l'ultimo comando (cioè dal tipo di cosa che ho mostrato sopra). Non è chiaro cosa significhi ripetere ripetutamente un "comando complesso" o quale uso possa essere. IOW, l'idea di ripetere un comando, ad esempio tenendo premuto un tasto a cui è vincolata, è piuttosto diversa dall'uso repeat-complex-command, che avvia una finestra di dialogo che consente di modificare e quindi invocare un comando specificando determinati valori di argomento.

Quindi, a meno che tu non riesca a descrivere meglio ciò che hai in mente combinando in qualche modo la ripetizione dei comandi nel solito senso con ciò che repeat-complex-commandfa, temo di non poterti aiutare con quella parte della tua domanda.


Aggiorna dopo il tuo chiarimento.

Quindi questo è essenzialmente ciò che hai, per ripetere l'ultimo comando "complesso", ovvero l'ultimo comando che legge l'input dal minibuffer. (Si noti che è necessario rimuovere repeat-complex-command-no-confirmdalla cronologia.)

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

Puoi associarlo a un tasto ripetibile (es. C-o'). Or you can define a repeatable command usingRipeti-comando (i.e., passripeti-complesso-comando-no-conferma 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`).

Ma quando si utilizza tale chiave, invocando repeat-complex-command-no-confirm, si ripeterà l'ultimo comando che ha utilizzato il minibuffer, non necessariamente l'ultimo comando.

Ad ogni modo, puoi usare qualcosa di simile al seguente per ottenere ciò che dici di volere. L'ultima riga impedisce my-repeatdi essere l'ultimo comando, in modo che il riutilizzo non tenti di ripetere my-repeatma ripete l'ultimo comando ripetuto.

(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

Questa domanda ha risposte che spiegano le differenze tra comando ripetizione e comando complesso ripetuto .
Utente Emacs l'

@EmacsUser: Sì, come puoi vedere, la domanda che hai collegato è su tutta la mappa - la domanda non era chiara, quindi le risposte sono di vasta portata. Sono tutti pertinenti a una certa interpretazione della domanda, ma sono un miscuglio. (Vedi il mio commento a questa risposta c'è.)
Drew

sì, grazie per il chiarimento. Questa risposta sicuramente aiuta chiunque a scavare più a fondo.
Utente Emacs l'

@ Grazie Grazie per la risposta dettagliata. Ho ampliato la mia domanda e, si spera, ora è più chiara.
Elena,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.