以下是设置在 Emacs 空闲一定时长后运行的计时器的方法。除创建方式外,空闲计时器的工作方式与普通计时器完全一致。
创建一个计时器,使其在 Emacs 下次连续空闲 secs 秒时运行。secs 可以是数值,也可以是 current-idle-time 返回的类型值。
若 repeat 为 nil,该计时器仅在 Emacs 首次满足空闲时长时执行一次。更常见的情况是 repeat 为非 nil,表示 每次 Emacs 空闲达到 secs 秒时均触发该计时器。
函数 run-with-idle-timer 返回一个计时器对象,可用于调用 cancel-timer(see 用于延迟执行的定时器)。
Emacs 在开始等待用户输入时进入 空闲(idle) 状态(通过超时等待输入的情况除外,see 读取单个事件),并持续至用户输入新内容。若计时器设为 5 秒空闲触发,则会在 Emacs 首次进入空闲约 5 秒后执行。即使 repeat 为非 nil,只要 Emacs 持续空闲,该计时器也不会重复触发,因为空闲时长会持续增加,不会回落至 5 秒。
Emacs 在空闲时可执行多种操作:垃圾回收、自动保存或处理子进程数据。但这些空闲期间的操作不会干扰空闲计时器,因为它们不会将空闲计时重置为零。一个设为 600 秒的空闲计时器,会在用户最后一次命令结束 10 分钟后触发,即便这 10 分钟内处理了数千次子进程输出、执行过垃圾回收与自动保存。
用户输入内容时,Emacs 在处理输入期间退出空闲状态;处理完成后再次进入空闲,所有设置为重复触发的空闲计时器会依次再次执行。
请勿编写包含循环的空闲计时器函数:在循环中逐次执行处理,并在 (input-pending-p) 非 nil 时退出。这种写法看似自然,却存在两个问题:
同样,请勿在空闲计时器函数中创建另一个空闲计时器(包括自身),且其 secs 参数小于或等于当前已空闲的时间。此类计时器会近乎立即触发并持续反复执行,而非等待 Emacs 下次进入空闲。正确做法是在当前空闲时长基础上增加适当间隔后重新调度,如下例所示。
若 Emacs 处于空闲状态,该函数返回已空闲的时长,格式与 current-time(see 时刻)相同。
若 Emacs 未空闲,current-idle-time 返回 nil。可借此便捷判断 Emacs 是否空闲。
current-idle-time 的主要用途是让空闲计时器函数“暂停”一段时间。它可以创建另一个空闲计时器,在额外空闲数秒后再次调用自身。示例如下:
(defvar my-resume-timer nil "`my-timer-function' 用于重新调度自身的计时器,或为 nil。") (defun my-timer-function () ;; 若用户在my-resume-timer激活时输入命令, ;; 下次主空闲计时器调用此函数时,取消my-resume-timer。 (when my-resume-timer (cancel-timer my-resume-timer)) ...do the work for a while... (when taking-a-break (setq my-resume-timer (run-with-idle-timer ;; 计算比当前空闲时长多出 break-length 的时间 (time-add (current-idle-time) break-length) nil 'my-timer-function))))