Next: Buffer Names, Previous: Buffer Basics, Up: Buffers [Contents][Index]
一般的に、1つのEmacsセッション内には、多くのバッファーが存在します。常に、それらのうちの1つがカレントバッファー(current buffer)に指定され、ます。カレントバッファーとは、ほとんどの編集が行われるバッファーのことです。テキストを調べたり変更するプリミティブのほとんどは、暗黙的にカレントバッファーにたいして処理を行います(Textを参照)。
通常は、選択されたウィンドウ内に表示されるバッファーがカレントバッファーですが、常にそうではありません。Lispプログラムは、バッファーのコンテンツを処理するために、スクリーン上に表示されているものを変更することなく、任意のバッファーを一時的にカレントに指定できます。カレントバッファーの指定にたいしてもっとも基本的な関数は、set-bufferです。
この関数は、カレントバッファーをリターンする関数。
(current-buffer)
⇒ #<buffer buffers.texi>
この関数は、buffer-or-nameをカレントバッファーにする。buffer-or-nameは既存のバッファー、または既存のバッファーの名前でなければならない。リターン値は、カレントになったバッファーである。
この関数は、そのバッファーをどのウィンドウにも表示しないので、必然的にユーザーはそのバッファーを見ることはできない。しかし、Lispプログラムはその後、そのバッファーにたいして処理を行うことになるだろう。
編集コマンドがエディターコマンドループにリターンする際、Emacsは選択されたウィンドウ内に表示されているバッファーにたいして、自動的にset-bufferを呼び出します。これは混乱を防ぐためで、これにより、Emacsがコマンドを読み取るときに、カーソルのあるバッファーが、コマンドを適用されるバッファーになるのが保証されます(Command Loopを参照)。したがって、異なるバッファーを指示して切り替える場合に、set-bufferを使用するべきではありません。これを行うためには、Switching Buffersで説明されているカを使用してください。
Lisp関数を記述する際は、処理後にカレントバッファーをリストアするために、コマンドループのこの振る舞いに依存しないでください。編集コマンドは、コマンドループだけではなく、他のプログラムからLisp関数としても呼び出されます。呼び出し側にとっては、そのサブルーチンがカレントだったバッファーを変更しないほうが便利です(もちろん、それがサブルーチンの目的でない場合ですが)。
他のバッファーにたいして一時的に処理を行うには、save-current-bufferフォーム内にset-bufferを置きます。以下の例は、コマンドappend-to-bufferの簡略版です:
(defun append-to-buffer (buffer start end)
"リージョンのテキストをBUFFERに追加する"
(interactive "BAppend to buffer: \nr")
(let ((oldbuf (current-buffer)))
(save-current-buffer
(set-buffer (get-buffer-create buffer))
(insert-buffer-substring oldbuf start end))))
ここでは、カレントバッファーを記録するためにローカル変数にバインドしてから、後でsave-current-bufferがそれを再びカレントにするよう、取り計らっています。次に、set-bufferが指定されたバッファーをカレントにして、insert-buffer-substringが元のバッファーの文字列を、指定された(今はカレントの)バッファーにコピーします。
かわりに、with-current-bufferマクロを使用することもできます:
(defun append-to-buffer (buffer start end)
"BUFFERにリージョンのテキストを追加する"
(interactive "BAppend to buffer: \nr")
(let ((oldbuf (current-buffer)))
(with-current-buffer (get-buffer-create buffer)
(insert-buffer-substring oldbuf start end))))
どちらの場合でも、追加されるバッファーが偶然他のウィンドウに表示されていた場合には、次回の再表示でそのテキストがどのように変更されたか表示されるでしょう。どのウィンドウにも表示されていない場合には、スクリーン上で即座に変更を目にすることはありません。コマンドはバッファーを一時的にカレントにしますが、そのことがバッファーの表示を誘因する訳ではありません。
バッファーローカルバインディングをもつ変数にたいして、(letや関数引数などで)ローカルバインディングを作成する場合は、そのローカルバインディングのスコープの最初と最後で、同じバッファーがカレントとなることを確認してください。そうしないと、あるバッファーではバインドして、他のバッファーではバインドされないことになるかもしれません!
set-bufferの使用において、カレントバッファーが戻ることに依存しないでください。なぜなら、間違ったバッファーがカレントのときにquitが発生した場合、その処理は行われないでしょう。たとえば上記の例に倣うと、以下は間違ったやり方です:
(let ((oldbuf (current-buffer)))
(set-buffer (get-buffer-create buffer))
(insert-buffer-substring oldbuf start end)
(set-buffer oldbuf))
例で示したようにsave-current-buffer、またはwith-current-bufferを使用すれば、quitやthrowを、通常の評価と同様に処理できます。
スペシャルフォームsave-current-bufferは、カレントバッファーの識別を保存して、bodyフォームを評価し、最後にそのバッファーをカレントにリストアする。リターン値は、body内の最後のフォームの値である。throwやエラーを通じた異常exitの場合でも、カレントバッファーはリストアされる(Nonlocal Exitsを参照)。
カレントとして使用されていたバッファーが、save-current-bufferによるexit時にkillされていた場合は、それが再びカレントとなることは当然ない。かわりに、exit直前にカレントバッファーが何であれ、それがカレントになる。
with-current-bufferマクロは、カレントバッファーの識別を保存して、buffer-or-nameをカレントにし、bodyフォームを評価して、最後にカレントバッファーをリストアする。buffer-or-nameには既存のバッファー、または既存のバッファー名を指定しなければならない。
リターン値は、body内の最後のフォームの値である。throwやエラーを通じた異常exitの場合でも、カレントバッファーはリストアされる(Nonlocal Exitsを参照)。
with-temp-bufferマクロは、一時的なバッファーをカレントバッファーとして、bodyフォームを評価する。これはカレントバッファーの識別を保存して、一時的なバッファーを作成、それをカレントとして、bodyフォームを評価し、一時バッファーをkillする間に、以前のカレントバッファーをリストアする。
デフォルトでは、このマクロにより作成されたバッファー内のアンドゥ情報(Undoを参照)は記録されない(が、必要ならbodyでそれを有効にできる)。
リターン値は、body内の最後のフォームの値である。最後のフォームとして(buffer-string)を使用することにより、一時バッファーのコンテンツをリターンできる。
throwやエラーを通じた異常exitの場合でも、カレントバッファーはリストアされる(Nonlocal Exitsを参照)。
Writing to
Filesのwith-temp-fileも参照されたい。