Next: , Previous: , Up: Positions   [Contents][Index]


29.3 エクスカーション

プログラム中の限定された部分で、ポイントを“一時的”に移動するのが便利なことが時折あります。これはエクスカーション(excursion: 遠足、小旅行)と呼ばれ、スペシャルフォームsave-excursionにより行います。この構成は、初期のカレントバッファー自体、ポイントおよびマークの値を記憶して、そのエクスカーション完了時にそれらをリストアします。これはプログラムのある部分において、プログラムの他の部分に影響を与えることなくポイントを移動する標準的な手段であり、EmacsのLispソース内では何度も使用されています。

カレントバッファー自体のみの保存やリストアが必要なら、かわりにsave-current-bufferwith-current-bufferを使用してください(Current Bufferを参照)。ウィンドウ構成の保存やリストアが必要なら、Window ConfigurationsFrame Configurationsで説明されているフォームを参照してください。

Special Form: save-excursion body…

このスペシャルフォームは、カレントバッファー自体、およびポイント値とマーク値を保存してbodyを評価し、最後にバッファーおよび保存したポイントとマークの値をリストアする。throwまたはエラーを通じたアブノーマルexit(Nonlocal Exitsを参照)の場合でも、保存された3つすべての値はリストアされる。

save-excursionがリターンする値はbody内の最後のフォームの結果、またはbodyフォームが与えられなければnilをリターンする。

save-excursionは、エクスカーション開始時にカレントだったバッファーのポイントとマークだけを保存ため、そのエクスカーション中に変更された他のバッファーのポイントおよび/またはマークは、その後も効果が残るでしょう。これはしばしば予期せぬ結果を招くので、エクスカーション中にset-bufferを呼び出した場合、バイトコンパイラーは警告を発します:

Warning: Use `with-current-buffer' rather than
         save-excursion+set-buffer

このような問題を回避するためには、以下の例のように望むカレントバッファーをセット後にのみsave-excursionを呼び出すべきです:

(defun append-string-to-buffer (string buffer)
  "BUFFER末尾にSTRINGを追加"
  (with-current-buffer buffer
    (save-excursion
      (goto-char (point-max))
      (insert string))))

同様にsave-excursionswitch-to-bufferのような関数が変更したウィンドウ/バッファーの対応をリストアしません。

警告: 保存されたポイント値に隣接する通常のテキスト挿入は、それがすべてのマーカーを再配置するのと同じように、保存されたポイントカーを再配置します。より正確には保存される値は挿入タイプnilのマーカーです。Marker Insertion Typesを参照してください。したがって保存されたポイント値は、リストア時には通常は挿入されたテキストの直前になります。

たとえsave-excursionがマーク位置を保存しても、バッファーを変更する関数がdeactivate-markをセットするのを禁止しないため、そのコマンド完了後にマークの非アクティブ化が効力を発揮します。The Markを参照してください。