gpt4 book ai didi

emacs - elisp 代码破坏了缓冲区,而不是在其他地方保存......为什么?

转载 作者:行者123 更新时间:2023-12-04 04:38:43 24 4
gpt4 key购买 nike

在尝试设置一些保存一些持久状态的东西时,我遇到了一些困难,以便我可以在 emacs 调用之间使用数据。

使用来自 another question 的一些代码作为起点,我想出了以下我想做的事情的小代码片段:

(defmacro with-output-to-file (path &rest body)
"record output of commands in body to file"
`(save-excursion
(let* ((buf (find-file-noselect ,path))
(standard-output buf))
(set-buffer buf)
(erase-buffer)
,@body
(save-buffer)
(kill-buffer))))

然后我有一个使用它的函数,例如:
(defun my-save-some-data ()
(with-output-to-file my-data-save-file
(prin1 my-data)))

编辑 :它们都遵循如下代码(以前,它们都是 setq;感谢@phils 的评论激励我将它们切换到 devfardefcustom ):
; note: my actual variable names (and filename value) are different;
; changed for example sake:
(defvar my-data (make-hash-table :test 'equal) "Data for a thing")
(defcustom my-data-save-file "~/tmp/my-data.el" "File to save my data to")

(注意:我还有一个功能可以读回数据,这会在加载时自动发生,或者按需发生。)

我已经将它设置为在几种情况下运行(可能太多?可能是糟糕的选择?无论如何,这就是我设置的):
(add-hook 'auto-save-hook 'my-save-some-data)
(add-hook 'kill-emacs-hook 'my-save-some-data)
(add-hook 'post-gc-hook 'my-save-some-data)

大多数情况下,这工作正常。但是,每隔一段时间,我就会遇到一个问题,其中数据被写入我以前打开的缓冲区之一(杀死那里的所有先前内容!),然后该缓冲区被杀死,并保存更改。

我只想说,这是非常烦人的,因为发生这种情况的缓冲区经常是我一直在做一些工作的地方,而且还不一定检查它。

我尝试更改上面的宏,从 (set-buffer buf) 替换继续:
       (with-current-buffer buf ; because set-buffer wasn't working??
(erase-buffer)
,@body
(if (eq buf (current-buffer))
(progn
(save-buffer)
(kill-buffer))
(message "buffer changed?!"))))))

这以某种方式设法使其附加到缓冲区,而不是覆盖它......所以我的 if 语句似乎在某种程度上起作用......但是我没有在我的 *Messages* 中看到消息缓冲,所以......我不太确定发生了什么。

我想我已经注意到的一件事(虽然很难确定,因为发生这种情况时我可能没有积极关注)是这发生在一个当时不活跃的缓冲区中,而不是我正在使用的缓冲区中目前正在编辑。

所以,问题:
  • 我在这里做错了吗?
  • 有没有其他/更好的方法来做到这一点?
  • 是否有以编程方式保存状态的标准方法,我可以使用? (我恰如其分地四处看了看,但没有找到任何东西……虽然我可能只是不知道该找什么。)
  • 我能做些什么来帮助自己追踪这个问题? (有没有办法设置断点或其他什么?)
  • 我可以在这样的代码中使用其他保护吗?

  • 欢迎任何其他想法。我正在添加更多 (message)希望同时获得更多调试信息的表单。

    更新 :我发现这只会发生在 post-gc-hook 上。 .我不知道我的变量是否以某种方式被破坏了(也许切换到 defvardefcustom 会解决这个问题?),或者在 post-gc-hook 处理中是否存在某种模糊的错误......检查用于使用最新更改重现测试用例。

    最佳答案

    你确实可以设置断点,一个简单的方法是把 (edebug)在你想打破的地方。然后就可以使用,n接下来,SPC对于步骤,和 e来评估。您可以阅读有关 edebug here 的更多信息.

    因此,您可以在调用 (set-buffer) 之前将条件断点设置为保护/警告,就像这样:

    (when (get-file-buffer my-data-save-file) 
    (read-from-minibuffer
    (format "Warning: %s is already being visited by a buffer, contents will be overwritten! Entering edebug" my-data-save-file))
    (edebug))

    如果您在某个缓冲区中访问的文件即将被您的宏覆盖,这将警告您然后进入调试器,您可以在其中检查正在发生的事情。

    这是 find-file-no-select 的文档字符串的一部分:
    Read file FILENAME into a buffer and return the buffer.
    If a buffer exists visiting FILENAME, return that one, but
    verify that the file has not changed since visited or saved.

    我的猜测是 my-data-save-file已被缓冲区访问,因此这是返回(并随后被覆盖)的缓冲区。但是您可以真正了解 (edebug) 发生了什么。

    关于emacs - elisp 代码破坏了缓冲区,而不是在其他地方保存......为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19260509/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com