如果你对某个文件进行了大量修改,随后又改变主意不想要这些改动,可以使用 revert-buffer 命令重新读取该文件的先前版本,从而放弃所有修改。See Reverting a Buffer in The GNU Emacs Manual。
该命令使用磁盘上已访问文件的内容替换当前缓冲区文本。此操作会撤销自文件被访问或保存以来的所有改动。
默认情况下,如果最新的自动保存文件比已访问文件更新,且参数 ignore-auto 为 nil,
revert-buffer 会询问用户是否改用该自动保存文件。当你以交互方式调用此命令时,若没有数值型前缀参数,ignore-auto 为 t;因此,交互模式下默认不检查自动保存文件。
通常,revert-buffer 在修改缓冲区前会请求确认;但如果参数 noconfirm 为非 nil 值,
revert-buffer 则不会请求确认。
该命令通常会通过 normal-mode 重新初始化缓冲区的主模式和次模式。但如果 preserve-modes
为非 nil 值,各类模式则保持不变。
恢复操作会借助 insert-file-contents 的替换功能,尝试保留缓冲区中的标记位置。如果执行恢复前缓冲区内容与文件内容完全一致,恢复操作会保留所有标记。如果二者不一致,恢复操作会修改缓冲区;这种情况下,它会保留缓冲区开头与结尾未改动文本(若有)中的标记。保留更多额外标记可能会引发问题。
从非文件来源恢复缓冲区时,标记通常不会被保留,具体行为取决于对应 revert-buffer-function 的实现。
revert-buffer 在执行过程中会将此变量绑定为非 nil 值。
你可以通过设置本节后续介绍的变量,自定义 revert-buffer 的工作方式。
该变量保存一份无需询问即可直接恢复的文件列表,其值为一组正则表达式。如果被访问的文件名匹配其中任一正则表达式,且文件在磁盘上已变更但缓冲区未被修改,revert-buffer 会直接恢复文件而不向用户请求确认。
部分主模式会通过为这些变量设置缓冲区局部绑定,来自定义 revert-buffer:
该变量的值为用于恢复当前缓冲区的函数。它应当是一个接受两个可选参数、执行恢复工作的函数。这两个可选参数 ignore-auto 与 noconfirm,即 revert-buffer 接收到的参数。
像目录编辑模式(Dired模式)这类场景中,编辑的文本并非文件内容,而是可以通过其他方式重新生成,这类模式可以为该变量设置缓冲区局部值,指定一个专用函数来重新生成内容。
该变量的值指定了恢复缓冲区时用于插入更新后内容的函数。该函数接收两个参数:第一个是要使用的文件名;第二个是当用户要求读取自动保存文件时为 t。
某个模式选择修改此变量而非 revert-buffer-function,原因是避免重复或替换 revert-buffer 的其余逻辑:包括请求确认、清空撤销列表、确定合适的主模式,以及运行下文列出的钩子。
该常规钩子由默认的 revert-buffer-function 在插入修改后内容之前运行。自定义的 revert-buffer-function 可能运行也可能不运行此钩子。
该常规钩子由默认的 revert-buffer-function 在插入修改后内容之后运行。自定义的 revert-buffer-function 可能运行也可能不运行此钩子。
该变量的值指定一组用于保存缓冲区状态的函数。在执行恢复操作前,列表中的每个函数会被无参调用,且应返回一个用于保存特定状态(例如只读状态)的匿名函数。恢复操作完成后,每个匿名函数会按列表顺序依次调用,将保存的状态恢复到已恢复的缓冲区中。
Emacs 可以自动恢复缓冲区。对于访问文件的缓冲区,该功能默认启用。下文说明如何为新型缓冲区添加自动恢复支持。
首先,这类缓冲区必须定义合适的 revert-buffer-function 与 buffer-stale-function。
该变量的值指定一个用于检查缓冲区是否需要恢复的函数。默认值仅处理访问文件的缓冲区,通过检查文件修改时间实现。不访问文件的缓冲区需要自定义函数,该函数接受一个可选参数 noconfirm。若缓冲区应当被恢复,函数应返回非 nil 值。调用该函数时,当前缓冲区为活跃缓冲区。
该函数主要用于自动恢复,但也可用于其他用途。例如,若未启用自动恢复,它可用于提醒用户缓冲区需要恢复。noconfirm 参数的设计含义是:若缓冲区将直接恢复而不询问用户,则为 t;若函数仅用于提醒用户缓冲区已过期,则为 nil。特别地,在自动恢复场景中,noconfirm 为 t。如果该函数仅用于自动恢复,你可以忽略 noconfirm 参数。
如果你希望每隔 auto-revert-interval 秒就自动执行一次恢复(如同缓冲区菜单),在缓冲区的模式函数中使用如下代码:
(setq-local buffer-stale-function
(lambda (&optional noconfirm) 'fast))
特殊返回值 ‘fast’ 告知调用方:未检查是否需要恢复,但恢复该缓冲区的操作开销很小。它同时告知自动恢复模块不要打印任何恢复信息,即便 auto-revert-verbose 为非 nil。这一点很重要,因为每隔 auto-revert-interval 秒就收到恢复提示会十分扰民。如果该函数被用于自动恢复之外的用途,此返回值提供的信息也可能有用。
当缓冲区具备了合适的 revert-buffer-function 与 buffer-stale-function 后,通常还需要解决若干问题。
缓冲区仅在标记为未修改时才会自动恢复。因此,你必须确保相关函数仅在以下情况将缓冲区标记为已修改:缓冲区包含可能因恢复而丢失的信息,或有理由认为用户正在编辑缓冲区,自动恢复会对其造成干扰。用户始终可以手动调整缓冲区的修改状态来覆盖这一行为。为支持该逻辑,对标记为未修改的缓冲区调用 revert-buffer-function 后,应保持缓冲区标记为未修改。
必须确保光标不会因自动恢复而频繁跳动。当然,如果缓冲区内容发生大幅变化,光标移动可能无法避免。
你应当确保 revert-buffer-function 不会打印与自动恢复模块自身重复的冗余信息(自动恢复的信息在 auto-revert-verbose 为 t 时显示),也不应实际覆盖 auto-revert-verbose 为 nil 的效果。因此,适配模式以支持自动恢复通常需要移除这类消息。对于每隔 auto-revert-interval 秒自动恢复一次的缓冲区,这一点尤为重要。
如果新增的自动恢复功能被集成到 Emacs 中,你应当在 global-auto-revert-non-file-buffers 的文档字符串中加以说明。
同样,你也应当在 Emacs 手册中记录这些新增内容。