o parágrafo de preenchimento marca o arquivo como alterado, mesmo que não tenha feito nada

11

Sempre que eu ligo fill-paragraph, o buffer é sempre marcado como modificado, mesmo que o comando não tenha efeito (ou seja, se o parágrafo já estiver preenchido). Ele também cria uma ação anulável vazia (facilmente detectada com undo-tree-mode). Outros comandos com potencial para fazer alterações, como os comandos de indentação, não marcam o buffer como modificado ou criam uma ação que não pode ser desfazida se nada foi alterado. Existe alguma maneira de fill-paragraphmarcar o buffer modificado e criar uma ação que não pode ser desfazida apenas se ele realmente mudou alguma coisa?

Lily Chung
fonte
Eu não acho que isso esteja correto - M-qnão marca o buffer alterado por padrão, pelo menos nos meus testes. Que modo você está usando? Eu acho que o modo está sobrescrevendo fill-paragraphde alguma forma.
shosti 24/09/14
@shosti Estou usando o modo Fundamental. O parágrafo deve ter mais de uma linha (quando devidamente preenchido).
Lily Chung
Ah, ok, eu vejo agora.
shosti

Respostas:

2

Observe que isso foi corrigido para o Emacsen mais recente (v.26 para cima).

clemera
fonte
10

O problema é que fill-paragraph(ou melhor, fill-region-as-paragraph) removerá e reinserirá novas linhas enquanto divide seu parágrafo. Não modificará o buffer se houver apenas uma linha. O no-op na lista de desfazer que você testemunha está apenas fill-paragraphremovendo e reinserindo novas linhas.

Não é trivial evitar isso. A seguir, é um hack muito ruim e altamente ineficiente para buffers grandes, mas talvez funcione para você. O comando imita fill-paragraph( M-q) com o mesmo comportamento, exceto que ele armazena o conteúdo do buffer antes de chamá-lo e, posteriormente, se o conteúdo permanecer o mesmo, ele restaurará o estado de modificação e desfará a lista antes da alteração. Para fazer isso, ele precisa de uma cópia (duas, na verdade) do conteúdo do buffer; portanto, isso é realmente ineficiente. :-)

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

Você pode vincular isso M-q.

Jorgen Schäfer
fonte
1
Sim, isso tem sido uma dor. ;-) Gostaria de saber (não me lembro) se uma correção para isso já foi solicitada antes. Parece que teria sido.
Drew
Hummm. Gostaria de saber se existe uma solução melhor que não precise verificar o buffer inteiro - talvez ele possa verificar apenas o parágrafo selecionado de alguma forma?
Lily Chung
fill-paragraphfaz alguma distinção entre vários casos, ou seja, se comporta de maneira diferente dependendo de uma região ativa, das funções de preenchimento de parágrafos existentes etc. Você teria que replicar esse comportamento para descobrir quais partes do buffer serão realmente alteradas. Possível, mas complicado. :-)
Jorgen Schäfer
@Drew Houve uma longa discussão sobre isso na lista de discussão no ano passado: bug # 13949: 24.3.50; 'fill-paragraph' nem sempre deve colocar o buffer como modificado
dkim
@ dkim: Sim, eu lembro agora. E nada aconteceu ...
Drew
1

Resposta tardia, mas aqui está uma versão simples que não modifica o buffer se o texto não for alterado.

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

Ele adapta algumas das idéias da resposta de @ JorgenSchäfer, mas funciona apenas com o parágrafo atual e apenas de maneira simples, separada por espaços em branco (consulte os comentários na resposta de @ JorgenSchäfer sobre complicações ocultas).

Esse é o único caso de uso relevante para meus próprios propósitos (ou seja, uso interativo com prosa "normal", sem região ativa), por isso estou publicando-o caso alguém queira usá-lo ou melhorá-lo para casos de uso mais complicados .

Dan
fonte