プログラム中の限定された部分でポイントを一時的に移動するのが便利なことが時折あります。これはエクスカーション(excursion:
遠足、小旅行)と呼ばれるもので、スペシャルフォームsave-excursion
により行われます。この構文は初期のカレントバッファー自体とポイントの値を記憶して、そのエクスカーション完了時にそれらをリストアします。これはプログラムのある部分においてプログラムの他の部分に影響を与えることなくポイントを移動する標準的な手段であり、EmacsのLispソース内では何度も使用されています。
カレントバッファー自体のみの保存やリストアが必要なら、かわりにsave-current-buffer
やwith-current-buffer
を使用してください(Current Bufferを参照)。ウィンドウ構成の保存やリストアが必要なら、Window ConfigurationsとFrame Configurationsで説明されているフォームを参照してください。
このスペシャルフォームはカレントバッファー自体とポイント値を保存、bodyを評価してから最後にバッファーと保存したポイントとマークの値をリストアする。throw
やエラーを通じたアブノーマルexit(Nonlocal Exitsを参照)の場合にも、保存されたいずれの値もリストアされる。
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-excursion
はswitch-to-buffer
のような関数が変更したウィンドウ/バッファーの対応をリストアしません。
警告:
保存されたポイント値に隣接する通常のテキスト挿入は、それがすべてのマーカーを再配置するのと同じように、保存されたポイントカーを再配置します。より正確には保存される値は挿入タイプnil
のマーカーです。Marker Insertion Typesを参照してください。したがって保存されたポイント値は、リストア時には通常は挿入されたテキストの直前になります。
このマクロはsave-excursion
と同様だが、マークの位置とmark-active
の保存とリストアも行う点が異なる。このマクロはEmacsのバージョン25.1以前にsave-excursion
が行っていたことを行う。