Come si possono "ripristinare" le modifiche dopo "annulla" con Emacs?


268

Questo articolo afferma che "Emacs ha ripetuto perché è possibile invertire la direzione durante l'annullamento, annullando così l'annullamento".

Cosa significa questo? Come può un utente "ripetere" con Emacs?


3
La risposta sotto la risposta accettata ti dice come , se è per questo che stai guardando questa risposta, che, dato come è scritto, mi aspetterei che la maggior parte delle persone lo stia effettivamente cercando.
Aaron Hall

Ho appena colpito la barra spaziatrice, e poi ho annullato dopo che ho annullato lo spazio e ho ripetuto gli annullamenti che hai fatto fino a quando non arriva alla fine e poi ricomincia da capo ... So che ci sono modi molto più complicati, ma questo è veloce e facile, ed è così che rotolo.
annullato il

Risposte:


294

Versione breve: annullando l'annullamento. Se si annulla e si esegue un comando non di modifica come C-f, quindi l'annullamento successivo annulla l'annullamento, con conseguente ripetizione.

Versione più lunga:

Puoi pensare di annullare come operando su una pila di operazioni. Se si esegue un comando (anche un comando di navigazione come C-f) dopo una sequenza di operazioni di annullamento, tutti gli annullamenti vengono inseriti nello stack delle operazioni. Quindi il prossimo annullamento annulla l'ultimo comando. Supponiamo di avere una sequenza di operazioni simile a questa:

  1. Inserisci "pippo"
  2. Inserisci "barra"
  3. Inserisci "I love spam"

Ora annulli. Annulla l'ultima azione, risultante nel seguente elenco:

  1. Inserisci "pippo"
  2. Inserisci "barra"

Se a questo punto fai qualcosa di diverso dall'annullamento, ad esempio C-f, lo stack di operazioni è simile al seguente:

  1. Inserisci "pippo"
  2. Inserisci "barra"
  3. Inserisci "I love spam"
  4. Annulla l'inserimento "I love spam"

Ora, quando annulli, la prima cosa che viene annullata è l'annullamento. Risultato nella pila originale (e nello stato del documento):

  1. Inserisci "pippo"
  2. Inserisci "barra"
  3. Inserisci "I love spam"

Se si esegue un comando di modifica per interrompere la sequenza di annullamento, tale comando viene aggiunto dopo l'annullamento ed è quindi la prima cosa da annullare successivamente. Supponiamo che tu abbia spostato indietro la "barra" invece di colpire C-f. Quindi avresti avuto

  1. Inserisci "pippo"
  2. Inserisci "barra"
  3. Inserisci "I love spam"
  4. Annulla l'inserimento "I love spam"
  5. Elimina "barra"

Questa aggiunta / nuova aggiunta avviene all'infinito. Ci vuole un po 'per abituarsi, ma dà davvero a Emacs un meccanismo di annullamento / ripetizione altamente flessibile e potente.


117
Nel caso in cui ciò sembri fastidioso, il vantaggio principale è che puoi sempre tornare a uno stato precedente. Nella maggior parte dei redattori, annullare diverse modifiche e quindi digitare accidentalmente un personaggio ti lascerebbe "bloccato" senza alcun modo per ripetere ciò che hai annullato. Emacs lo rende banale.
phils,

3
Suppongo che nella tua costruzione, se una persona volesse farlo su carta, avresti bisogno di due pile. Perché se per esempio, nel punto in cui hai scritto "Ora, annulli. Annulla l'ultima azione, risultante nel seguente list: "tu (comprensibilmente) non hai mostrato l'annullamento, e se avesse fatto molti annullamenti, non li mostreresti fino a quando non fosse stato fatto qualcosa per interrompere la sequenza di annullamento, quindi li avresti aggiunti. Un altro modo per mostrare sarebbe avere un elenco e aggiungere annullamenti all'elenco anche prima che vengano interrotti, ma per notare dove si trova il cursore nell'elenco, quindi sappiamo da dove lavorano gli annullamenti all'indietro
barlop

25
Sembra fastidioso.
Felipe,

13
Non so perché questa risposta sia stata accettata quando non ti dice nemmeno COME .
Aaron Hall

8
Purtroppo questa risposta non dice nulla sul comando redo che è Cg C- /.
vishnuprasanth,

211

Per annullare: C-_

Per ripetere dopo un annullamento: C-g C-_

Digita più volte C-_ per ripetere ciò che è stato annullato C-_ Per ripetere un comando emacs più volte, esegui il comando quindi digita C-xze quindi digita più volte sul ztasto per ripetere il comando (interessante quando vuoi eseguire più volte una macro)


4
Per ripetere cose che puoi anche usare C-u, per esempio C-u 8 *(inserisce otto * dove si trova il cursore). Quindi puoi usare C-u x C-_per annullare x passaggi.
Patrick,

10
Questo non ha nulla a che fare con la domanda originale, ma subito dopo aver eseguito una macro di tastiera (con C-x e), puoi semplicemente premere tutte ele volte che devi eseguirla di nuovo.
Christian Berg,

7
Inoltre, C-/e C-x usono combinazioni di tasti Annulla alternativi, equivalenti a C-_. Preferisco C-/poiché è più facile colpire.
Rory O'Kane,

8
Avvertenza: quando questa risposta dice che C-g C-_verrà "ripetuto dopo un annullamento", questo si applica solo la prima volta che si preme la combinazione. Successivamente, ripeti il ​​tasto Annulla senza C-g. Quindi, per ripetere tre volte subito dopo l'annullamento, digitare C-g C-_ C-_ C-_. Se digiti C-g C-_ C-g C-_ C-g C-_, ti limiterai a girare in tondo, annullando la ripetizione del tuo annullamento ...
Rory O'Kane

@ RoryO'Kane Non so molto di emacs, quindi per favore correggimi dove sbaglio, ma dato che Cg C-_ non ha alcun effetto dopo una ripetizione, potrebbe essere perché funziona solo dopo un annullamento (come suggerisce la descrizione "ripeti dopo un annullamento". Quindi non è così tanto che sta andando in cerchio ripetendo un annullamento o una ripetizione ecc. non sta facendo nulla perché un annullamento non è stato appena fatto prima di esso. Cg C- _ Cg C-_ non va in cerchio dopo il primo, non fa letteralmente nulla.
barlop

56
  • Per annullare una volta:C-/
  • Per annullare due volte: C-/ C-/
  • Per ripetere una volta, subito dopo l'annullamento:C-g C-/
  • Per ripetere due volte, subito dopo aver svitato: C-g C-/ C-/. Si noti che C-gnon si ripete.
  • Per annullare di nuovo immediatamente , una volta:C-g C-/
  • Per annullare di nuovo immediatamente, due volte: C-g C-/ C-/
  • Per ripetere ancora , lo stesso ...

Se hai premuto un tasto (sia digitando caratteri che spostando il cursore) dall'ultimo comando di annullamento, non è necessario digitare C-gprima del prossimo annullamento / ripetizione. C-gè solo un tasto sicuro da premere che non fa nulla da solo, ma conta come un tasto di non annullamento per segnalare la fine della sequenza di annullamento. Premendo un altro comando come C-fpotrebbe funzionare anche; è solo che avrebbe spostato il cursore da dove lo avevi.

Se premi C-go un altro comando quando non volevi, e ora stai annullando nella direzione sbagliata, premi semplicemente C-gper invertire nuovamente la direzione. Dovrai annullare tutto attraverso le ripetizioni e le annullamenti accidentali prima di arrivare alle annullamenti che desideri, ma se continui a colpire C-/, alla fine raggiungerai lo stato desiderato. In effetti, ogni stato in cui il buffer è mai stato è raggiungibile, se si C-gpreme una volta e poi si preme C-/abbastanza volte.

Scorciatoie alternative per undo, diversi C-/, sono C-_, C-x ue M-x undo.

Vedi Annulla nel Manuale di Emacs per maggiori dettagli sul sistema di annullamento di Emacs.


38

Per coloro che desiderano avere le funzionalità di annullamento / ripetizione più comuni, qualcuno ha scritto undo-tree.el. Fornisce l'aspetto e la sensazione di annullamento dei non-Emac, ma fornisce l'accesso all'intero "albero" della cronologia degli annullamenti.

Mi piace il sistema di annullamento integrato di Emacs, ma trovo questo pacchetto molto intuitivo.

Ecco il commento dal file stesso:

Emacs ha un potente sistema di annullamento. A differenza del sistema di annullamento / ripetizione standard nella maggior parte dei software, consente di ripristinare qualsiasi stato passato di un buffer (mentre il sistema di annullamento / ripetizione standard può perdere gli stati passati non appena si esegue la ripetizione). Tuttavia, questo potere ha un prezzo: molte persone trovano il sistema di annullamento di Emacs confuso e difficile da usare, generando una serie di pacchetti che lo sostituiscono con il sistema di annullamento / ripetizione meno potente ma più intuitivo.

Sia la perdita di dati con l'annullamento / ripetizione standard, sia la confusione dell'annullamento di Emacs derivano dal tentativo di trattare la cronologia degli annullamenti come una sequenza lineare di modifiche. Non è. La "modalità di annullamento dell'albero" fornita da questo pacchetto sostituisce il sistema di annullamento di Emacs con un sistema che considera la cronologia degli annullamenti come quella che è: un albero ramificato di modifiche. Questa semplice idea consente di combinare il comportamento più intuitivo del sistema di annullamento / ripetizione standard con la potenza di non perdere mai alcuna cronologia. Un ulteriore vantaggio aggiuntivo è che in alcuni casi la cronologia degli annullamenti può essere archiviata in modo più efficiente, consentendo di accumulare più modifiche prima che Emacs inizi a scartare la cronologia.


3
Fantastico! Chi ha detto che l'annullamento di emacs era insondabile? :-)
Peter.O

Sorprendente! concettualmente sano e intuitivo per l'utente. Questo dovrebbe essere nei pacchetti predefiniti. Un commento: vorrei che fosse visualizzato anche un messaggio di avviso durante la ripetizione da un punto di diramazione, non solo quando si ripristina. Ad esempio, quando l'utente chiama una ripetizione: 'Ripeti da un punto di diramazione' o 'Ramo di ripetizione predefinito usato' - solo per avvisare l'utente che ci sono più diramazioni.
Basilea Shishani,

1
Un altro approccio a questo problema che è molto più semplice da implementare e non richiede un visualizzatore è quello di mantenere SOLO l'ultimo punto di diramazione e fornire 3 comandi: annulla, ripristina, cambia-diramazione. Annulla / Ripeti avviserà quando viene colpito IL ramo e cambia-ramo cambierà semplicemente se in un ramo altro emette semplicemente un messaggio "non in un ramo". Se la ramificazione si verifica in qualsiasi momento, il punto di diramazione precedente viene perso. Ciò risolverebbe il problema della perdita di stato ragionevolmente bene e con una complessità minima.
Basilea Shishani,

1
Attenzione, questo ha un bug di vecchia data in redo che può fallire casualmente: github.com/syl20bnr/spacemacs/issues/9903 - noto dal 2014
ideasman42

@ ideasman42 Apparentemente si tratta di un "non-bug": dr-qubit.org/Lost_undo-tree_history.html
Dalker

19

Fai attenzione a una stranezza di annullamento dell'albero per ripetere !

Molti popolari "kit di base" (preludio, purcell, spacemacs) vengono forniti in bundle con undo-tree. La maggior parte (tutto?) Lo abilita anche automaticamente. Come accennato, l'annullamento dell'albero è un modo pratico per visualizzare e attraversare l'albero di annullamento / ripetizione. Prelude fornisce anche un key-chord ( uu) e anche C-x u.

Il problema è: undo-albero sembra naufragare di default Emacs' e ben noto vincolante per redo :C-g C-/ .

Invece, puoi usare questi tasti simmetrici per annullare / ripetere :

C-/     undo
C-S-/   redo

Questi sono utili poiché a volte si desidera ripetere rapidamente senza aprire il visualizzatore.


Questo. Sto usando Spacemacs e non sono riuscito a capire perché non funzionasse per me. Grazie!
mghaoui,

11

Trovo redo.elestremamente utile eseguire annulla / ripristina "normale" e di solito lo associo a CSz e annulla a Cz, in questo modo:

(when (require 'redo nil 'noerror)
    (global-set-key (kbd "C-S-z") 'redo))

(global-set-key (kbd "C-z") 'undo)

Basta scaricare il file, inserirlo nel percorso lisp e incollare quanto sopra nel proprio .emacs.


I commenti nell'intestazione di redo.el dicono che è fatto per XEmacs. C'è qualche problema nell'usarlo in GNU Emacs e in altri Emacsen correlati?
A. Levy,

Non ho ancora avuto problemi e lo uso da almeno 6 mesi :)
monotux

4
Da emacswiki.org/emacs/RedoMode : Tuttavia, redo.el è obsoleto e spesso distrugge il contenuto di "buffer perché il comportamento di" primitive-undo "è stato leggermente diverso da quello precedente da Emacs 22. RedoPlus è un fork di redo.el e funziona correttamente nella nuova versione di Emacs. Puoi ottenere RedoPlus qui: emacswiki.org/emacs/redo+.el
rofrol

2

Emacs 28 aggiunge un comando redo (chiamato undo-redo).

Se si desidera avere le operazioni di annullamento / ripetizione più tipiche, è possibile utilizzare i seguenti comandi.

(global-set-key (kbd "C-z") 'undo-only)
(global-set-key (kbd "C-S-z") 'undo-redo)

1

Se si desidera ripetere l'ultima operazione, procedere come segue.

  1. ESC
  2. Fai un altro undo ( C + /)

0

Per impostazione predefinita, ripetere in Emacs richiede di premere Cg, quindi annullare.

Tuttavia è possibile utilizzare l'annullamento incorporato di Emacs per implementare anche un comando redo.

Il pacchetto undo-fu , utilizza la funzionalità di annullamento integrata di Emacs per esporre sia annulla che ripristina.

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.