填充段标记文件已更改,即使它没有执行任何操作


11

每当我调用时fill-paragraph,即使该命令无效(即该段落已被填充),该缓冲区也始终被标记为已修改。它还会创建一个空的可撤消操作(很容易通过检测到undo-tree-mode)。其他有可能进行更改的命令(例如缩进命令)不会将缓冲区标记为已修改,也不会在未进行任何更改的情况下创建可撤消的操作。有什么方法可以使fill-paragraph标记标记为已修改的缓冲区,并仅在实际上更改了某些内容时创建可撤消的操作?


我认为这不正确- M-q至少在我的测试中,没有标记默认情况下更改的缓冲区。您使用什么模式?我猜该模式会fill-paragraph以某种方式覆盖。
shosti

@shosti我正在使用基本模式。该段必须超过一行(如果正确填充)。
莉莉·钟

好的,我现在看到了。
shosti

Answers:



10

问题在于fill-paragraph(或更确切地说,fill-region-as-paragraph)会在细分您的段落时删除并重新插入换行符。如果只有一行,它将不会修改缓冲区。您看到的撤消列表中的禁止操作只是fill-paragraph删除并重新插入换行符。

避免这种情况并非易事。以下是一个非常糟糕的技巧,对于大型缓冲区而言效率很低,但也许对您有用。该命令模仿fill-paragraphM-q)的行为相同,除了在调用之前先存储缓冲区的内容外,此后,如果内容保持不变,它将恢复更改前的修改状态和撤消列表。为此,它需要一个缓冲区内容的副本(实际上是两个),因此,实际上效率很低。:-)

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

您可以将其绑定到M-q


1
是的,这一直很痛苦。;-)我想知道(我不记得了)以前是否曾要求对此进行修复。好像会那样。
Drew

嗯 我想知道是否有更好的解决方案,不必检查整个缓冲区-也许它可以以某种方式仅检查选定的段落?
莉莉·钟

fill-paragraph会在各种情况之间进行一些区分,即,根据活动区域,现有填充段函数等的不同而表现不同。您必须复制该行为,以找出实际上要更改缓冲区的哪些部分。可能,但棘手。:-)
JorgenSchäfer2014年

@Drew去年在邮件列表上对此进行了长时间的讨论:bug#13949:24.3.50; 'fill-paragraph'不应该总是将缓冲区修改为
dkim 2014年

@dkim:是的,我现在记得。一无所获...
Drew

1

较晚的答案,但这是一个简单的版本,如果文本不变,该版本不会修改缓冲区。

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

它改编了@JorgenSchäfer的答案中的一些想法,但仅适用于当前段落,并且仅以简单的,空格分隔的方式起作用(请参阅有关@JorgenSchäfer的有关引擎盖下并发症的评论)。

这是唯一与我的目的相关的用例(即与“正常”散文互动使用,没有活动区域),所以我要发布它,以防有人想使用它或针对更复杂的用例进行改进。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.