在过去的几年里,我一直在缓慢地增加我的 Emacs 配置,添加零碎,添加新模式等。大约一年前,一个问题开始定期出现:一些代码正在我的缓冲区上设置修改后的位。它实际上并没有改变任何东西,它只是设置了这个标志。这有点烦人,因为每次我运行compile
或save-some-buffers
我必须手动丢弃这些缓冲区中的更改以重置修改的位。我怎样才能找到有问题的代码?
2 回答
与 phils 不同,我希望您的 modified-p 标志不是由缓冲区设置set-buffer-modified-p
而是由缓冲区的实际更改设置的。这可能的原因是 Emacs 将 text-properties 视为属于缓冲区的内容,因此更改它们会设置 modified-p 标志,即使在许多情况下结果是不可见的,即使它是可见的通常不会被用户视为修改(用户通常将其理解为“当我保存缓冲区时影响文件”)。
因此,大多数设置 text-properties 的代码在之后需要小心重置 modified-p 标志。最好的方法通常是将设置属性的代码包装在with-silent-modification
.
尝试追查罪魁祸首的一种方法是尝试撤消修改(例如,使用C-/
),但当然,如果修改不可见,撤消也将不可见。因此,您可能想查看C-h v buffer-undo-list RET
哪些是用于跟踪修改的内部数据。幸运的是,不仅设置了 modified-p,还设置了 undo-list,该列表将告诉您更改了什么。例如,该列表可能看起来像(nil (nil face nil 12345708 . 12345713))
这意味着更改是将face
属性设置为位置 12345708 和 12345713 之间的新值,并且该属性的旧值是nil
(即上面的第三个nil
)。有时查看受影响的职位M-: (goto-char 12345708) RET
足以找出谁应该受到责备。其他时候看着M-: (get-text-property 12345708 'face) RET
,它为您提供设置的新值,更有用。
如果确实有东西明确地将缓冲区设置为已修改而不更改任何内容,那么我猜它应该调用set-buffer-modified-p
.
我原本打算建议debug-on-entry
,set-buffer-modified-p
但粗略的测试表明,这通常具有极大的破坏性,因此您可以通过以下方式指出您对哪些缓冲区感兴趣:
(defvar my-debug-set-buffer-modified-p-buffers nil)
(defadvice set-buffer-modified-p
(before my-debug-set-buffer-modified-p-advice)
(when (memq (current-buffer) my-debug-set-buffer-modified-p-buffers)
(debug)))
(ad-activate 'set-buffer-modified-p)
(defun my-debug-set-buffer-modified-p (buffer)
(interactive (list (current-buffer)))
(if (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))
(message "Disabled for %s" buffer))
(add-to-list 'my-debug-set-buffer-modified-p-buffers buffer)
(message "Enabled for %s" buffer)))