プログラムの局所的な範囲内で一時的にポイントを移動させることは、しばしば有用です。これはエクスカーションと呼ばれ、save-excursionという特殊形式で行われます。この構文は、現在のバッファの初期状態とポイントの値を記憶し、エクスカーション完了後にそれらを復元します。これは、プログラムの一部分内でポイントを移動させつつ、プログラムの他の部分に影響を与えないための標準的な手法であり、EmacsのLispソース内で数千回も使用されています。
現在のバッファのアイデンティティを保存・復元するだけでよい場合は、代わりに save-current-buffer または with-current-buffer を使用してください(現在のバッファ を参照)。ウィンドウ構成を保存または復元する必要がある場合は、ウィンドウ構成 および フレーム構成 で説明されている形式を参照してください。
この特殊なフォームは、現在のバッファの識別子とその中のポイントの値を保存し、bodyを評価し、最後にバッファと保存されたポイントの値を復元します。throwやエラーによる異常終了の場合でも、保存された両方の値は復元されます(非局所終了を参照)。
save-excursion が返す値は、body
内の最後のフォームの結果であり、ボディフォームが指定されていない場合は nil の結果となります。
save-excursion はエクスカーション開始時に有効だったバッファの point
のみを保存するため、エクスカーション中に他のバッファの point
に加えられた変更は、その後もそのまま保持されます。これにより意図しない結果が生じることが多いため、バイトコンパイラはエクスカーション中に set-buffer を呼び出した場合に警告を発します:
Warning: Use ‘with-current-buffer’ rather than
save-excursion+set-buffer
このような問題を回避するには、以下の例のように、目的のカレントバッファを設定してから save-excursion を呼び出すようにしてください。
(defun append-string-to-buffer (string buffer)
"Append STRING to the end of BUFFER."
(with-current-buffer buffer
(save-excursion
(goto-char (point-max))
(insert string))))
同様に、save-excursion は switch-to-buffer などの関数によって変更されたウィンドウ・バッファの対応関係を復元しません。
警告:
保存済みポイント値の隣接箇所に通常のテキストを挿入すると、すべてのマーカーと同様に、保存済み値の位置が移動します。より正確には、保存済み値は挿入タイプ
nil のマーカーです。マーカー挿入タイプを参照してください。したがって、保存済みポイント値を復元すると、通常は挿入されたテキストよりも前に配置されます。
このマクロは save-excursion と同様ですが、マーク位置と mark-active の保存・復元も行います。このマクロは、Emacs 25.1 より前の save-excursion が行っていた動作を再現します。