0

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

4

2 回答 2

4

与 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,它为您提供设置的新值,更有用。

于 2012-10-05T15:58:48.960 回答
3

如果确实有东西明确地将缓冲区设置为已修改而不更改任何内容,那么我猜它应该调用set-buffer-modified-p.

我原本打算建议debug-on-entryset-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)))
于 2012-10-05T11:53:52.650 回答