riempire il paragrafo contrassegna il file come modificato, anche se non ha fatto nulla


11

Ogni volta che chiamo fill-paragraph, il buffer è sempre contrassegnato come modificato, anche se il comando non ha avuto effetto (ovvero se il paragrafo è già stato riempito). Crea inoltre un'azione annullabile vuota (facilmente rilevabile con undo-tree-mode). Altri comandi che hanno il potenziale per apportare modifiche, come i comandi di rientro, non contrassegnano il buffer come modificato o creano un'azione annullabile se nulla è stato modificato. C'è un modo per fill-paragraphcontrassegnare il buffer modificato e creare un'azione annullabile solo se ha effettivamente cambiato qualcosa?


Non penso che sia corretto-- M-qnon contrassegna il buffer modificato per impostazione predefinita, almeno dai miei test. Quale modalità stai usando? Immagino che la modalità sia fill-paragraphin qualche modo sovrascritta .
— shosti,

@shosti Sto usando la modalità Fondamentale. Il paragrafo deve essere lungo più di una riga (se correttamente compilato).
— Lily Chung,

Ah OK, lo vedo ora.
— shosti,

Risposte:


2

Si noti che questo problema è stato risolto per il nuovo Emacsen (v.26 in poi).


10

Il problema è che fill-paragraph(o meglio fill-region-as-paragraph) rimuoverà e reinserirà le nuove righe mentre si rompe il paragrafo. Non modificherà il buffer se esiste solo una riga. La no-op nella lista degli annullamenti a cui sei testimone è semplicemente fill-paragraphrimuovere e reinserire le nuove righe.

Non è banale evitarlo. Quello che segue è un trucco piuttosto brutto e altamente inefficiente per buffer di grandi dimensioni, ma forse funziona per te. Il comando imita fill-paragraph( M-q) con lo stesso comportamento, tranne per il fatto che memorizza il contenuto del buffer prima di chiamarlo, e successivamente, se il contenuto è rimasto lo stesso, ripristinerà lo stato di modifica e annullerà l'elenco prima della modifica. Per fare questo, ha bisogno di una copia (due, in realtà) del contenuto del buffer, quindi davvero, questo è abbastanza inefficiente. :-)

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

Puoi legarlo a M-q.


1
Sì, questo è stato a lungo un dolore. ;-) Mi chiedo (non ricordo) se una soluzione per questo è stata richiesta in precedenza. Sembra che sarebbe stato.
— Drew

Hmmm. Mi chiedo se esiste una soluzione migliore che non deve controllare l'intero buffer, forse potrebbe in qualche modo controllare solo il paragrafo selezionato?
— Lily Chung,

fill-paragraphfa una certa distinzione tra vari casi, ovvero si comporta in modo diverso a seconda di una regione attiva, funzioni di paragrafo di riempimento esistenti, ecc. Dovresti replicare quel comportamento per capire quali parti del buffer verranno effettivamente modificate. Possibile, ma difficile. :-)
— Jorgen Schäfer,

@Drew C'è stata una lunga discussione al riguardo sulla mailing list dell'anno scorso: bug # 13949: 24.3.50; 'fill-paragraph' non dovrebbe sempre mettere il buffer come modificato
— dkim

@dkim: Sì, ora ricordo. E nulla mai è venuto di esso ...
— Drew

1

Risposta in ritardo, ma ecco una versione semplice che non modifica il buffer se il testo non cambia.

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

Adatta alcune delle idee nella risposta di @ JorgenSchäfer, ma funziona solo con il paragrafo corrente e solo in modo semplice e separato da spazi (vedi commenti sulla risposta di @ JorgenSchäfer sulle complicazioni sotto il cofano).

Si tratta dell'unico caso d'uso pertinente per i miei scopi (ovvero, l'uso interattivo con prosa "normale", nessuna regione attiva), quindi lo sto pubblicando nel caso in cui qualcuno voglia utilizzarlo o migliorarlo per casi d'uso più complicati .

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.