summaryrefslogtreecommitdiff
path: root/devdocs/elisp/idle-timers.html
blob: 8baaacd0968137d6b031b9deba71760c2a85d235 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
 <h3 class="section">Idle Timers</h3>  <p>Here is how to set up a timer that runs when Emacs is idle for a certain length of time. Aside from how to set them up, idle timers work just like ordinary timers. </p> <dl> <dt id="run-with-idle-timer">Command: <strong>run-with-idle-timer</strong> <em>secs repeat function &amp;rest args</em>
</dt> <dd>
<p>Set up a timer which runs the next time Emacs is idle for <var>secs</var> seconds. The value of <var>secs</var> may be a number or a value of the type returned by <code>current-idle-time</code>. </p> <p>If <var>repeat</var> is <code>nil</code>, the timer runs just once, the first time Emacs remains idle for a long enough time. More often <var>repeat</var> is non-<code>nil</code>, which means to run the timer <em>each time</em> Emacs remains idle for <var>secs</var> seconds. </p> <p>The function <code>run-with-idle-timer</code> returns a timer value which you can use in calling <code>cancel-timer</code> (see <a href="timers">Timers</a>). </p>
</dd>
</dl>  <p>Emacs becomes <em>idle</em> when it starts waiting for user input (unless it waits for input with a timeout, see <a href="reading-one-event">Reading One Event</a>), and it remains idle until the user provides some input. If a timer is set for five seconds of idleness, it runs approximately five seconds after Emacs first becomes idle. Even if <var>repeat</var> is non-<code>nil</code>, this timer will not run again as long as Emacs remains idle, because the duration of idleness will continue to increase and will not go down to five seconds again. </p> <p>Emacs can do various things while idle: garbage collect, autosave or handle data from a subprocess. But these interludes during idleness do not interfere with idle timers, because they do not reset the clock of idleness to zero. An idle timer set for 600 seconds will run when ten minutes have elapsed since the last user command was finished, even if subprocess output has been accepted thousands of times within those ten minutes, and even if there have been garbage collections and autosaves. </p> <p>When the user supplies input, Emacs becomes non-idle while executing the input. Then it becomes idle again, and all the idle timers that are set up to repeat will subsequently run another time, one by one. </p> <p>Do not write an idle timer function containing a loop which does a certain amount of processing each time around, and exits when <code>(input-pending-p)</code> is non-<code>nil</code>. This approach seems very natural but has two problems: </p> <ul> <li> It blocks out all process output (since Emacs accepts process output only while waiting). </li>
<li> It blocks out any idle timers that ought to run during that time. </li>
</ul> <p>Similarly, do not write an idle timer function that sets up another idle timer (including the same idle timer) with <var>secs</var> argument less than or equal to the current idleness time. Such a timer will run almost immediately, and continue running again and again, instead of waiting for the next time Emacs becomes idle. The correct approach is to reschedule with an appropriate increment of the current value of the idleness time, as described below. </p> <dl> <dt id="current-idle-time">Function: <strong>current-idle-time</strong>
</dt> <dd>
<p>If Emacs is idle, this function returns the length of time Emacs has been idle, using the same format as <code>current-time</code> (see <a href="time-of-day">Time of Day</a>). </p> <p>When Emacs is not idle, <code>current-idle-time</code> returns <code>nil</code>. This is a convenient way to test whether Emacs is idle. </p>
</dd>
</dl> <p>The main use of <code>current-idle-time</code> is when an idle timer function wants to “take a break” for a while. It can set up another idle timer to call the same function again, after a few seconds more idleness. Here’s an example: </p> <div class="example"> <pre class="example">(defvar my-resume-timer nil
  "Timer for `my-timer-function' to reschedule itself, or nil.")

(defun my-timer-function ()
  ;; <span class="roman">If the user types a command while <code>my-resume-timer</code></span>
  ;; <span class="roman">is active, the next time this function is called from</span>
  ;; <span class="roman">its main idle timer, deactivate <code>my-resume-timer</code>.</span>
  (when my-resume-timer
    (cancel-timer my-resume-timer))
  ...<var>do the work for a while</var>...
  (when <var>taking-a-break</var>
    (setq my-resume-timer
          (run-with-idle-timer
            ;; Compute an idle time <var>break-length</var>
            ;; more than the current value.
            (time-add (current-idle-time) <var>break-length</var>)
            nil
            'my-timer-function))))
</pre>
</div><div class="_attribution">
  <p class="_attribution-p">
    Copyright &copy; 1990-1996, 1998-2022 Free Software Foundation, Inc. <br>Licensed under the GNU GPL license.<br>
    <a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Idle-Timers.html" class="_attribution-link">https://www.gnu.org/software/emacs/manual/html_node/elisp/Idle-Timers.html</a>
  </p>
</div>