28.5 缓冲区修改

Emacs 会为每个缓冲区维护一个名为 修改标记(modified flag)的标记, 用于记录你是否修改过该缓冲区的文本内容。每当你更改缓冲区内容时,该标记会被设为 t, 而在你保存缓冲区时,该标记会被清空为 nil。因此,这个标记能反映出缓冲区是否存在未保存的修改。 标记的值通常会显示在模式行中(see 模式行中使用的变量),并对保存操作(see 保存缓冲区)和自动保存操作(see 自动保存)起控制作用。

部分 Lisp 程序会显式设置该标记。例如,函数 set-visited-file-name 会将该标记设为 t, 这是因为即便缓冲区文本与先前访问的文件内容一致,它也不再匹配新访问的文件。

修改缓冲区内容的相关函数详见 文本

Function: buffer-modified-p &optional buffer

buffer 自上次从文件中读取或保存后发生过修改,该函数返回非 nil 值; 否则返回 nil。如果 buffer 在上次修改后执行过自动保存, 该函数会返回符号 autosaved。若 buffernil 或被省略, 则默认使用当前缓冲区。

Function: set-buffer-modified-p flag

flag 为非 nil,该函数会将当前缓冲区标记为已修改; 若 flagnil,则标记为未修改。

调用该函数的另一个效果是强制重新显示当前缓冲区的模式行。实际上, 函数 force-mode-line-update 正是通过以下方式实现该功能:

(set-buffer-modified-p (buffer-modified-p))
Function: restore-buffer-modified-p flag

该函数与 set-buffer-modified-p 功能类似,但不会强制重新显示模式行。 此外,该函数允许 flag 的值为符号 autosaved, 此值会将缓冲区标记为已修改,且标记为在上次修改后执行过自动保存。

Command: not-modified &optional arg

该命令会将当前缓冲区标记为未修改状态,即无需保存。 若 arg 为非 nil,则会将缓冲区标记为已修改, 使其在下次合适的时机被保存。以交互方式调用时,arg 为前缀参数。

请勿在程序中使用该函数,因为它会在回显区打印提示信息; 应改用上述的 set-buffer-modified-p 函数。

Function: buffer-modified-tick &optional buffer

该函数返回 buffer 的修改计数器值(modification-count)。 这是一个每次缓冲区被修改时都会递增的计数器。 若 buffernil(或被省略),则使用当前缓冲区。

Function: buffer-chars-modified-tick &optional buffer

该函数返回 buffer 的字符变更修改计数器值(character-change modification-count)。 仅修改文本属性不会改变该计数器的值;但每当有文本被插入或从缓冲区中删除时, 该计数器会被重置为 buffer-modified-tick 函数的返回值。 通过对比两次调用 buffer-chars-modified-tick 得到的值, 你可以判断两次调用之间该缓冲区是否发生过字符变更。 若 buffernil(或被省略),则使用当前缓冲区。

有时需要以「未实际改变文本内容」的方式修改缓冲区,例如仅修改文本属性时。 如果你的程序需要修改缓冲区,但又不想触发任何响应缓冲区修改的钩子函数和功能, 可以使用 with-silent-modifications 宏。

Macro: with-silent-modifications body…

执行 body 中的代码,且假装这些代码未修改缓冲区。 这包括跳过文件锁定检查(see 文件锁)、 跳过缓冲区修改钩子函数的执行(see 变更钩子)等操作。 注意:若 body 中实际修改了缓冲区文本(而非仅修改文本属性), 可能会导致撤销数据损坏。