Emacs——创建/删除“buffer-local”重复空闲定时器

8

我有一个使用重复空闲计时器的小模式:

(timer-activate-when-idle
    (run-with-idle-timer 0.2 t 'function-name))

我正在尝试找出处理一个以上缓冲区中同时激活同一 minor-mode 的最佳方法,并了解如何在不影响其他缓冲区的情况下,在杀死缓冲区或停用 minor-mode 时取消定时器。
如果可能的话,我的首选方法是创建一个“buffer-local”空闲定时器并为其分配唯一的名称/标识以进行取消。如果这种方法可行,则非常感谢提供示例。
我最不喜欢的处理方法是循环所有打开的缓冲区,以确定其中是否有任何一个激活了特定的 minor-mode,如果没有,则取消计时器。换句话说,将有一个为所有缓冲区提供服务的计时器。
非常感谢您提供任何处理此情况的想法。
[注意:我意识到我可以设置一个条件,防止定时器执行任何操作(例如,如果未激活 minor-mode xyz),但当不再需要特定的定时器时,我喜欢清理干净。]
1个回答

13
好的,您可以基本上按照您所描述的做。
(defvar-local my-local-timer nil "Buffer-local timer.")

(defun do-something-with (buf)
  "Callback function for `my-local-timer'."
  (when (buffer-live-p buf)
    (with-current-buffer buf
      ...)))

(setq my-local-timer
      (run-with-idle-timer 0.2 t 'do-something-with (current-buffer)))

(add-hook 'kill-buffer-hook
          (lambda () 
            (when (timerp my-local-timer) 
              (cancel-timer my-local-timer))))

计时器对象被添加到timer-idle-list中,变量的作用是让您在需要修改/取消时可以通过名称访问它。因此,变量是缓冲区本地的没有问题(除非您在不取消计时器的情况下杀死缓冲区)。
是否实际上想要每个缓冲区运行一个单独的计时器是另一回事,但如果您想要(或需要),您肯定可以这样做,并且可能有更少的清理工作。
如果您选择单个计时器路线,但您不想循环遍历所有缓冲区,您可以简单地维护感兴趣的缓冲区列表(启用模式可以添加当前缓冲区;禁用模式可以删除它),然后您可以迭代这些缓冲区。由于列表可能会留下过期条目,因此您的计时器函数将检查每个缓冲区是否有效,并且模式变量仍然设置,并删除无效条目。如果列表为空,您可以取消计时器。

非常感谢您提供的示例和解释,非常感激!!! :) - lawlist
如果您在kill-buffer-hook中从列表中删除死缓冲区,为什么还需要buffer-live-p?您说有方法,但我很好奇它们是什么。 - Joseph Garvin
我认为这个评论特别是针对在启用/禁用次要模式时添加/删除列表项的想法,而不是使用kill-buffer-hook。同时使用该挂钩可能已经足够了。(话虽如此,对某些任意定时器驱动回调的缓冲区参数进行验证似乎对我来说并不是一个坏主意;但是我一时半会儿想不起来是否知道一个失败案例。) - phils

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接