plik akapitu wypełnienia jako zmieniony, nawet jeśli nic nie zrobił

11

Ilekroć dzwonię fill-paragraph, bufor jest zawsze oznaczany jako zmodyfikowany, nawet jeśli polecenie nie miało żadnego efektu (tj. Jeśli akapit był już wypełniony). Tworzy również pustą, niemożliwą do cofnięcia akcję (łatwą do wykrycia za pomocą undo-tree-mode). Inne polecenia, które mogą potencjalnie wprowadzać zmiany, takie jak polecenia wcięcia, nie oznaczają bufora jako zmodyfikowanego ani nie powodują cofnięcia działania, jeśli nic nie zostało zmienione. Czy jest jakiś sposób na fill-paragraphzmodyfikowanie bufora i utworzenie niemożliwej do cofnięcia akcji, tylko jeśli coś zmieniło?

Lily Chung
źródło
Nie sądzę, żeby to było poprawne - M-qnie oznacza domyślnej zmiany bufora, przynajmniej z moich testów. Z jakiego trybu korzystasz? Domyślam się, że ten tryb jest fill-paragraphw jakiś sposób nadpisywany .
shosti
@shosti Używam trybu podstawowego. Akapit musi mieć więcej niż jedną linię (jeśli jest odpowiednio wypełniony).
Lily Chung
Ach OK, teraz to widzę.
shosti

Odpowiedzi:

2

Zauważ, że zostało to naprawione dla nowszych Emacsen (v.26 w górę).

Clemera
źródło
10

Problem polega na tym, że fill-paragraph(a raczej fill-region-as-paragraph) usunie i ponownie wstawi nowe wiersze, rozkładając akapit. Nie zmodyfikuje bufora, jeśli jest tylko jedna linia. No-op na liście cofnięć, której jesteś świadkiem, to po prostu fill-paragraphusuwanie i ponowne wstawianie nowych linii.

Unikanie tego nie jest trywialne. Poniżej znajduje się dość zły hack i bardzo nieefektywny dla dużych buforów, ale może to działa dla ciebie. Polecenie mimics fill-paragraph( M-q) o identycznym zachowaniu, z wyjątkiem tego, że przechowuje zawartość bufora przed jego wywołaniem, a następnie, jeśli zawartość pozostała taka sama, przywróci stan modyfikacji i cofnie listę sprzed zmiany. Aby to zrobić, potrzebuje kopii (właściwie dwóch) zawartości bufora, więc tak naprawdę jest to dość nieefektywne. :-)

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

Możesz to powiązać M-q.

Jorgen Schäfer
źródło
1
Tak, to był od dawna ból. ;-) Zastanawiam się (nie pamiętam), czy wcześniej zażądano naprawy tego problemu. Wygląda na to, że tak by było.
Drew
Hmmm. Zastanawiam się, czy istnieje lepsze rozwiązanie, które nie musi sprawdzać całego bufora - może mógłby jakoś sprawdzić tylko wybrany akapit?
Lily Chung
fill-paragraphrobi pewne rozróżnienie między różnymi przypadkami, tj. zachowuje się różnie w zależności od aktywnego regionu, istniejących funkcji wypełniania akapitów itp. Trzeba by było powtórzyć to zachowanie, aby dowiedzieć się, które części bufora mają zostać zmienione. Możliwe, ale trudne. :-)
Jorgen Schäfer
@Drew W zeszłym roku odbyła się długa dyskusja na ten temat na liście mailingowej: bug # 13949: 24.3.50; „fill-paragraph” nie zawsze powinien umieszczać bufor jako zmodyfikowany
dkim
@dkim: Tak, teraz pamiętam. I nic z tego nie wyszło ...
Drew
1

Późna odpowiedź, ale oto prosta wersja, która nie modyfikuje bufora, jeśli tekst się nie zmienia.

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

Dostosowuje niektóre pomysły zawarte w odpowiedzi @ JorgenSchäfer, ale działa tylko z bieżącym akapitem i tylko w prosty, oddzielony spacjami sposób (patrz komentarze do odpowiedzi @ JorgenSchäfer na temat komplikacji pod maską).

Chodzi o jedyny przypadek użycia, który jest odpowiedni dla moich własnych celów (tj. Interaktywne użycie z „normalną” prozą, brak aktywnego regionu), więc zamieszczam go na wypadek, gdyby ktoś chciał go użyć lub poprawić w bardziej skomplikowanych przypadkach użycia .

Dan
źródło