Fill-Paragraph markiert die Datei als geändert, auch wenn sie nichts getan hat

11

Wenn ich aufrufe fill-paragraph, wird der Puffer immer als geändert markiert, auch wenn der Befehl keine Auswirkung hatte (dh wenn der Absatz bereits gefüllt war). Es wird auch eine leere rückgängig zu machende Aktion erstellt (leicht zu erkennen mit undo-tree-mode). Andere Befehle, die möglicherweise Änderungen vornehmen können, wie z. B. die Einrückungsbefehle, markieren den Puffer nicht als geändert oder erstellen eine rückgängig zu machende Aktion, wenn nichts geändert wurde. Gibt es eine Möglichkeit, fill-paragraphden Puffer als markiert zu markieren und nur dann eine rückgängig zu machende Aktion zu erstellen, wenn tatsächlich etwas geändert wurde?

Lily Chung
quelle
Ich denke nicht, dass dies korrekt M-qist - markiert den Puffer nicht standardmäßig geändert, zumindest nicht aus meinen Tests. Welchen Modus verwenden Sie? Ich würde vermuten, dass der Modus fill-paragraphin irgendeiner Weise überschreibt .
Shosti
@shosti Ich benutze den Grundmodus. Der Absatz muss mehr als eine Zeile lang sein (wenn er richtig ausgefüllt ist).
Lily Chung
Ah OK, ich sehe es jetzt.
Shosti

Antworten:

2

Beachten Sie, dass dies für neuere Emacsen (ab Version 26) behoben ist.

Clemera
quelle
10

Das Problem ist, dass fill-paragraph(oder besser gesagt fill-region-as-paragraph) Zeilenumbrüche entfernt und wieder eingefügt werden, während Ihr Absatz aufgeschlüsselt wird. Der Puffer wird nicht geändert, wenn nur eine Zeile vorhanden ist. Das No-Op in der Rückgängig-Liste, die Sie sehen, ist nur das fill-paragraphEntfernen und erneutes Einfügen von Zeilenumbrüchen.

Es ist nicht trivial, dies zu vermeiden. Das Folgende ist ein ziemlich schlechter Hack und für große Puffer sehr ineffizient, aber vielleicht funktioniert es für Sie. Der Befehl ahmt fill-paragraph( M-q) mit dem gleichen Verhalten nach, außer dass er den Inhalt des Puffers vor dem Aufrufen speichert. Wenn der Inhalt gleich bleibt, stellt er anschließend den Änderungsstatus wieder her und macht die Liste vor der Änderung rückgängig. Dazu benötigt es eine Kopie (eigentlich zwei) des Pufferinhalts, was wirklich ineffizient ist. :-)

(defun my/fill-paragraph (&optional justify region)
  (interactive (progn
                 (barf-if-buffer-read-only)
                 (list (if current-prefix-arg 'full) t)))
  (let ((old-text (buffer-string))
        (old-modified (buffer-modified-p))
        (old-undo-list buffer-undo-list))
    (fill-paragraph justify region)
    (when (equal old-text (buffer-string))
      (setq buffer-undo-list old-undo-list)
      (set-buffer-modified-p old-modified))))

Sie können das binden an M-q.

Jorgen Schäfer
quelle
1
Ja, das war lange ein Schmerz. ;-) Ich frage mich (ich erinnere mich nicht), ob ein Fix dafür schon einmal angefordert wurde. Scheint so gewesen zu sein.
Drew
Hmmm. Ich frage mich, ob es eine bessere Lösung gibt, die nicht den gesamten Puffer überprüfen muss - vielleicht könnte sie irgendwie nur den ausgewählten Absatz überprüfen?
Lily Chung
fill-paragraphunterscheidet zwischen verschiedenen Fällen, dh es verhält sich je nach aktivem Bereich, vorhandenen Funktionen zum Ausfüllen von Absätzen usw. unterschiedlich. Sie müssten dieses Verhalten replizieren, um herauszufinden, welche Teile des Puffers tatsächlich geändert werden. Möglich, aber schwierig. :-)
Jorgen Schäfer
@Drew Im letzten Jahr gab es eine lange Diskussion darüber auf der Mailingliste: Fehler # 13949: 24.3.50; 'Fill-Paragraph' sollte den Puffer nicht immer als modifiziert setzen
dkim
@dkim: Ja, ich erinnere mich jetzt. Und nichts wurde jemals daraus ...
Drew
1

Späte Antwort, aber hier ist eine einfache Version, die den Puffer nicht ändert, wenn sich der Text nicht ändert.

(defun my-fill-paragraph (&optional justify region)
  "Fill paragraph, but don't modify the buffer if filling doesn't
change the text.  See `fill-paragraph' for details."
  (interactive (progn
                 (barf-if-buffer-read-only)
                 (list (if current-prefix-arg 'full) t)))
  (if (buffer-modified-p)
      ;; if modified: use standard fill-paragraph
      (fill-paragraph justify region)
    ;; if unmodified: get a candidate filled version
    (save-excursion
      (let* ((col fill-column)
             (beg (progn (forward-paragraph -1)
                         (skip-syntax-forward " >")
                         (point)))
             (end (progn (forward-paragraph 1)
                         (skip-syntax-backward " >")
                         (point)))
             (old (buffer-substring-no-properties beg end))
             (new (with-temp-buffer
                    (setq fill-column col)
                    (insert old)
                    (fill-paragraph justify region)
                    (buffer-string))))
        ;; don't modify unless the old and new versions differ
        (unless (string-equal old new)
          (delete-region beg end)
          (insert new))))))

Es passt einige der Ideen in der Antwort von @ JorgenSchäfer an, funktioniert jedoch nur mit dem aktuellen Absatz und nur auf einfache, durch Leerzeichen getrennte Weise (siehe Kommentare zu @ JorgenSchäfers Antwort zu Komplikationen unter der Haube).

Dies ist ungefähr der einzige Anwendungsfall, der für meine eigenen Zwecke relevant ist (dh interaktive Verwendung mit "normaler" Prosa, keine aktive Region). Ich poste ihn daher, falls jemand ihn verwenden oder für kompliziertere Anwendungsfälle verbessern möchte .

Dan
quelle