谁在Emacs中为我的文件设置修改标志?

谁在Emacs中为我的文件设置修改标志?,emacs,elisp,Emacs,Elisp,在过去几年中,我一直在缓慢地增加我的Emacs配置,添加位和块,添加新模式等。大约一年前,一个问题开始定期出现:一些代码正在设置我的缓冲区上修改的位。它实际上没有改变任何东西,只是设置了这个标志。这有点烦人,因为每次运行compile或保存一些缓冲区时,我都必须手动放弃这些缓冲区中的更改以重置修改的位。我怎样才能找到有问题的代码 如果确实有什么东西在不更改任何内容的情况下显式地将缓冲区设置为modified,那么我猜它应该调用set-buffer-modified-p 我本来打算建议对set-b

在过去几年中,我一直在缓慢地增加我的Emacs配置,添加位和块,添加新模式等。大约一年前,一个问题开始定期出现:一些代码正在设置我的缓冲区上修改的位。它实际上没有改变任何东西,只是设置了这个标志。这有点烦人,因为每次运行
compile
保存一些缓冲区时,我都必须手动放弃这些缓冲区中的更改以重置修改的位。我怎样才能找到有问题的代码

如果确实有什么东西在不更改任何内容的情况下显式地将缓冲区设置为modified,那么我猜它应该调用
set-buffer-modified-p

我本来打算建议对
set-buffer-modified-p
进行
debug-on-entry
,但粗略的测试表明,这通常会造成极大的破坏性,因此有一种方法可以表明您对哪些缓冲区感兴趣:

(defvar my-debug-set-buffer-modified-p-buffers nil)
(defadvice set-buffer-modified-p
(在my-debug-set-buffer-modified-p-advice之前)
(当(memq(当前缓冲区)my-debug-set-buffer-modified-p-buffers)
(调试)
(ad激活“set-buffer-MODIFED-p”)
(定义my-debug-set-buffer-modified-p(缓冲区)
(交互式(列表(当前缓冲区)))
(如果(memq buffer my-debug-set-buffer-modified-p-buffers)
(progn(setq my-debug-set-buffer-modified-p-buffers
(delq buffer my-debug-set-buffer-modified-p-buffers))
(消息“已禁用%s”缓冲区)
(添加到列表“my-debug-set-buffer-modified-p-buffers”
(消息“已为%s启用”缓冲区)))

与phils相反,我希望您的modified-p标志不是由
set-buffer-modified-p
设置的,而是由缓冲区的实际更改设置的。这是可能的原因,因为Emacs将文本属性视为属于缓冲区的内容,因此更改它们将设置modified-p标志,即使在许多情况下结果是不可见的,并且即使结果是可见的,用户通常也不会将其视为修改(用户通常理解为类似于“保存缓冲区时影响文件”)

因此,大多数设置文本属性的代码都需要小心,以便在之后重置modified-p标志。最好的方法通常是将设置属性的代码包装在
中,并进行静默修改


追踪罪犯的一种方法是尝试撤消修改(例如使用
C-/
),但当然,如果修改不可见,撤消它也将不可见。因此,您可能需要查看
C-h v buffer undo list RET
,这是用于跟踪修改的内部数据。幸运的是,不仅设置了修改的-p,而且还设置了撤消列表,该列表将告诉您更改了什么。例如,该列表可能看起来像
(nil(nil face nil 12345708.12345713))
,这意味着更改是将
face
属性设置为位置12345708和12345713之间的新值,并且该属性的旧值是
nil
(这是上面的第三个
nil
)。有时用
M-:(goto char 12345708)RET查看受影响的位置就足以找出谁该受责备。有时查看
M-:(获取文本属性12345708'面)RET
,它为您提供了设置的新值,更有用。

我完全同意——如果我的答案真的显示了罪魁祸首,我会感到非常惊讶。不过,似乎值得将其作为一个可能的原因加以消除;我想不出一个明显的方法来调试替代方案:)@phils您可能会有很大的分歧与维护人员一起!:)