[ << ] [ >> ]           [Top] [Contents] [Index] [ ? ]

2. 実際の評価の仕方

Emacs Lisp での関数の定義の書き方を学ぶ前に、ちょっと時間を取って、今ま で書いてきた様々なS式を評価する方法について述べておこう。これらのS式は 関数を最初の (そしてしばしば唯一の) 要素として持つリストである。幾つかの バッファに関連する関数は、単純であるし、興味深くもあるので、これらの関数 から始めようと思う。また、別のセクションで、同じくバッファに関連する他の コードについて、それらがどのように書かれているか見てみるつもりだ。

評価の仕方  編集コマンドのタイプするか C-x C-e
                                で評価を実行出来る。
2.1 バッファの名前  
2.2 バッファの獲得  
2.3 バッファ間の移動  
2.4 バッファのサイズとポイントの位置  
2.5 練習問題  

評価の仕方

Emacs Lisp に対して、カーソルを動かすとかスクリーンをスクロールするなど の編集コマンドを与える場合、あなたは常に (最初の要素が関数であるよう な) あるS式を評価している。これが Emacs の動作の基本である。

あなたが何かキーを押すと、そのことで Lisp インタプリタはあるS式を評価す る。そういう風にしてあなたは求む結果を得るのである。たとえプレーンテキス トをタイプしている時でも、Emacs Lisp の関数を評価させているのだ。この場 合に呼ばれるのは self-insert-command であり、これは、単にあなたが タイプした文字を挿入するものである。キーを押すことで評価されるような関数 はインタラクティブ (interactive) な関数、あるいは、コマ ンド (command) と呼ばれる。関数をインタラクティブにする方法は関数 の定義の書き方の章で説明することにする。関数をインタ ラクティブにする, 参照。

キーボードコマンドをタイプするのに加えて、我々はもう一つS式を評価する方 法を学んだのだった。それはカーソルをリストの終端に持っていって C-x C-e とタイプするやり方である。他にも同様にS式を評価する方法がある。そ れらについては他のセクションでその都度説明するつもりだ。

評価されるのに使われることに加えて、次の幾つかのセクションで出てくる関数 は、それらそのものが元々重要である。これらの関数を学習することで、バッファ とファイルの違いやバッファを切り替える方法、そしてその中での位置を定める 方法についてよく理解出来るようになるだろう。


2.1 バッファの名前

buffer-namebuffer-file-name という二つの関数を見てみる と、ファイルとバッファの違いがよく分るだろう。(buffer-name) とい うS式を評価すると、バッファの名前がエコー領域に表示される。一方、 (buffer-file-name) を評価すると、バッファに関連付けられているファ イルの名前がエコー領域に表示される。普通は (buffer-name) で返され る名前は、それに関連付けられているファイルの名前と一致しており、 (buffer-file-name) はそのファイルのフルパスを返す。

ファイルとバッファは異なる種類の物である。ファイルというのは計算機に記録 されている情報であり、それを消去しない限りはずっと残っているものである。 一方でバッファは Emacs の内部の情報であり、その時々のセッション (訳註: つまり、Emacs を起動して終了するまで) が終わると(もしくはそのバッファを kill すると) 消え去ってしまうものである。普通はバッファはファイルからコ ピーした情報を保持している。このことを、バッファがそのファイルにビ ジット (visit) しているという。我々はこのコピーに対して編集などの 仕事を行う。バッファに対する変更はそのバッファをセーブするまではファイル には反映されない。バッファをセーブすると、バッファの内容はファイルにコピー されて、そのまま記録されることになる。

もしこの文を GNU Emacs の Info で読んでいるのであれば、以下のS式の直後 にカーソルを持っていって C-x C-e とタイプすることで、各々の式を評 価することが出来る。

 
(buffer-name)

(buffer-file-name)

私がこれらの式を評価してみたところ、(buffer-name) を評価すると `"introduction.texinfo"' という値が返され、 (buffer-file-name) を評価すると `"/gnu/work/intro/introduction.texinfo"' が返ってきた。前者がバッファ の名前で、後者はそのファイル名である。(S式の中の括弧は、Lisp インタプリ タが buffer-namebuffer-file-name を関数として扱ってい ることを示している。もし括弧が無ければ、インタプリタはそのシンボルを変数 として評価しようとしただろう。詳しくは 変数, を参照。)

ファイルとバッファは違うものであるにも関わらず、しばしばバッファのことを ファイルと言ったり、また、その逆を言ったりする人は多い。実際、大抵の人は 「私はファイルを編集している」といい、「私はファイルにセーブしようとして いるバッファを編集している」などとは言ったりはしない。それでも殆どの場合、 状況から言いたいことは通じてしまう。しかしながら計算機のプログラムを扱う 場合は、その違いを心に留めておくことが重要だ。計算機は人間のように賢くは ないのである。

ところで `buffer' という言葉は衝突の際の衝撃を吸収するクッションを表わす 言葉から来ている。初期の計算機では、バッファはファイルと計算機の中央演算 処理装置 (CPU) の間のクッションの役目をしていた。ファイルを保存するドラ ムやテープと CPU は互いに全く異なる装置であり、速度も全然違っている。バッ ファは各々が互いに効果的に作業出来るようにするものだった。その後、バッファ は中継ぎとか、一時的な保管場所とかいう意味から変化して作業する場所を示す ようになった。この変化は小さな港から巨大な町への変化と似ている。かつては 単に船に積まれる貨物が一時的に保管される場所でしかなかった所が、ビジネス や文化の中心としての存在になってしまったのである。

さて、全てのバッファが必ず何らかのファイルに関連付けられているわけではな い。例えば emacs という単独のコマンドで、ファイルを指定せずに Emacs のセッションを始めた場合、Emacs は `*scratch*' というバッファ の画面からスタートする。このバッファはどのファイルにもビジットしていない。 同様に `*Help*' というバッファもどのファイルにも関連付けられてはい ない。

もし `*scratch*' バッファに切り替えて (buffer-name) とタイプ し、その直後にカーソルを置いて C-x C-e とタイプしてそのS式を評価 したなら、"*scratch*" という名前が返り、エコー領域に表示される。 つまり、バッファの名前は "*scratch*" である。しかし、同じことを (buffer-file-name) でやったなら、エコー領域には nil と表示 される。nil は「無 (nothing)」を表わすラテン語の単語である。この場合は `*scratch*' バッファがどのファイルにも関連付けられていないことを意 味している。(Lisp では nil は「偽 (false)」という意味や、空のリス トである () の同意語としても使われる。)

ついでに言っておくと、もしあなたが、`*scratch*' バッファにいて、ある S式が返す値をエコー領域ではなく `*scratch*' バッファそのものに表示 したい場合は、C-x C-e の代わりに C-u C-x C-e とタイプすれば 良い。こうすると、値はS式のすぐ後に表示される。つまり `*scratch*' バッファには次のように表示される。

 
(buffer-name)"*scratch*"

これは Info の中では実行出来ない。というのも Info バッファは書き込み不可 (read-only) であり、勝手にバッファの中身を修正したりすることは出来ないか らである。しかし、編集可能なバッファであれば、どのバッファであろうと実行 出来る。コードや文書(例えばこのマニュアルなんか)を書いている時には、この 機能は大変便利である。


2.2 バッファの獲得

buffer-name という関数はバッファの名前を返す。従って、バッ ファそのものを取り出すには、別の関数が必要になる。これは current-buffer という関数である。コードの中でこの関数を使うと、バッ ファそのものが得られる。

名前と、その名前がついているオブジェクトないしは実体とは、互いに異なって いる。あなたはあなたの名前とは違う。あなたは、他の人からその名前で呼ばれ る一人の人間である。もしあなたが George と話したいと頼んだ時に、 `G', `e', `o', `r', `g', `e' という文字の 書かれたカードを渡されたとしたら、あなたは面白いとは思うかもしれないが、 本来の要求は満たされない。あなたは名前と話したいというのではなく、その名 前を持つ人間と話したいのだから。バッファもそれと同じだ。スクラッチバッファ の名前は `*scratch*' である。しかし、その名前はバッファそのものでは ない。ということで、バッファそのものを取り出すときは、 current-buffer のような関数が必要なわけである。

しかしながら、事情はもう少し複雑である。例えば current-buffer を すぐ後で実験するように、S式の中で評価したとする。そうすると、バッファの 中身ではなく、バッファの名前のみが表示される。Emacs がこのように動作する のには二つの理由がある。そのバッファは何千行もあるかもしれない---これは 手軽に表示出来るというものではない。そして他のバッファで、名前は違っても 中身は同じものがあるかもしれない。それらを区別するのは、大変大切なことで ある。

さて、これがこの関数を含むS式である。

 
(current-buffer)

もし、ごく普通にこのS式を評価したとすると、エコー領域には `#<buffer *info*>' のように表示される。このように特殊な様式で表示す ることで、バッファの名前ではなく、そのバッファ自身が返されたことを示して いるのである。

ついでに言うと、プログラムの中には数値やシンボルをタイプすることは出来る が、表示されているバッファについてはそんなことは出来ない。バッファを取り 込む唯一の方法は current-buffer のような関数を使うことなのである。

関連する関数に other-buffer というのがある。これは、今、現在いる バッファ、つまりカレントバッファを除いてもっとも最近選択したバッファを返 す。もし直前に `*scratch*' バッファに行って帰ってきたとしたら、 other-buffer は、このバッファを返す。

このことは次のS式を評価することで確かめられる。

 
(other-buffer)

エコー領域には `#<buffer *scratch*>' もしくは、あなたが最近行って帰っ てきたバッファの名前が表示されたはずだ。


2.3 バッファ間の移動

other-buffer という関数はこれを引数とする関数から呼ばれた場合には 実際にそのバッファの中身を提供する。これは other-bufferswitch-to-buffer を使って他のバッファに切り替えることで確かめられ る。

が、その前に、switch-to-buffer という関数を簡単に紹介しておこう。 Info バッファから (buffer-name) を評価するために `*scratch*' バッファに行って戻ってくる際に、多分あなたはまず C-x b とタイプし、 そしてミニバッファにどのバッファに移るか尋ねるプロンプトが出た時に `*scratch*' とタイプしたのではないだろうか。この時のキーストローク C-x b は Lisp インタプリタに対してインタラクティブに Emacs Lisp の 関数 switch-to-buffer を評価させているのである。前にも言ったよう に Emacs はこのようにして動作している。また別のキーストロークはまた別の 関数を呼び出したり走らせたりする。例えば C-fforward-char を呼び出すし、M-eforward-sentence を呼び出す、といった感じである。

S式の中で switch-to-buffer と書いて、そいつに移るべきバッファを 与えると、C-x b と全く同じようにしてバッファを切り替えることが出来 る。

ここにそのS式を挙げておく。

 
(switch-to-buffer (other-buffer))

switch-to-buffer というシンボルはこのリストの最初の要素であるから、 Lisp インタプリタは、こいつを関数として扱い、それに定義されている命令を 実行する。しかし、その前に、内側に括弧に挟まれた other-buffer が あることを発見し、こちらを先に解釈する。other-buffer は、このリス トの最初の (そしてこの場合は唯一の) 要素であるから、Lisp インタプリタは この関数を走らせる。するとこいつは別のバッファを返す。次にインタプリタは 返ってきたバッファを switch-to-buffer に引数として渡して、この関 数を走らせる。そうして Emacs は他のバッファに切り替わる。もし、この文書 を Info で読んでいるなら早速試してみよう。上のS式を評価するのである。 (戻ってくるには、C-x b RET とタイプする。)

後の方のセクションに出てくるプログラミングの例では switch-to-buffer よりも set-buffer という関数の方をより多 く見かけるだろう。これは計算機のプログラムと人間の違いによる。人間は目を 持ち今作業している計算機の端末の上にそのバッファを見たいと思うものである。 これはいうまでもなく当たり前のことである。しかしながら、プログラムは目を 持たない。プログラムがバッファを扱っている時には、バッファはスクリーンに 見えていなくたって良いのである。

switch-to-buffer は人間のために設計されており、二つのことを行う。 一つは Emacs が注意を向けているバッファを切り替えることであり、もう一つ は画面に見えているバッファを切り替えることである。一方、 set-buffer の方は一つの仕事しかしない。単に計算機が注意を向けてい るバッファを別のバッファに切り替えるだけである。画面に見えているウィンド ウはそのままだ (勿論、普通はそのコマンドが終了するまでは何も起こらない。)

ここでまた別の専門用語を紹介しよう。呼び出す (call) という言 葉である。最初のシンボルが関数であるリストを評価すると、その関数が呼び出 される。(call される。)この時の呼び出すという単語の使い方は、「呼び出す」 ことで実体としての関数が何かをやってくれることから来ている---本物の配管 工を「呼び出す」と水洩れを直してくれるのと一緒である。


2.4 バッファのサイズとポイントの位置

最後に、簡単な関数を幾つか見てみよう。buffer-size, point, point-min, そして point-max である。これらはバッファのサイ ズとその中でのポイントの位置の情報を与えてくれるものである。

buffer-size という関数は現在のバッファの大きさを教えてくれる。 つまり、そのバッファの中の文字の数を返すのである。

 
(buffer-size)

これをいつものように、S式の最後にカーソルを持っていって C-x C-e とタイプすることで評価してみよう。

Emacs の中では現在のカーソルの位置はポイントと呼ばれる。(point) というS式はバッファの始まりからポイントまでの文字数を返す。それによって 現在のカーソルの場所が分る。

次のS式をこのバッファの中でいつも通りに評価すればポイントまでの文字数が 分る。

 
(point)

これを書いているときには、point の値は121905であった。この point という関数は、このマニュアルの後の方に出てくる幾つかの例の 中では頻繁に使われる。

勿論ポイントの値はバッファの中での位置に依存している。次の場所でポイント を評価すれば、その値はさっきよりも大きくなっているはずである。

 
(point)

私の場合この場所でのポイントの値は122376であった。これは両方のS式の間に (空白も含めて) 471文字あることを示している。(訳註:Mule では、内部的にマ ルチバイト文字の先頭にリーディングキャラクタを付けて扱うので、例えば2バ イト文字一つは3ポイントに数えられる。)

point-min という関数はちょっと point に似ているが、こちら はカレントバッファ中のポイントの値の中で許される最小の値を返す。この値は ナローイング (narrowing) が有効になっていない限り1という数値 である。(ナローイングというのは、あなた自身もしくはプログラムの操作をバッ ファの特定部分に制限してしまうある仕組みである。詳しくは ナローイングとワイドニング, を参照のこと。) 同様に、 point-max というのはカレントバッファ中のポイントの値の中で許され る最大の値を返す。


2.5 練習問題

あなたが作業しているファイルを一つ開いて、その中央辺りまで行きなさい。そ して、そのバッファ名、ファイル名、長さ、及びファイルの中での位置を調べな さい。


[ << ] [ >> ]           [Top] [Contents] [Index] [ ? ]

This document was generated by Matsuda Shigeki on April, 10 2002 using texi2html