Answers:
问题在于fill-paragraph
(或更确切地说,fill-region-as-paragraph
)会在细分您的段落时删除并重新插入换行符。如果只有一行,它将不会修改缓冲区。您看到的撤消列表中的禁止操作只是fill-paragraph
删除并重新插入换行符。
避免这种情况并非易事。以下是一个非常糟糕的技巧,对于大型缓冲区而言效率很低,但也许对您有用。该命令模仿fill-paragraph
(M-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
。
fill-paragraph
会在各种情况之间进行一些区分,即,根据活动区域,现有填充段函数等的不同而表现不同。您必须复制该行为,以找出实际上要更改缓冲区的哪些部分。可能,但棘手。:-)
较晚的答案,但这是一个简单的版本,如果文本不变,该版本不会修改缓冲区。
(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的有关引擎盖下并发症的评论)。
这是唯一与我的目的相关的用例(即与“正常”散文互动使用,没有活动区域),所以我要发布它,以防有人想使用它或针对更复杂的用例进行改进。
M-q
至少在我的测试中,没有标记默认情况下更改的缓冲区。您使用什么模式?我猜该模式会fill-paragraph
以某种方式覆盖。