Wie ändere ich einen Puffer, ohne es zu merken?

11

F: Wie füge ich Text in einen Puffer ein / ändere ihn, ohne es zu undomerken?

Hier ist der Anwendungsfall. Ich habe am Anfang jeder Datei einen Kommentarblock, der unter anderem einen Zeitstempel für die letzte Änderung an einer Datei aktualisiert. Ich möchte diesen Zeitstempel ändern können, ohne dass die undoEinrichtungen dies bemerken.

Der Grund, warum ich undohier kurzschließen möchte, ist der folgende Randfall, der beim Bearbeiten / Kompilieren von LaTeX-Dokumenten auftritt (und wahrscheinlich auch andere, aber dies ist derjenige, der mich am häufigsten verrückt macht):

  1. Nehmen Sie eine kleine Änderung an der Datei vor, um zu sehen, wie sich dies auf das kompilierte Dokument auswirkt
  2. Speichern Sie die Datei (wodurch der Zeitstempel aktualisiert wird).
  3. Führen Sie latexdie Datei aus
  4. Entscheide, dass die Änderung schlecht ist
  5. undo die Veränderungen

Das Problem in Schritt (5) ( undo) besteht darin, dass die in Schritt (1) vorgenommene Änderung nicht rückgängig gemacht wird, sondern die in Schritt (2) aktualisierte Zeitstempel-Aktualisierung rückgängig gemacht wird. Das würde mich nicht stören (ich könnte es einfach noch undoeinmal tun ), außer dass es sich auch bis zum Zeitstempel oben in der Datei bewegt, was fast immer viele, viele Zeilen von der eigentlichen inhaltlichen Änderung entfernt ist. Es ist sehr irritierend und bricht meine Konzentration völlig.

Ich stelle die Frage in Bezug auf eine Datei, die ich besuche, aber es geht allgemeiner darum, Puffer zu ändern.

Also: Wie kann ich verhindern, undodass eine bestimmte Änderung an einem Puffer bemerkt wird?

Dan
quelle
1
Dies hängt nicht mit Ihrer Rückgängig-Frage zusammen, kann aber bei dem Problem "Rückgängig macht den Punkt" hilfreich sein
Kindermädchen
2
Wäre es nicht am besten, wenn diese Änderung des Datumsstempels an das neueste Element in der Rückgängig-Geschichte angehängt würde? Auf diese Weise undowürden beide rückgängig gemacht.
Malabarba
Ich denke, was du wirklich willst, ist atomic-change-group.
@ John: Wie würde das helfen? Die beiden Änderungen an der Gruppe werden durch separate Befehle ausgelöst: eine „kleine Änderung“ (z. B. ein Einfügen) und die Aktualisierung des Zeitstempels beim Speichern.
Gilles 'SO - hör auf böse zu sein'
Beachten Sie, dass aus irgendeinem Grund keine dieser Methoden in vorhandenen Antworten für mich funktioniert hat. Diese Antwort definiert jedoch ein with-undo-collapseMakro, das sehr nützlich war: emacs.stackexchange.com/a/7560/2418
ideasman42

Antworten:

6

Die Antwort von @ stsquad hat mich auf den richtigen Weg gebracht. Grundsätzlich sind die Schritte:

  1. speichern buffer-undo-list
  2. deaktivieren undo
  3. mach dein Ding
  4. Aktivieren undound wiederherstellen Sie diebuffer-undo-list

Hier ist eine Skizze einer solchen Funktion:

(defun disable-undo-one-off ()
  (let ((undo buffer-undo-list))        ; save the undo list
    (buffer-disable-undo)               ; disable undo
    (do-some-stuff)                     ; do your thing
    (buffer-enable-undo)                ; re-enable undo
    (setq buffer-undo-list undo)))      ; restore the undo list

Bearbeiten:let Tatsächlich stellt sich heraus, dass eine einfachere Lösung immer noch darin besteht, einfach zu binden, buffer-undo-listsodass Änderungen an der Liste im Hauptteil des letGet Clobbers auftreten, wenn die ursprüngliche Liste wiederhergestellt wird:

(defun disable-undo-one-off ()
  (let (buffer-undo-list)
    (do-some-stuff)))

Die Hauptbeschränkung dabei ist, dass es für Modifikationen zu funktionieren scheint, die die Anzahl der Zeichen im Puffer nicht ändern (z. B. "Kätzchen" in "Welpen" ändern, aber nicht "Katzen"), da sonst der Rest rückgängig gemacht wird Liste bezieht sich jetzt auf die falschen Punkte. Daher ist dies nur eine Teillösung .

Dan
quelle
Vielleicht möchten Sie das in einen Entspannungsschutz einwickeln, falls Sie mitten in Ihrem Ding aus der Aktivität ausbrechen. Ich wusste nicht, dass Sie dies alles in einer Funktion tun, die es einfacher macht, den Überblick zu behalten.
stsquad
Können Sie der Lösung auch eine Aktualisierung des Zeitstempels hinzufügen, um den Rückgängig-Verlauf (und den Punktverlauf, falls möglich) nicht zu aktualisieren?
Kaushal Modi
@stsquad: gute Idee, werde es später versuchen. Nochmals vielen Dank für den Hinweis auf die fraglichen Funktionen und Listen.
Dan
@kaushalmodi: Klärende Frage: Bedeutet das, dass Sie die aktuelle Zeitstempel-Aktualisierungsfunktion sehen möchten?
Dan
@Dan Möchten Sie sehen, wie Sie die Zeitstempel-Aktualisierungsfunktion so ändern, dass der Rückgängig- oder Punktverlauf nicht aktualisiert wird.
Kaushal Modi
3

Eine Rückgängig-Operation kombiniert mehrere Elemente aus der Rückgängig-Liste . Ein nilEintrag in der Liste markiert die Grenze zwischen zwei Änderungsgruppen. Durch Entfernen der nilam Anfang der Liste automatisch eingefügten Liste, die automatisch von der Toplevel-Schleife¹ eingefügt wird, können Sie die Zeitstempelaktualisierung mit der letzten Pufferänderung gruppieren, die technisch nicht Ihrer Anforderung entspricht, das Problem in Ihrem Szenario jedoch praktisch lösen sollte.

(defun time-stamp-group-undo ()
  (if (eq nil (car buffer-undo-list))
      (setq buffer-undo-list (cdr buffer-undo-list)))
  (time-stamp))

(Warnung: ungetestet, die Rückgängig-Liste erfordert möglicherweise mehr Massage.)

Sie können auch auf andere Weise mit der Rückgängig-Liste spielen, indem Sie den Positionseintrag (eine Ganzzahl) für die Zeitstempelaktualisierung ändern.

¹ entfernt ähnlich wie Gruppeninsertionen. self-insert-command

Gilles 'SO - hör auf böse zu sein'
quelle
2

Das Problem mit dem, was Sie vorschlagen, ist, dass der Rückgängig-Baum eine Liste von Deltas ist, um von Ihrem Standort zu Ihrem gewünschten Standort zu gelangen. Obwohl es durchaus möglich ist, das Rückgängigmachen der Nachverfolgung für einen Puffer zu deaktivieren, bin ich mir nicht sicher, wie sich eine nicht aktive Aufzeichnung von Änderungen auswirken würde. Ich habe derzeit einen Schalter zum Ein- und Ausschalten eines bestimmten Puffers, da es nicht sinnvoll ist, Informationen in einem wachsenden Protokoll oder einer aktualisierten Seite rückgängig zu machen. Die Änderungen beim Umschalten werden jedoch nicht berücksichtigt:

(defun my-toggle-buffer-undo ()
  "Toggle undo tracking in current buffer."
  (interactive)
  (with-current-buffer (current-buffer)
    (if (eq buffer-undo-list t)
        (setq buffer-undo-list nil)
      (buffer-disable-undo (current-buffer)))))

(define-key my-toggle-map "u" 'my-toggle-buffer-undo)

buffer-disable-rückgängig macht die Puffer-Rückgängig-Liste eigentlich nur auf Null . Wenn Sie den Status der Puffer-Rückgängig-Liste auf Ihrem Umschalter gespeichert haben, können Sie ihn möglicherweise später wiederherstellen?

stsquad
quelle