Next: , Previous: , Up: System Interface   [Contents][Index]


38.11 アイドルタイマー

以下はEmacsの特定の期間アイドル時に実行するタイマーをセットアップする方法です。それらをセットアップする方法とは別にすればアイドルタイマーは通常のタイマーと同様に機能します。

Command: run-with-idle-timer secs repeat function &rest args

Emacsの次回secs秒間アイドル時に実行するタイマーをセットアップする。secsの値には数値、またはcurrent-idle-timeがリターンするタイプの値を指定できる。

repeatnilなら、Emacsが充分長い間アイドルになった初回の1回だけタイマーは実行される。これは大抵はrepeatが非nilの場合であり、そのときはEmacsがsecs秒間アイドルになったときに毎回そのタイマーが実行される。

関数run-with-idle-timercancel-timer呼び出し時に使用できるタイマー値をリターンする。

ユーザー入力の待機時にEmacsはアイドル(idle)となり、ユーザーが何らかの入力を与えるまでアイドルのままとなります。あるタイマーを5秒間のアイドルにセットすると、Emacsが最初に約5秒間アイドルになったときにタイマーが実行されます。たとえrepeatが非nilでもEmacsがアイドルであり続けるかぎりタイマーが再実行されることはありません。アイドル期間は増加を続けて再び5秒に減少することはないからです。

アイドル時にEmacsはガーベージコレクションや自動保存やサブプロセスからのデータ処理など、さまざまなことを行うことができます。しかしこれらの幕間劇がアイドルのクロックを0にリセットすることはないのでアイドルタイマーと干渉することはありません。600秒にセットされたアイドルタイマーはたとえその10分間にサブプロセスの出力が何回到達しても、たとえガーベージコレクションや自動保存が行われてもユーザーコマンドが最後に終了してから10分経過後に実行されるでしょう。

ユーザーが入力を与えるとEmacsは入力の実行の間は非アイドルになります。それから再びアイドルとなると、繰り返すようにセットアップされたすべてのアイドルタイマーは1つずつ異なる時刻に実行されるでしょう。

実行ごとに特定の量を処理するループを含んだり、(input-pending-p)が非nilのときにexitするアイドルタイマー関数を記述しないでください。このアプローチはとても自然に見えますが2つの問題があります:

同様にsecs引数がカレントのアイドル期間以下となるような、別のアイドルタイマー(同じアイドルタイマーも含む)をセットアップするアイドルタイマー関数を記述しないでください。そのようなタイマーはほとんど即座に実行されて、Emacsが次回アイドルになるのを待機するかわりに再現なく継続して実行されるでしょう。以下で説明するようにカレントのアイドル期間を適切に増加させて再スケジュールするのが正しいアプローチです。

Function: current-idle-time

この関数はEmacsがアイドルならEmacsがアイドルとなった期間をcurrent-timeで使用するのと同じ4つの整数リストのフォーマット(sec-high sec-low microsec picosec)でリターンする(Time of Dayを参照)。

Emacsがアイドルでなければcurrent-idle-timenilをリターンする。これはEmacsがアイドルかどうかテストする手軽な方法である。

current-idle-timeの主な用途はアイドルタイマー関数を少し“休憩”したいときです。そのアイドルタイマー関数はさらに数秒アイドル後に、同じ関数を再呼び出しするために別のタイマーをセットアップできます。以下はその例です:

(defvar my-resume-timer nil
  "Timer for `my-timer-function' to reschedule itself, or 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)
                      (seconds-to-time break-length))
            nil
            'my-timer-function))))