Next: , Previous: , Up: エコーエリア   [Contents][Index]


40.4.2 処理の進捗レポート

処理の完了まで暫く時間を要するかもしれない際には、進行状況についてユーザーに通知するべきです。これによりユーザーが残り時間を予測するとともに、Emacsがhungしているのではなく処理中であることを明確に確認できます。プログレスリポーター(progress reporter: 進行状況リポーター)を使用するのが、これを行う便利な方法です。

以下は何も有用なことを行わない実行可能な例です:

(let ((progress-reporter
       (make-progress-reporter "Collecting mana for Emacs..."
                               0  500)))
  (dotimes (k 500)
    (sit-for 0.01)
    (progress-reporter-update progress-reporter k))
  (progress-reporter-done progress-reporter))
Function: make-progress-reporter message &optional min-value max-value current-value min-change min-time

この関数は以下に挙げる他の関数の引数として使用されることになるプログレスリポーターオブジェクトを作成してリターンする。これはプログレスリポーターを高速にするように、可能なかぎり多くのデータを事前に計算するというアイデアが元となっている。

この後にプログレスリポーターを使用する際には、進行状況のパーセンテージを後に付加してmessageが表示されるだろう。messageは単なる文字列として扱われる。たとえばファイル名に依存させる必要があるなら、この関数の呼び出し前にformat-messageを使えばよい。

引数min-valuemax-valueは処理の開始と終了を意味する数値であること。たとえばバッファーをスキャンする処理なら、これらをそれぞれpoint-minpoint-maxにセットするべきだろう。max-valuemin-valueより大であること。

かわりにmin-valuemax-valuenilにセットすることができる。この場合にはプログレスリポーターは進行状況のパーセンテージを報告しない。かわりにプログレスリポーターを更新するたびに刻み(notch)を回転する“スピナー(spinner)”を表示する。

min-valuemax-valueが数値なら、進行状況の初期の数値を与える引数current-valueを与えることができる。省略時のデフォルトはmin-value

残りの引数はエコーエリアの更新レートを制御する。プログレスリポーターは次のメッセージを表示する前に、その処理が少なくともmin-changeパーセントより多く完了するまで待機する。デフォルトは1パーセント。min-timeは連続するプリントの間に空ける最小時間をミリ秒単位で指定する(いくつかのオペレーティングシステムではプログレスリポーターは秒の小数部をさまざまな精度で処理するかもしれない)。

この関数はprogress-reporter-updateを呼び出すので、最初のメッセージは即座にプリントされる。

Function: progress-reporter-update reporter &optional value

この関数は操作の進行状況報告に関する主要な機能を担う。これはreporterのメッセージと、その後にvalueにより決定された進行状況のパーセンテージを表示する。パーセンテージが0、または引数min-changemin-timeに比べて十分0に近ければ出力は省略される。

reportermake-progress-reporter呼び出しがリターンした結果でなければならない。valueは処理のカレント状況を指定して、make-progress-reporterに渡されたmin-valuemax-valueの間(両端を含む)でなければならない。たとえばバッファーのスキャンにおいては、valuepointび呼び出し結果であるべきだろう。

オプション引数suffixは、reporterのメインメッセージと進行状況テキストの後に表示する文字列。reporterが非数値のリポーターならvaluenil、またはsuffixのかわりに使用する文字列であること。

この関数はmake-progress-reporterに渡されたmin-changemin-timeにしたがい、毎回の呼び出しで新たなメッセージを出力しない。したがってこれは非常に高速であり、通常はこれを呼び出す回数を減らすことを試みるべきではない。結果として生じるオーバーヘッドは、あなたの努力をほぼ否定するだろう。

Function: progress-reporter-force-update reporter &optional value new-message suffix

この関数はprogress-reporter-updateと同様だが、これは無条件にメッセージをエコーエリアにプリントする点が異なる。

reportervaluesuffixprogress-reporter-updateの場合と同じ意味をもつ。オプションのnew-messagereporterのメッセージを変更できる。この関数は常にエコーエリアを更新するので、そのような変更は即座にユーザーに示されるだろう。

Function: progress-reporter-done reporter

この関数は処理の完了時に呼び出されること。これはエコーエリア内に単語‘done’を付加したreporterのメッセージを表示する。

progress-reporter-updateに‘100%’とプリントさせようとせずに、常にこの関数を呼び出すこと。まずこの関数は決してそれをプリントしないだろうし、これが発生しないために多くの正当な理由がある。次に‘done’はより自明である。

Macro: dotimes-with-progress-reporter (var count [result]) reporter-or-message body…

これはdotimesと同じ方法で機能するが、上述の関数を使用してループ進行状況(loop progress)の報告も行う便利なマクロである。これによりタイプ量を幾分節約できる。引数reporter-or-messageは文字列、またはプログレスリポーターオブジェクト。

以下の方法でこのマクロを使用することにより、このサブセクションの例を書き換えることができる:

(dotimes-with-progress-reporter
    (k 500)
    "Collecting some mana for Emacs..."
  (sit-for 0.01))

make-progress-reporterのオプション引数を指定したい場合には、reporter-or-message引数としてリポーターオブジェクトを使用するのが便利。たとえば前出の例は以下のように書き換えられる:

(dotimes-with-progress-reporter
    (k 500)
    (make-progress-reporter "Collecting some mana for Emacs..." 0 500 0 1 1.5)
  (sit-for 0.01))
Macro: dolist-with-progress-reporter (var list [result]) reporter-or-message body…

これはdolistと同じ方法で機能するが、上述の関数を使用してループ進行状況(loop progress)の報告も行う便利なマクロである。これによりタイプ量を幾分節約できる。dotimes-with-progress-reporterの場合のように、reporter-or-messageはプログレスリポーターか文字列。このマクロにより、前出の例を以下のように書き換えられる:

(dolist-with-progress-reporter
    (k (number-sequence 0 500))
    "Collecting some mana for Emacs..."
  (sit-for 0.01))