Node:Top, Next:, Previous:(dir), Up:(dir)


Node:Copying, Next:, Previous:Top, Up:Top

GNU一般公有使用許諾書

1991年6月 バージョン2.0

Copyright © 1989, 1991 Free Software Foundation, Inc.
675 Mass Ave, Cambridge, MA 02139, USA 1

何人も、以下の内容を変更しないでそのまま複写する場合に限り、
本使用許諾書を複製したり頒布することができます。

はじめに

ほとんどのソフトウェアの使用許諾は、ソフトウェアを共有し、 変更するユーザの自由を奪うことを意図しています。 それに対して、我々のGNU一般公有使用許諾は、 フリー・ソフトウェアを共有したり変更する自由をユーザに保証するためのもの、 即ちフリー・ソフトウェアがそのユーザ全てにとって フリーであることを保証するためのものです。 本使用許諾は、Free Software Foundationのほとんど全てのソフトウェアに 適用されるだけでなく、 プログラムの作成者が本使用許諾に依るとした場合のそのプログラムにも 適用することができます。 (その他の Free Software Foundation のソフトウェアのいくつかは、 本許諾書ではなく、GNUライブラリ一般公有使用許諾で保護されます。) あなたは自分のプログラムにもこれを適用できます。

我々がフリー・ソフトウェアについて言う場合は 自由のことに言及しているのであって、価格のことではありません。 我々の一般公有使用許諾の各条項は、次の事柄を確実に実現することを 目的として立案されています。

このようなユーザの権利を守るために、我々は、 何人もこれらの権利を否定したり、あるいは放棄するように ユーザに求めることはできないという制限条項を設ける必要があります。 これらの制限条項は、ユーザが、フリー・ソフトウェアの複製物を 頒布したり変更しようとする場合には、そのユーザ自身が守るべき義務ともなります。

例えば、あなたがフリー・ソフトウェアの複製物を頒布する場合、 有償か無償かにかかわらず、 あなたは自分の持っている権利を全て相手に与えなければなりません。 あなたは、相手もまたソース・コードを受け取ったり入手できるということを 認めなければなりません。 さらにあなたは、彼らが自分たちの権利を知るように、 これらの条項を知らしめなければなりません。

 我々は次の2つの方法でユーザの権利を守ります。 (1)ソフトウェアに著作権を主張し、 (2)本使用許諾の条項の下で ソフトウェアを複製・頒布・変更する権利をユーザに与えます。

また、各作成者や我々自身を守るために、 本フリー・ソフトウェアが無保証であることを 全ての人々が了解している必要があります。 さらに、他の誰かによって変更されたソフトウェアが頒布された場合、 受領者はそのソフトウェアがオリジナル・バージョンではないということを 知らされる必要があります。 それは、他人の関与によって原開発者に対する評価が 影響されないようにするためです。

最後に、どのフリー・プログラムもソフトウェア特許に絶えず脅かされています。 我々は、フリー・プログラムの再頒布者が個人的に特許権を取得し、 事実上そのプログラムを自分の財産にしてしまうという危険を 避けたいと願っています。 これを防ぐために我々は、いずれの特許も、 誰でも自由に使用できるように使用許諾されるべきか、 あるいは何人に対しても全く使用させないかの、 いずれかにすべきであることを明らかにしてきました。

複写・頒布・変更に対する正確な条項と条件を次に示します。

  1. 本使用許諾は、本一般公有使用許諾の各条項に従って頒布されるという 著作権者からの告知文が表示されているプログラムやその他の作成物に適用されます。 以下において「プログラム」とは、そのようなプログラムや作成物を指すものとし、 また、「プログラム生成物」とは、上述した「プログラム」自身、または、 著作権法下における全ての派生物;すなわち、その「プログラム」の全部又は一部を、 そのまま又は変更して、且つ/又は他の言語に変換して、 内部に組み込んだ作成物を意味します。 (以下、言語変換は「変更」という用語の中に無条件に含まれるものとします。) 本使用許諾によって許諾を受ける者を「あなた」と呼びます。 

    複製、頒布、変更以外の行為は本使用許諾の対象としません。 それらは本使用許諾の範囲外です。 「プログラム」を実行させる行為に関して制約はありません。 「プログラム」の出力は、 (「プログラム」を実行させて作成させたかどうかとは無関係に) その内容が「プログラム生成物」である場合に限り本使用許諾の対象となります。 これが当てはまるかどうかは、「プログラム」が何をするものかに依ります。

  2. あなたは、どのような媒体上へ複製しようとする場合であっても、 入手した「プログラム」のソース・コードを そのままの内容で複写した上で適正な著作権表示と保証の放棄を明確、 且つ適正に付記する場合に限り、複製又は頒布することができます。 その場合、本使用許諾及び無保証に関する記載部分は、 全て元のままの形で表示してください。 また、「プログラム」の頒布先に対しては、 「プログラム」と共に本使用許諾書の写しを渡してください。

    複製物の引き渡しに要する実費は請求することができます。 また、あなた独自の保証を行なう場合はそれを有償とすることができます。

  3. 次の各条件を全て満たしている限り、あなたは、 「プログラム」又はその一部分を変更して「プログラム生成物」とすることができ、 さらに、変更版や右作成物を上記第2項に従って複製又は頒布することもできます。
    1. ファイルを変更した旨とその変更日とを、変更したファイル上に明確に表示すること。
    2. 変更したか否かを問わず、凡そ「プログラム」 又はその一部分を内部に組み込んでいるか 又はそれから派生した生成物を頒布する場合には、 その全体を本使用許諾の条項に従って第三者へ無償で使用許諾すること。
    3. 変更したプログラムが実行時に通常の対話的な方法で コマンドを読むようになっているとすれば、 最も普通の方法で対話的にそのプログラムを実行する時に、 次の内容を示す文言がプリンタへ印字されるか、或いは画面に表示されること。
      • 適切な著作権表示。
      • 無保証であること(あなたが独自に保証する場合は、その旨)。
      • 頒布を受ける者も、 本使用許諾と同一の条項に従って「プログラム」を再頒布できること。
      • 頒布を受ける者が本使用許諾書の写しを参照する方法。 (例外として、「プログラム」自体は対話的であっても起動時の文言を 通常は印字しないのならば、 あなたの「プログラム生成物」はこのような文言を印字する必要はありません。)

    これらの要件は変更された作成物にも全て適用されます。 その変更版の或る部分が「プログラム」の派生物ではなく、 しかもそれ自体独立で異なる作成物だと合理的に考えられる場合、 あなたがそれらを別の作成物として頒布した時は、 本使用許諾とその条項はそれらの部分には適用されません。 しかし、それらを「プログラム生成物」の一部として頒布する場合は、 全体が本使用許諾の条項に従って頒布されなければならず、 使用許諾を受ける他の全ての者に対する許諾も プログラム全体にわたって与えられなければならず、 結果として、誰が書いたかにかかわらず、 全ての部分に本使用許諾が適用されなければなりません。

    このように、本条項の意図するところは、 完全にあなたによって書かれた作成物について、権利を要求したり、 あなたと権利関係を争うことではありません。 むしろその目的は、作成物が「プログラム生成物」 である場合にその派生物や集合物の頒布を規制することにあります。

    さらに、「プログラム」(又は「プログラム生成物」)と 「プログラム生成物」とはならない他のプログラムとを、 単に保管や頒布のために同一の媒体上にまとめて記録したとしても、 本使用許諾は他のプログラムには適用されません。

  4. あなたは、以下のうちいずれか1つを満たす限り、 上記第2項及び第3項に従って「プログラム」 (又は、上記第3項で言及している「プログラム生成物」)を オブジェクト・コード又は実行可能な形式で複製及び頒布することができます。
    1. 対応する機械読み取り可能なソース・コード一式を一緒に引き渡すこと。 その場合、そのソース・コードの引き渡しは上記第2項及び第3項に従って、 通常ソフトウェアの交換に用いられる媒体で行なわれること。
    2. 少なくとも3年間の有効期間を定め、 且つその期間内であれば対応する機械読み取り可能なソース・コード一式の複製を、 ソース頒布に関わる実費以上の対価を要求せずに提供する旨、 及びその場合には上記第2項及び第3項に従って、 通常ソフトウェアの交換に用いられる媒体で提供される旨を記載した書面を、 第三者に一緒に引き渡すこと。
    3. 対応するソース・コード頒布の申し出に際して、 あなたが得た情報を一緒に引き渡すこと。 (この選択肢は、営利を目的としない頒布であって、 且つあなたが上記の(b)項に基づいて、 オブジェクト・コード或いは実行可能形式の プログラムしか入手していない場合に限り適用される選択項目です。)

    なお、ソース・コードとは、変更作業に適した記述形式を指します。 また、実行可能形式のファイルに対応するソース・コード一式とは、 それに含まれる全モジュールに対応する全てのソース・コード、 及びあらゆる関連のインタフェース定義ファイル、 及び実行を可能にするコンパイルとインストールの制御に関する記述を指します。 特別な例外として、実行可能なファイルが動作するオペレーティング・システムの 主要な構成要素(コンパイラ、カーネルなど)と共に (ソース・コード又はバイナリのどちらかで)頒布されているものについては、 その構成要素自体が実行形式に付随していない場合に限り、 頒布されるソース・コードに含める必要はありません。

    実行可能形式またはオブジェクト・コードの頒布が、 指示された場所からの複製のためのアクセス権の賦与である場合、 同じ場所からのソース・コードの複製のための同等なアクセス権を賦与すれば、 たとえ第三者にオブジェクト・コードと共にソースの複製を強いなくとも、 ソース・コードを頒布したものとみなします。

  5. 本使用許諾が明示的に許諾している場合を除き、あなたは、 「プログラム」を複製、変更、サブライセンス、頒布することができません。 本使用許諾に従わずに「プログラム」を複製、変更、サブライセンス、 頒布しようとする行為は、それ自体が無効であり、且つ、 本使用許諾があなたに許諾している「プログラム」の権利を自動的に消滅させます。 その場合、本使用許諾に従ってあなたから複製物やその権利を得ている第三者は、 本使用許諾に完全に従っている場合に限り、 引続き有効な使用権限を持つものとします。
  6. あなたはまだ同意の印として署名していないので、 本使用許諾を受け入れる必要はありません。 しかし、あなたに「プログラム」又はその派生物を変更又は再頒布する許可を 与えるものは本使用許諾以外にはありません。 これらの行為は、あなたがもし本使用許諾を受け入れないのであれば、 法律によって禁じられます。 従って、あなたが「プログラム」(又は「プログラム生成物」)の変更又は頒布を 行えば、それ自体であなたは本使用許諾を受け入れ、且つ、 「プログラム」又はその「プログラム生成物」の複製、頒布、変更に 関するこれらの条項と条件の全てを受け入れたことを示します。
  7. あなたが「プログラム」(又はその「プログラム生成物」)を再頒布すると自動的に、 その受領者は、元の使用許諾者から、本使用許諾の条項に従って「プログラム」を 複製、頒布、変更することを内容とする使用許諾を受けたものとします。 あなたは、受領者に許諾された権利の行使について、 さらに制約を加えることはできません。 あなたには、第三者に本使用許諾の受け入れを強いる責任はありません。
  8. 裁判所の判決、又は特許侵害の申し立て、又は(特許問題に限らない) 何らかの理由の結果として、あなたに課せられた条件が本使用許諾と 相入れないものであったとしても(裁判所の命令、契約、その他によるものであれ)、 本使用許諾の条件が免除されるものではありません。 本使用許諾による責務と、その他の何らかの関連責務を同時に満たす態様で 頒布することができないならば、 あなたは「プログラム」を全く頒布してはいけません。 例えば、特許権の内容が、あなたから直接又は間接に複製を受け取った全ての人に 使用料のないプログラムの再頒布を許さないものであれば、 あなたがかかる特許上の要請と本使用許諾の両方を満足させる方法は、 「プログラム」の頒布を完全に断念することだけです。

    本条項の或る部分が何らかの特別な状況下で無効または適用不可能になった場合、 本条項のその他の残りの部分が適用されるように意図されており、また、 本条項は全体としてその他の状況に当てはまるように意図されています。

    本条項の目的は、特許やその他の財産権を侵害したり、 そのような権利に基づく主張の妥当性を争うようにあなたに 勧めることではありません。 本条項の唯一の目的は、フリー・ソフトウェアの頒布システムの完全性を守ることで、 それは公有使用許諾の実践によって履行されます。 多くの人々が、このシステムの一貫した適用を信頼して、 このシステムを通じて頒布されている幅広い範囲のソフトウェアに惜しみない貢献を してくれました。 作成者や寄贈者が他の何らかのシステムを通じてソフトウェアを 頒布したいと決めることは彼らの自由意志であり、 使用許諾を受ける者はその選択を強いることはできません。

    本条項は、本使用許諾の他の条項の意味内容が何であるかを 完全に明らかにすることを意図しています。

  9. 「プログラム」の頒布・使用が、ある国において特許又は著作権で 保護されたインタフェースのどちらかで制限される場合、 「プログラム」を本使用許諾下においた原著作権保持者は、 その国を除外する旨の明示的な頒布地域制限を加え、 それ以外の(除外されない)国に限定して頒布が 許されるようにすることができます。 そのような場合、その制限を本使用許諾の本文に あたかも書かれているかのように本使用許諾の中に組み入れられるものとします。
  10. Free Software Foundation は随時、本一般公有使用許諾の改訂版、 又は新版を公表することがあります。 そのような新しいバージョンは、 現行のバージョンと基本的に変わるところはありませんが、 新しい問題や懸案事項に対応するために細部では異なるかもしれません。

    各バージョンは、バージョン番号によって区別します。 「プログラム」中に本使用許諾のバージョン番号の指定がある場合は、 その指定されたバージョンか、又はその後にFree Software Foundationから 公表されているいずれかのバージョンから1つを選択して、 その条項と条件に従ってください。 「プログラム」中に本使用許諾のバージョン番号の指定がない場合は、 Free Software Foundation が公表したどのバージョンでも選択することができます。

  11. 「プログラム」の一部を頒布条件の異なる他のフリー・プログラムに 組み込みたい場合は、その開発者に書面で許可を求めてください。 Free Software Foundation が著作権を持っているソフトウェアについては、 Free Software Foundation へ書面を提出してください。 このような場合に対応するために我々は例外的処理をすることもありますが、 その判断基準となるのは、次の2つの目標の実現に合致するか否かという点です。 即ち、1つは我々のフリー・ソフトウェアの全ての派生物を フリーな状態に保つことであり、もう1つはソフトウェアの共有と再利用とを 広く促進させることです。
  12. 「プログラム」は無償で使用許諾されますので、適用法令の範囲内で、 「プログラム」の保証は一切ありません。 著作権者やその他の第三者は全く無保証で「そのまま」の状態で、且つ、 明示か暗黙であるかを問わず一切の保証をつけないで提供するものとします。 ここでいう保証とは、市場性や特定目的適合性についての暗黙の保証も含まれますが、 それに限定されるものではありません。 「プログラム」の品質や性能に関する全てのリスクはあなたが負うものとします。 「プログラム」に欠陥があるとわかった場合、 それに伴う一切の派生費用や修理・訂正に要する費用は全てあなたの負担とします。
  13. 適用法令の定め、又は書面による合意がある場合を除き、 著作権者や上記許諾を受けて「プログラム」の変更・再頒布を為し得る第三者は、 「プログラム」を使用したこと、 または使用できないことに起因する一切の損害について何らの責任も負いません。 著作権者や前記の第三者が、そのような損害の発生する可能性について 知らされていた場合でも同様です。 なお、ここでいう損害には通常損害、特別損害、偶発損害、間接損害が含まれます (データの消失、又はその正確さの喪失、あなたや第三者が被った損失、 他のプログラムとのインタフェースの不適合化、等も含まれますが、 これに限定されるものではありません)。

注意

英文文書(GNU General Public License)を正式文書とする。 この和文文書は弁護士の意見を採り入れて、 できるだけ正確に英文文書を翻訳したものであるが、 法律的に有効な契約書ではない。

和文文書自体の再配布に関して

いかなる媒体でも次の条件がすべて満たされている場合に限り、 本和文文書をそのまま複写し配布することを許可する。 また、あなたは第三者に対して本許可告知と同一の許可を与える場合に限り、 再配布することが許可されています。

あなたの新しいプログラムにこれらの条項を適用する方法

あなたが新しくプログラムを作成し、それを公用に供したい場合は、 プログラムをフリー・ソフトウェアにして、 全ての人々が以上の各条項に従ってこれを再頒布や変更をすることが できるようにするのが最良の方法です。

そうするためには、プログラムに以下の表示をしてください。 その場合、無保証であるということを最も効果的に伝えるために、 ソース・ファイルの冒頭にその全文を表示すれば最も安全ですが、 その他の方法で表示する場合でも、「著作権表示」と全文を読み出す為の アドレスへのポインタだけはファイル上に表示しておいてください。

プログラム名とどんな動作をするものかについての簡単な説明の行
Copyright(C) 19○○年、著作権者名

本プログラムはフリー・ソフトウェアです。
あなたは、Free Software Foundationが公表したGNU 一般公有使用許諾の
「バージョン2」或いはそれ以降の各バージョンの中からいずれかを選択し、
そのバージョンが定める条項に従って本プログラムを
再頒布または変更することができます。

本プログラムは有用とは思いますが、頒布にあたっては、
市場性及び特定目的適合性についての暗黙の保証を含めて、
いかなる保証も行ないません。
詳細についてはGNU 一般公有使用許諾書をお読みください。

あなたは、本プログラムと一緒にGNU一般公有使用許諾の写しを
受け取っているはずです。
そうでない場合は、
 Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA 2 へ手紙を書いてください。

また、ユーザが電子メイルや書信であなたと連絡をとる方法についての情報も 書き添えてください。

プログラムが対話的に動作する場合は、 対話モードで起動した時に次のような短い告知文が表示されるようにしてください。

Gnomovision バージョン69、Copyright(C)19○○年 著作権者名
Gnomovision は完全に無保証です。詳細は show w とタイプしてください。
これはフリー・ソフトウェアなので、特定の条件の下でこれを再頒布する
ことができます。詳細は show c とタイプしてください。

上記のshow wshow cは各々、 本一般公有使用許諾の関連する部分を表示するコマンドを指します。 もちろん、あなたが使うこれらのコマンドはshow wshow cといった 呼び名でなくても構いません。 さらに、それらのコマンドはあなたのプログラムに合わせる為に、 マウスでクリックしたりメニュー形式にすることもできます。

また、必要と認めた場合には、あなたの雇い主 (あなたがプログラマとして働いている場合)や在籍する学校から、 そのプログラムに対する「著作権放棄」を認めた署名入りの書面を入手してください。 ここにその文例を載せます。名前は変えてください。

Yoyodyne, Inc. は、James Hacker が開発したプログラム`Gnomovision'
(コンパイラにつなげるプログラム)についての著作権法上の全ての権利を放棄する。

Ty Coon の署名, 1 April 1989
Ty Coon, 副社長

本一般公有使用許諾は、あなたのプログラムを財産権の対象となっている 他のプログラムに組み込むことは認めていません。 あなたのプログラムがサブルーチン・ライブラリであって、 あなたがそのライブラリを財産権の対象となっている他のアプリケーションと リンクさせることによって、さらに有用なものにしようとする場合には、 本使用許諾書の代わりに、GNUライブラリ一般公有使用許諾書に従ってください。


Node:Introduction, Next:, Previous:Copying, Up:Top

はじめに

GNU Emacsテキストエディタの大部分は、 Emacs Lispと呼ばれるプログラム言語で記述してあります。 Emacs Lispで新たなコードを書いて、 それをエディタの拡張としてインストールできます。 しかし、Emacs Lispは、単なる『拡張言語』ではありません。 それ自身、れっきとしたプログラム言語です。 他のプログラム言語でできることは、Emacs Lispでできます。

Emacs Lispは、エディタで使うために設計してあるため、 ファイル、バッファ、ディスプレイ、サブプロセスなどを扱う機能に加えて、 テキストを走査し解析する特別な機能もあります。 Emacs Lispは編集機構に密に組み込まれています。 このため、編集コマンドはLispプログラムからも呼び出せる関数ですし、 カスタマイズのためのパラメータは普通のLisp変数です。

本書は、Emacs Lispを完全に記述することを目指しています。 初心者向けの入門には、Free Software Foundation刊、 Bob ChassellのAn Introduction to Emacs Lisp Programming 3 をご覧ください。 本書では、Emacsの操作を熟知しているものと仮定します。 操作に関する基本的な情報は、The GNU Emacs Manual 4 を参照してください。

おおまかにいえば、始めのほうの章では、 多くのプログラム言語に見られる機能に相当するEmacs Lispの機能を説明し、 あとのほうの章では、 Emacs Lispに特有の機能や編集に特化した機能を説明します。

本書は、2.5版です。


Node:Caveats, Next:, Up:Introduction

警告

本書は、数多くの草稿を重ねてきました。 ほぼ完璧に近いはずですが、誤りは皆無ではありません。 ふれていない話題も少なからずあります。 (大部分の個別のモードのような)副次的と捉えている話題や、 まだ執筆していない話題もあります。 完全にはこれらに対処しきれませんので、 意図的に省いたことがらもあります。 たとえば、VMSにおける利用方法に関する情報です。

本書で取り上げたことがらに関しては、本書は完璧であるべきですから、 例題や記述内容から章や節の構成順序といったことまで、 広く意見を求めています。 混乱を招くような記述や、本書でふれていないことがらを 学ぶためにソースや実験で調べる必要があるときには、 本書を改訂すべきなのでしょう。 そのときは、ぜひ、教えてください。

意見や訂正は、下記へメイルしてください。

bug-lisp-manual@gnu.org

ここに蓄積されたメイルは、誰かが改訂作業を始めるまでは、読み出しません。 改訂までに、数か月、ときには、数年経過することもあります。 ですから、返事がないと憤慨しないでください。 あなたのメイルは、そのうち処理されます。 Emacs保守グループに迅速に連絡したい場合には、 bug-gnu-emacs@gnu.orgにメイルしてください。


Node:Lisp History, Next:, Previous:Caveats, Up:Introduction

Lispの歴史

Lisp(LISt Processing language、リスト処理言語)は、 人工知能の研究向けに1950年代末にMITで初めて開発されました。 Lisp言語はとても強力なので、 エディタコマンドを記述するなどの他の目的にも理想的なのです。

長年にわたって何ダースものLispが実装されており、 それぞれが独自の特徴を有しています。 その多くは、1960年代のMITのMACプロジェクトで開発されたMaclispの 影響を受けています。 最終的には、Maclispの系統の実装者達は共同して、 Common Lispと呼ばれるLispシステムの規格を開発しました。 そうこうするうちに、MITのGerry SussmanとGuy Steeleは、 単純化してあるが非常に強力なSchemeと呼ばれるLispの方言を開発しました。

GNU EmacsはMaclispの影響を強く受けていますが、 Common Lispからの影響は少ないです。 Common Lispを知っている読者は、 Common Lispとの多くの類似点に気づかれるでしょう。 しかしながら、Common Lispの多くの機能は、 省いてあるか、単純化してあります。 これは、GNU Emacsが必要とするメモリ量を削減するためです。 ときには、劇的に単純化してあるために、 Common Lispユーザーは混乱するかもしれません。 GNU Emacs LispとCommon Lispとの相違点は、 ことあるごとに指摘するつもりです。 Common Lispを知らない読者は、何も心配することはありません。 本書は自己完結しています。

clライブラリにより、Common Lispをかなりエミュレートできます。 See Top

Emacs LispはSchemeの影響をまったく受けていません。 しかし、GNUプロジェクトには、Guileと呼ばれるSchemeの実装があります。 拡張が必要なすべての新たなGNUソフトウェアではGuileを使います。


Node:Conventions, Next:, Previous:Lisp History, Up:Introduction

表記法

本節では、本書で用いる表記法を説明します。 本節を読み飛ばして、あとで参照してもかまいません。


Node:Some Terms, Next:, Up:Conventions

用語

本書では、『Lispリーダ』および『Lispプリンタ』という言葉で、 Lispオブジェクトのテキスト表現を実際のLispオブジェクトに変換する Lisp内部のルーティン群、および、逆の変換を行うルーティン群を指します。 詳しくは、See Printed Representation。 本書の読者を『プログラマ』と考えて『読者』と呼びます。 『ユーザー』とは作者自身を含めたLispプログラムを使う人のことです。

Lispコードの例は、(list 1 2 3)という形式で、 このフォントで記します。 メタな変数の名前や説明対象の関数に対する引数の名前は、 first-numberという形式で、このフォントで書きます。


Node:nil and t, Next:, Previous:Some Terms, Up:Conventions

nilt

Lispでは、シンボルnilには3つの異なる意味があります。 まず、nilという名前のシンボルです。 2つめは、真理値の(false)です。 3つめは、空リスト、つまり、要素数が0個のリストです。 変数として使った場合、nilの値はつねにnilです。

Lispリーダにとっては、()nilは同一です。 どちらも、同じオブジェクト、シンボルnilを表します。 シンボルを異なった書き方にするのは、完全に人間向けです。 ()nilをLispリーダが読み取ったあとでは、 プログラマが実際にどちらの表記を用いたかわかりません。

本書では、空リストを強調するときには()を使い、 真理値のを強調するときにはnilを使います。 これは、Lispプログラムでも使うとよい慣習です。

(cons 'foo ())                ; 空リストであることを強調する
(not nil)                     ; 真理値のであることを強調する

真理値の真を必要とする場面では、 nil以外の値は、(true)であるとみなします。 しかし、を表す望ましい書き方はtです。 を表す値が必要なとき、 適当な判断基準がない場合にはtを使います。 シンボルtの値はつねにtです。

Emacs Lispでは、niltは特別なシンボルであり、 評価するとそれ自身になります。 そのため、これらをプログラム内で定数として使うとき、 これらをクォートする必要はありません。 これらの値を変更しようとすると、エラーsetting-constantになります。 コロン(:)で始まる名前のシンボルも同様です。 See Constant Variables


Node:Evaluation Notation, Next:, Previous:nil and t, Up:Conventions

評価の表記法

評価可能なLisp式をフォーム(form、形式)と呼びます。 フォームを評価すると、Lispオブジェクトである結果を生じます。 本書の例題では、これを=>で表します。

(car '(1 2))
     => 1

これは、『(car '(1 2))を評価すると1になる』と読みます。

フォームがマクロ呼び出しの場合には、 Lispが評価すべき新たなフォームに展開します。 展開結果を==>で表します。 展開したフォームの評価結果を示す場合もあれば、 示さない場合もあります。

(third '(a b c))
     ==> (car (cdr (cdr '(a b c))))
     => c

あるフォームを説明するときに、 同一の結果を生じる別のフォームを示すことがあります。 2つのまったく等価なフォームを==で表します。

(make-sparse-keymap) == (list 'keymap)


Node:Printing Notation, Next:, Previous:Evaluation Notation, Up:Conventions

結果表示の表記法

本書の数多くの例題は、評価するとテキストを表示します。 (*scratch*バッファのような)Lisp対話バッファで例題のコードを 実行すると、表示テキストはバッファに挿入されます。 (関数eval-regionで評価するなどの) 別の手段で例題を実行すると、表示テキストはエコー領域に表示されます。 エコー領域に表示されるテキストは、1行に切り詰められていることに 注意してください。

本書の例題では、表示場所には無関係に、 表示テキストを-|で表します。 フォームを評価した結果返される値(ここではbar)は、 後続の行に分けて書きます。

(progn (print 'foo) (print 'bar))
     -| foo
     -| bar
     => bar


Node:Error Messages, Next:, Previous:Printing Notation, Up:Conventions

エラーメッセージ

エラーを通知する例題もあります。 これは、通常、エコー領域にエラーメッセージを表示します。 エラーメッセージは、error-->で始まる行に示します。 エコー領域には、error-->は表示されないことに注意してください。

(+ 23 'x)
error--> Wrong type argument: number-or-marker-p, x


Node:Buffer Text Notation, Next:, Previous:Error Messages, Up:Conventions

バッファ内のテキストの表記法

バッファ内のテキストを修正する例題もあります。 このような場合、『実行前』と『実行後』のテキストを示します。 それらの例題では、バッファ名を含めたダッシュから成る2行で挟んで、 当該バッファの内容を示します。 さらに、ポイント位置を-!-で表します。 (もちろん、ポイントを表す記号は、バッファ内のテキストの一部ではない。 現在ポイントが位置する2つの文字のあいだを表す。)

---------- Buffer: foo ----------
This is the -!-contents of foo.
---------- Buffer: foo ----------

(insert "changed ")
     => nil
---------- Buffer: foo ----------
This is the changed -!-contents of foo.
---------- Buffer: foo ----------


Node:Format of Descriptions, Previous:Buffer Text Notation, Up:Conventions

記述形式

関数、変数、マクロ、コマンド、ユーザーオプション、 スペシャルフォームは、本書では統一した形式で記述します。 第1行目は、それぞれの名前と、引数があれば引数群です。 これに説明文が続き、場合によっては例題も示します。


Node:A Sample Function Description, Next:, Up:Format of Descriptions

関数の記述例

関数の記述では、まず始めに説明対象の関数名があります。 同じ行には、引数名の並びも続きます。 これらの名前は、説明文の中で引数の値を参照するために使います。

引数ならびにキーワード&optionalが現れていれば、 それ以降の引数を省略できることを示します(省略した引数の値はnil)。 関数を呼び出すときに&optionalを書いてはいけません。

キーワード&rest (このあとには1つの引数名だけが続く)は、 残りの引数が何個でもよいことを示します。 直後にある1つの引数名は、変数としての値を持ち、 その値は残りのすべての引数のリストです。 関数を呼び出すときに&restを書いてはいけません。

では、仮想的な関数fooの記述を以下に示します。

foo integer1 &optional integer2 &rest integers Function
関数fooは、integer2からinteger1を引き算し、 残りのすべての引数を減算結果に加える。 integer2を指定しないと、デフォルトでは、数19から引き算する。
(foo 1 5 3 9)
     => 16
(foo 5)
     => 14

より一般的には、つぎのとおり。

(foo w x y...)
==
(+ (- x w) y...)

integerinteger1bufferなどの)型名を名前とする引数は、 その型の値であると仮定します。 (buffersのように)型を複数形にした場合には、 しばしば、その型のオブジェクトのリストを意味します。 objectという名前の引数は、任意の型でかまいません。 (Emacsオブジェクトの型の一覧については、see Lisp Data Types)。 (new-fileなどの)その他の名前の引数は、関数の説明文の中で言及します。 複数の関数の引数に共通する特徴について、 節の始めで説明する場合もあります。

&optional&restについての詳しい説明は、 See Lambda Expressions

コマンド、マクロ、スペシャルフォームの記述も同じ形式ですが、 「関数」のかわりに 「コマンド」、「マクロ」、「スペシャルフォーム」のいずれかです。 コマンドは、対話的に呼び出せる単なる関数です。 マクロは関数とは違った方法で引数を処理します(引数を評価しない)が、 同じ方法で引数を記します。

スペシャルフォームの記述では、省略可能な引数や繰り返される引数を 示すために、より複雑な記法を使います。 というのは、引数並びを個々の引数に分離する方法が複雑だからです。 [optional-arg]は、 optional-argが省略可能であることを示します。 また、repeated-args...は、0個以上の引数を示します。 いくつかの引数をリスト構造の内側にまとめるときには、 括弧を使います。

count-loop (var [from to [inc]]) body... Special Form
この仮想的なスペシャルフォームは、 フォーム群bodyを実行してから変数varを増やすことを 反復するループを実現する。 最初は、変数の値はfromである。 以降の反復では、変数を1(あるいは、指定があればincだけ)増やす。 vartoに等しくなると、 bodyを実行せずにループから抜ける。 例を示す。
(count-loop (i 0 10)
  (prin1 i) (princ " ")
  (prin1 (aref vector i))
  (terpri))

fromtoを省略すると、 ループ開始前にvarnilを束縛し、 各反復の開始時にvarnil以外であるとループから抜け出る。

(count-loop (done)
  (if (pending)
      (fixit)
    (setq done t)))

このスペシャルフォームでは、引数fromtoは省略できるが、 両者を同時に指定するか、同時に省略すること。 これらを指定した場合、incを指定してもよい。 これらの引数は、引数varとともにリストにまとめる。 これはbodyと区別するためであり、 bodyは残りのフォームの要素すべてを含む。


Node:A Sample Variable Description, Previous:A Sample Function Description, Up:Format of Descriptions

変数の記述例

変数(variable)は、値を保持するための名前です。 ユーザーはどんな変数でも設定できますが、 ユーザーが変更可能な特定の変数群があり、 それらをユーザーオプション(user options)と呼びます。 普通の変数もユーザーオプションも関数の記述と同じ形式で示しますが、 それらに引数はありません。

仮想的な変数electric-future-mapの記述例を示します。

electric-future-map Variable
この変数の値は、Electric Command Futureモードで使用する 完全なキーマップである。 このマップに含まれる関数は、まだ実行していないコマンドの編集を可能にする。

ユーザーオプションの記述も同じ形式ですが、 「変数」のかわりに「ユーザーオプション」です。


Node:Version Info, Next:, Previous:Conventions, Up:Introduction

版情報

これらの機構は、使用中のEmacsの版に関する情報を提供します。

emacs-version コマンド
この関数は、実行中のEmacsの版を記述した文字列を返す。 この文字列はバグの報告に含めると有益である。
(emacs-version)
  => "GNU Emacs 20.3.5 (i486-pc-linux-gnulibc1, X toolkit)
 of Sat Feb 14 1998 on psilocin.gnu.org"

対話的に呼び出すと、この関数は同じ情報をエコー領域に表示する。

emacs-build-time Variable
この変数の値は、ローカルのサイトでEmacsを構築した日時を示す。 3つの整数から成るリストであり、 current-timeと同様のもの(see Time of Day)。
emacs-build-time
     => (13623 62065 344633)

emacs-version Variable
この変数の値は、実行中のEmacsの版番号。 "20.3.1"のような文字列である。 この文字列の最後の数字は、Emacsのリリース版番号の一部ではなく、 特定のディレクトリでEmacsを構築するたびに増える。

つぎの2つの変数は、Emacs 19.23以降に存在します。

emacs-major-version Variable
Emacsのメジャー版番号を表す整数。 Emacs 20.3では、値は20。

emacs-minor-version Variable
Emacsのマイナ版番号を表す整数。 Emacs 20.3では、値は3。


Node:Acknowledgements, Previous:Version Info, Up:Introduction

謝辞

本書は、Robert Krawitz、Bil Lewis、Dan LaLiberte、 Richard M. Stallman、Chris Welty、GNUマニュアルプロジェクトのボランティア による何年にもわたる努力で執筆されました。 Computational Logic社のWarren A. Hunt, Jr.が手配した 国防省Advanced Research Projects Agency、ARPA Order 6082の援助のもと、 Robert J. Chassellは本書のレビューと編集に協力してくれました。

以下の方々が訂正を送ってくれました。 Karl Berry、Jim Blandy、Bard Bloom、 Stephane Boucher、David Boyes、Alan Carroll、Richard Davis、Lawrence R. Dodd、Peter Doornbosch、David A. Duff、Chris Eich、Beverly Erlebacher、David Eckelkamp、Ralf Fassel、Eirik Fuller、Stephen Gildea、 Bob Glickstein、Eric Hanchrow、George Hartzell、Nathan Hess、 Masayuki Ida、 Dan Jacobson、Jak Kirman、Bob Knighten、Frederick M. Korz、Joe Lammens、Glenn M. Lewis、K. Richard Magill、Brian Marick、Roland McGrath、Skip Montanaro、John Gardiner Myers、Thomas A. Peterson、 Francesco Potorti、Friedrich Pukelsheim、Arnold D. Robbins、Raul Rockwell、Per Starback、Shinichirou Sugou、Kimmo Suominen、Edward Tharp、 Bill Trost、Rickard Westman、Jean White、Matthew Wilding、Carl Witty、 Dale Worley、Rusty Wright、David D. Zuhn。


Node:Lisp Data Types, Next:, Previous:Introduction, Up:Top

Lispのデータ型

Lispオブジェクト(object)とは、 Lispプログラムが使用し操作するデータのことです。 (type)やデータ型(data type)とは、ここでは、 可能なオブジェクトの集合を意味します。

各オブジェクトは、少なくとも、1つの型に属します。 同じ型のオブジェクトは、構造に類似性があり、普通、同じ文脈で使われます。 型は互いに重複していてもよく、オブジェクトは複数の型に属することができます。 そのため、オブジェクトが特定の型に属するかどうかは判断できますが、 オブジェクトの型を『1つ』に限定することはできません。

Emacsには少数の基本オブジェクト型を組み込んであります。 これらの型は他のすべてのオブジェクト型を構成するもとであり、 基本型(primitive types)と呼びます。 各オブジェクトはたった1つの基本型に属します。 基本型には、 整数(integer)、浮動小数点数(float)、 コンス(cons)、シンボル(symbol)、 文字列(string)、ベクトル(vector)、subrバイトコード関数(byte-code function)、 ならびに、編集に関連するバッファ(buffer)などの 特別な型があります。 (see Editing Types。)

各基本型には、その型に属するオブジェクトであるかどうかを検査する 対応するLisp関数があります。

Lispオブジェクトは型を自己記述(self-typing)するという点で、 Lispは他の多くの言語とは異なります。 つまり、オブジェクトの基本型は、オブジェクト自体に暗に含まれています。 たとえば、オブジェクトがベクトルであれば、それを数と扱うことはありません。 Lispには、ベクトルは数ではないとわかっているのです。

多くの言語では、プログラマは各変数のデータ型を宣言する必要があります。 型はコンパイラが知っているのであって、データの中には入っていません。 このような型宣言はEmacs Lispには存在しません。 Lisp変数はどんな型の値でも保持でき、 変数に入れた値と型を記録しています。

本章では、GNU Emacs Lispの各標準型の表示表現と入力構文を説明します。 これらの型の使用方法の詳細は、あとの章に譲ります。


Node:Printed Representation, Next:, Up:Lisp Data Types

表示表現と入力構文

オブジェクトの表示表現(printed representation)とは、 Lispプリンタ(関数prin1)がそのオブジェクトを出力表示するときの 書式です。 オブジェクトの入力構文(read syntax)とは、 Lispリーダ(関数read)がそのオブジェクトを入力として受理する書式です。 See Read and Print

ほとんどのオブジェクトには1つ以上の可能な入力構文があります。 ある種の型のオブジェクトには入力構文はありませんが、 そのような型のオブジェクトをLispプログラムに直接入力する意味がないからです。 このような場合を除くと、 オブジェクトの表示表現はそのオブジェクトの入力構文でもあります。

他の言語では、式はテキストであって、これ以外の形はありません。 Lispでは、式はとにかくLispオブジェクトであって、 オブジェクトの入力構文であるテキストは副次的なものです。 この違いを強調する必要はありませんが、 このことを心に留めておかないと混乱することがあります。

各型には表示表現があります。 入力構文のない型もあります。 たとえば、バッファ型には入力構文はありません。 このような型のオブジェクトはハッシュ記法(hash notation)で表示します。 つまり、文字列#<のあとに説明用の文字列 (典型的には型名にオブジェクトの名前を続けたもの)を続け、 対応する>で閉じます。 ハッシュ記法を読み取ることはできませんから、 Lispリーダが#<に出会うとエラーinvalid-read-syntaxを 通知します。

(current-buffer)
     => #<buffer objects.texi>

読者が対話的に式を評価するとき、 Lispインタープリタは、まず、 式のテキスト表現を読み取ってLispオブジェクトを生成し、 そのオブジェクトを評価します(see Evaluation)。 しかしながら、評価と読み取りは別々の動作です。 読み取りでは、読み取ったテキストが表すLispオブジェクトを返します。 このオブジェクトを、のちに評価する場合もありますが、 評価しない場合もあります。 オブジェクトを読み取る基本関数readについては、 See Input Functions


Node:Comments, Next:, Previous:Printed Representation, Up:Lisp Data Types

コメント

コメント(comment)は、プログラム内に書かれたテキストであり、 プログラムを読む人間のためだけにあり、 プログラムの意味にはまったく影響しません。 Lispでは、文字列や文字定数の外にあるセミコロン(;)で コメントを始めます。 コメントは行末までです。 Lispリーダは、コメントを破棄します。 コメントは、 Lispシステム内部でプログラムを表すLispオブジェクトの一部にはなりません。

#@countという書き方は、 後続のcount個の文字を飛び越します。 これは、プログラムで生成したバイナリデータを含むコメントに便利です。 Emacs Lispのバイトコンパイラは、出力ファイルにこのようなコメントを使います (see Byte Compilation)。 しかしながら、ソースファイル向きではありません。

コメントの体裁に関する慣習については、See Comment Tips


Node:Programming Types, Next:, Previous:Comments, Up:Lisp Data Types

プログラミング向けの型

Emacs Lispには、大きく2種類の型があります。 Lispのプログラミングに関わるものと、編集に関わるものです。 前者は、さまざまな形でLispの多くの実装に見られます。 後者は、Emacs Lispに固有です。


Node:Integer Type, Next:, Up:Programming Types

整数型

Emacs Lispにおける整数の値の範囲は、ほとんどの計算機では、 -134217728から134217727(28ビット長。つまり から です。 (計算機によっては、より広い範囲になる。) Emacs Lispの算術演算関数は、桁溢れ(オーバフロー)を 検査しないことを覚えておいてください。 したがって、ほとんどの計算機では、 (1+ 134217727)は-134217728となります。

整数の入力構文は、(10を基数とした)数字の並びであり、 先頭に符号があってもよく、また、最後にピリオドがあってもかまいません。 Lispインタープリタが生成する表示表現では、 先頭の+や最後の.はありません。

-1               ; 整数 -1
1                ; 整数 1
1.               ; これも整数 1
+1               ; これも整数 1
268435457        ; 28ビット長整数では、これも整数 1

より詳しくは、See Numbers


Node:Floating Point Type, Next:, Previous:Integer Type, Up:Programming Types

浮動小数点数

Emacsは浮動小数点数を扱えます (ただし、コンパイル時のオプションで使用不可にできる)。 浮動小数点数の範囲は、計算機に依存します。

浮動小数点数の表示表現には、 小数点(に続けて1桁以上の小数部分)または指数、 あるいは、その両方が必要です。 たとえば、1500.015e215.0e21.5e3.15e4は、同じ1500という値の 浮動小数点数を書く5つの方法です。 どれも、まったく等価です。

詳しくは、See Numbers


Node:Character Type, Next:, Previous:Floating Point Type, Up:Programming Types

文字型

Emacs Lispにおける文字(character)は、 整数以外の何物でもありません。 いいかえれば、文字はその文字コードで表現されます。 たとえば、文字Aは整数 65と表現されます。

プログラムで個々の文字を独立に使うことはあまりありません。 文字を並べた文字列(strings)として扱うことが断然多いのです。 See String Type

文字列内、バッファ内、ファイル内の文字は、 現時点では、0から524287までの範囲、19ビット長に制限されます。 しかし、この範囲の値すべてが正しい文字コードではありません。 0から127までのコードはASCIIコードです。 それ以外は、非ASCIIです(see Non-ASCII Characters)。 キーボード入力を表す文字は、コントロール、メタ、シフトなどの 修飾キーを符号化するために、範囲がより広くなります。

文字は、実際には整数ですから、文字の表示表現は10進数です。 また、文字の入力構文として10進数も可能ですが、 Lispプログラムでこのように文字を書くのは最悪です。 Emacs Lispに用意してある文字向けの特別な入力構文を つねに使うべきです。 これらの構文は疑問符で始まります。

英数字向けの普通の入力構文は、疑問符に続けて1つの英数字を書きます。 したがって、文字A?A、文字B?B、 文字a?aと書きます。

たとえば、つぎのとおりです。

?Q => 81     ?q => 113

同じ入力構文を句読点文字にも使えますが、 \を追加して、Lispコードを編集するEmacsコマンドが混乱しないように することがよいでしょう。 たとえば、空白文字は?\ と書きます。 文字\は、クォートするために2つめの\を使う必要があり ?\\です。

コントロールg、バックスペース、タブ、改行、 垂直タブ、ページ送り、復帰、エスケープは、 それぞれ、?\a?\b?\t?\n?\v?\f?\r?\eと書きます。 つまり、つぎのとおりです。

?\a => 7                 ; C-g
?\b => 8                 ; バックスペース、 <BS>、C-h
?\t => 9                 ; タブ、 <TAB>、C-i
?\n => 10                ; 改行、C-j
?\v => 11                ; 垂直タブ、C-k
?\f => 12                ; ページ送り文字、C-l
?\r => 13                ; 復帰、<RET>, C-m
?\e => 27                ; エスケープ文字、<ESC>、C-[
?\\ => 92                ; バックスラッシュ文字、\

バックスラッシュで始まる系列は エスケープシーケンス(escape sequences)とも呼びます。 バックスラッシュが、エスケープ文字の役割を果たすからです。 この使い方は、文字<ESC>とは関係ありません。

コントロール文字は別の入力構文でも表現できます。 疑問符に続けてバックスラッシュ、カレット(^)、そして、 対応するコントロールでない文字を大文字か小文字で書きます。 たとえば、?\^I?\^iも、 値が9である文字C-iの正しい入力構文です。

カレットのかわりに、C-を使ってもかまいません。 ですから、?\C-iは、?\^I?\^iと等価です。

?\^I => 9     ?\C-I => 9

文字列やバッファ内ではASCIIのコントロール文字だけが許されますが、 キーボード入力においてはC-で任意の文字をコントロール文字にできます。 これらの非ASCIIコントロール文字の文字コードは、 対応する非コントロール文字の文字コードと のビットを含みます。 普通の端末では、非ASCIIコントロール文字を生成する手立てはありませんが、 Xウィンドウシステムや他のウィンドウシステムでは、 簡単に生成できます。

歴史的な理由で、 Emacsは<DEL>文字を?に対応したコントロール文字として扱います。

?\^? => 127     ?\C-? => 127

その結果、今のところ、 Xウィンドウシステムのもとでは意味のある文字Control-?\C-では表現できません。

ファイルや文字列に現れるコントロール文字を表現するには、 ^構文を勧めます。 キーボード入力のコントロール文字には、C-構文が好ましいです。 どちらを使ってもプログラムの意味には影響しませんが、 それを読む人には理解の手助けになるかもしれません。

メタ文字(meta character)は、 <META>修飾キーを使って打った文字です。 そのような文字を表す整数は、(ほとんどの計算機では負の数になる) のビットがセットされています。 上位のビットをメタや他の修飾子に用いることで、 基本となる文字コードの範囲をできるだけ大きくします。

文字列では、メタ文字を表すASCII文字には のビットを付加します。 つまり、文字列に収められるメタ文字のコードは128から255の範囲であり、 任意のASCII文字のメタ変種を使えます。 (Emacs 18やそれ以前では、この方式を文字列の外にある文字にも使っていた。)

メタ文字の入力構文には\M-を使います。 たとえば、?\M-AM-Aです。 \M-と一緒に8進文字コードも使えますし(下記参照)、 \C-や文字向けの他の構文も使えます。 したがって、M-A?\M-Aと書いたり?\M-\101と書けます。 同様に、C-M-b?\M-\C-b?\C-\M-b?\M-\002と書けます。

図形文字の大文字小文字は、その文字コードで示されます。 たとえば、ASCIIではaAの文字を区別します。 しかし、ASCIIではコントロール文字の大文字小文字を表現できません。 Emacsでは、コントロール文字を打つときに使ったシフトキーを表すために のビットを付加します。 このような区別はX端末や他の特別な端末を使っている場合に限り可能です。 普通の端末ではこのような区別を計算機に送れません。

Xウィンドウシステムでは、 文字に設定可能な修飾ビットが他に3つあります。 ハイパー(hyper)、スーパー(super)、アルト(alt)です。 これらの修飾ビットの構文は、 \H-\s-\A-です。 (これらのプレフィックスでは、大文字小文字を区別する。) したがって、?\H-\M-\A-xAlt-Hyper-Meta-xを表します。

文字向けのもっとも汎用の入力構文では、 文字コードを8進数や16進数で表現します。 8進数を使うには、順に、 疑問符、バックスラッシュ、(3桁までの)8進数字文字コードを書きます。 たとえば、?\101は文字Aを表し、 ?\001は文字C-aを表し、?\002は文字C-bを表します。 この構文で任意のASCII文字を表現できますが、 ASCIIでの表現よりも8進数値で表現することが重要な場合に限るべきです。

?\012 => 10         ?\n => 10         ?\C-j => 10
?\101 => 65         ?A => 65

16進数を使うには、順に、疑問符、バックスラッシュ、 x、16進数字文字コードを書きます。 16進数の桁数はいくつでもよいので、任意の文字コードを表現できます。 したがって、?\x41は文字Aを表し、 ?\x1は文字C-aを表し、 ?\x8e0

特別なエスケープの意味を持たないどんな文字のまえにもバックスラッシュを 付けることができ、しかも、無害です。 したがって、?\+?+に等価です。 ほとんどの文字のまえにバックスラッシュを付ける理由はありません。 しかしながら、Lispコードを編集するEmacsコマンドが混乱しないように、 ()\|;'`"#.,のいずれかの文字のまえにはバックスラッシュを付けるべきです。 空白、タブ、改行、ページ送りのような白文字のまえにも バックスラッシュを付けるべきです。 しかしながら、タブなどの実際の白文字のかわりに、 \tなどの読みやすいエスケープシーケンスを使ったほうが明確です。


Node:Symbol Type, Next:, Previous:Character Type, Up:Programming Types

シンボル型

GNU Emacs Lispにおけるシンボル(symbol)は、 名前を持ったオブジェクトです。 シンボル名は、シンボルの表示表現としての役割があります。 普通の使い方では、名前は一意です。 つまり、2つのシンボルが同じ名前を持つことはありません。

シンボルは、変数としての役割、関数名としての役割、 あるいは、属性リストを保持する役割を果たします。 また、他のすべてのLispオブジェクトと区別するためだけの役割を 果たすこともあり、データ構造の内部にそのようなシンボルが存在することを 正確に認識できます。 ある場面においては、普通、これらのうちの1つの使い方をします。 しかし、ある1つのシンボルに対してすべての使い方をしてもかまいません。

シンボル名には、どんな文字でも含められます。 ほとんどのシンボル名は、英文字、数字、-+=*/の句読点文字で書かれます。 そのような名前では、特別な書き方は必要ありません。 名前が数に見えなければ、名前を構成する文字はなんでもよいのです。 (名前が数に見えるときには、 名前の先頭に\を書いてシンボルであると強制する。) _~!@$%^&:<>{}の文字はあまり使われませんが、 これらにも特別な書き方は必要ありません。 これら以外の文字は、バックスラッシュでエスケープすれば、 シンボル名に含められます。 文字列におけるバックスラッシュの用法とは対照的に、 シンボル名におけるバックスラッシュは、直後の1文字をクォートするだけです。 たとえば、文字列では\tはタブ文字を表しますが、 シンボル名では英文字tをクォートするだけです。 名前にタブ文字を含むシンボルを書くには、 実際に(バックスラッシュの直後に)タブを使う必要があります。 しかし、そのようなことをするのは皆無でしょう。

Common Lispに関した注意: Common Lispでは、小文字を明示的にエスケープしない限り、 小文字をつねに大文字に『変換』する。 Emacs Lispでは、大文字と小文字を区別する。

シンボル名の例をいくつかあげましょう。 5番目の例の+は、数として読まれるのを防ぐために エスケープしてあることに注意してください。 6番目の例では、これは必要ありません。 なぜなら、名前の残りの部分が数としては不正だからです。

foo                 ; fooという名前のシンボル
FOO                 ; FOOという名前のシンボル、fooとは別
char-to-string      ; char-to-stringという名前のシンボル
1+                  ; 1+という名前のシンボル
                    ;   (整数の+1ではない)
\+1                 ; +1という名前のシンボル
                    ;   (読みにくい名前)
\(*\ 1\ 2\)         ; (* 1 2)という名前のシンボル(悪い名前)
+-*/_~!@$%^&=:<>{}  ; +-*/_~!@$%^&=:<>{}という名前のシンボル
                    ;   これらの文字をエスケープする必要はない


Node:Sequence Type, Next:, Previous:Symbol Type, Up:Programming Types

シーケンス型

シーケンス(sequence)とは、 要素の順序集合を表現するLispオブジェクトです。 Emacs Lispには2種類のシーケンス、つまり、リストと配列があります。 したがって、リスト型や配列型のオブジェクトは、 シーケンス型でもあると考えられます。

配列はさらに、文字列、ベクトル、文字テーブル、ブールベクトルに細分されます。 ベクトルは任意の型の要素を保持できますが、 文字列の要素は文字である必要があり、 ブールベクトルの要素はtnilのいずれかである必要があります。 バッファ内の文字のように、 文字列内の文字はテキスト属性を持てます(see Text Properties)。 ベクトルとブールベクトル 5 では、それらの要素が文字であったとしても、 テキスト属性を扱えません。 文字テーブルは、ベクトルに似ていますが、正しい文字コードで添字付けします。

リスト、文字列、および、その他の配列型は別のものですが、 それらには重要な類似性があります。 たとえば、それらすべてに長さlがあり、 それらのすべての要素は0からl-1で添字付けできます。 シーケンス関数と呼ばれるいくつかの関数は、 任意のシーケンス型を扱います。 たとえば、シーケンスから指定した添字の要素を取り出すには、 関数eltを使います。 See Sequences Arrays Vectors

一般には、同一のシーケンスを二度読み取ることは不可能です。 というのは、読むたびにつねに新たにシーケンスを作成するからです。 シーケンスの入力構文を二度読むと、 同じ内容の2つのシーケンスを得ることになります。 1つ例外があります。 空リスト()は、つねに同じオブジェクトnilを表します。


Node:Cons Cell Type, Next:, Previous:Sequence Type, Up:Programming Types

コンスセルとリスト型

コンスセル(cons cell)とは、 CARスロットおよびCDRスロットと呼ばれる 2つのポインタから成るオブジェクトです。 各スロットは、任意のLispオブジェクトを指すことができます。 また、現在CARスロットが指しているオブジェクトがなんであれ、 『コンスセルのCARは』といったいい方をします。 CDRについても同様です。

リスト(list)はコンスセルが連なったものであり、 各コンスセルのCDRスロットは、 後続のコンスセルを指すか空リストを指します。 リストに作用する関数については、See Lists。 ほとんどのコンスセルは、リストの一部分として使われるので、 リスト構造(list structure)という用語は、 コンスセルから成る任意の構造のことを意味します。

CARCDRという名称は、Lispの歴史に由来します。 最初のLispはIBM 704で動作していました。 この計算機では、ワードを2つの部分、『番地』(address)部分、 『減数』(decrement)部分と呼ばれるものに分けていました。 CARはレジスタの番地部分の内容(Contents of Address Register)を 取り出す命令であり、 CDRはレジスタの減数部分の内容(Contents of Decrement Register)を 取り出す命令でした。 一方、『コンスセル』という名称は、 これらを作成する関数consからきています。 この関数名は、その目的、セルを作る(construction of cells)からきています。

コンスセルはLispの核心なので、 『コンスセルではないオブジェクト』に対する名称もあります。 これらのオブジェクトをアトム(atoms)と呼びます。

リストの入力構文と表示表現は同一です。 開き括弧で始まり、任意個の要素、閉じ括弧で終えます。

読み取り時には、括弧の内側の各オブジェクトが、 リストの各要素になります。 つまり、これらの要素からなるコンスセルを作ります。 コンスセルのCARスロットで要素を指します。 同じコンスセルのCDRスロットで、 リスト上のつぎの要素を保持している、 リストのつぎのコンスセルを指します。 最後のコンスセルのCDRスロットはnilを指します。

リストは、コンスセルを1対の箱で表して図示できます。 (Lispリーダがこのような図表示を読むことはない。 人間や計算機が理解できるテキスト表記と違い、 箱を用いた図表示は人間だけが理解できる。) つぎの図は、3つの要素から成るリスト(rose violet buttercup)を表します。

    --- ---      --- ---      --- ---
   |   |   |--> |   |   |--> |   |   |--> nil
    --- ---      --- ---      --- ---
     |            |            |
     |            |            |
      --> rose     --> violet   --> buttercup

この図で、各箱は、任意のLispオブジェクトを指すことができるスロットを表します。 箱の対でコンスセルを表します。 各矢印は、アトムや他のコンスセルであるLispオブジェクトを指すポインタです。

この例では、最初のコンスセルのCARを表す最初の箱は、 rose(シンボル)を指しています。 あるいは、rose(シンボル)を『含んでいる』ともいいます。 最初のコンスセルのCDRを表す2番目の箱は、 つぎの1対の箱、2番目のコンスセルを指しています。 2番目のコンスセルのCARvioletであり、 このコンスセルのCDRは3番目のコンスセルです。 3番目の(最後の)コンスセルのCDRは、nilです。

同じリスト(rose violet buttercup)を 別の方法で図表示するとつぎのようになります。

 ---------------       ----------------       -------------------
| car   | cdr   |     | car    | cdr   |     | car       | cdr   |
| rose  |   o-------->| violet |   o-------->| buttercup |  nil  |
|       |       |     |        |       |     |           |       |
 ---------------       ----------------       -------------------

内部に要素を持たないリストは、空リスト(empty list)です。 これはシンボルnilと同一です。 いいかえれば、nilはシンボルでもありリストでもあります。

Lispの構文で書き表したリストの例を示します。

(A 2 "A")            ; 3要素のリスト
()                   ; 要素を持たないリスト(空リスト)
nil                  ; 要素を持たないリスト(空リスト)
("A ()")             ; 文字列"A ()"だけの1要素のリスト
(A ())               ; Aと空リストから成る2要素のリスト
(A nil)              ; 上と同じ
((A B C))            ; 1要素のリスト
                     ;   (その要素は3要素のリスト)

リスト(A ())や、これと同じ(A nil)を 箱と矢印で書くとつぎのようになります。

    --- ---      --- ---
   |   |   |--> |   |   |--> nil
    --- ---      --- ---
     |            |
     |            |
      --> A        --> nil


Node:Dotted Pair Notation, Next:, Up:Cons Cell Type

ドット対記法

ドット対記法(dotted pair notation)とは、 CARCDRを明示したコンスセルを表すもう1つの構文です。 この構文では、(a . b)で、 CARがオブジェクトaであり CDRがオブジェクトbであるコンスセルを表します。 したがって、ドット対記法は、リストの構文よりさらに汎用性があります。 ドット対記法では、リスト(1 2 3)は、 (1 . (2 . (3 . nil)))と書けます。 nilで終るリストならば、どちらの記法でも書き表せますが、 リスト記法のほうがわかりやすくて便利です。 リストを表示するときには、コンスセルのCDRがリスト以外の場合に限って ドット対記法を使います。

ドット対記法を箱で表現してみます。 つぎの例は(rose . violet)を表したものです。

    --- ---
   |   |   |--> violet
    --- ---
     |
     |
      --> rose

最後のCDRnil以外であるようなコンスセルの連鎖を表現するために、 リスト記法にドット対記法を組み合わせることもできます。 リストの最後の要素のあとにドットを書き、 続けて、最後のコンスセルのCDRを書きます。 たとえば、(rose violet . buttercup)は、 (rose . (violet . buttercup))に等価です。 このオブジェクトはつぎのようになります。

    --- ---      --- ---
   |   |   |--> |   |   |--> buttercup
    --- ---      --- ---
     |            |
     |            |
      --> rose     --> violet

(rose . violet . buttercup)という構文は不正です。 これが意味することはなにもありません。 たとえあったとしても、CDRviolet用にすでに使っているコンスセルの CDRbuttercupを置けということになります。

リスト(rose violet)は、(rose . (violet))に等価であり、 つぎのように図示できます。

    --- ---      --- ---
   |   |   |--> |   |   |--> nil
    --- ---      --- ---
     |            |
     |            |
      --> rose     --> violet

同様に、3要素のリスト(rose violet buttercup)は、 (rose . (violet . (buttercup)))に等価です。


Node:Association List Type, Previous:Dotted Pair Notation, Up:Cons Cell Type

連想リスト型

連想リスト(association list)、すなわち、alistは、 各要素がコンスセルであるように特別に構成したリストのことです。 各要素では、CARキー(key)と考え、 CDR連想値(associated value)と考えます。 (場合によっては、連想値を、CDRCARに保持することもある。) 連想リストはスタックとして使われることがままあります。 というのは、リストの先頭に対応関係を追加/削除するのが簡単だからです。

たとえば、

(setq alist-of-colors
      '((rose . red) (lily . white)  (buttercup . yellow)))

は、変数alist-of-colorsに、3要素の連想リストを設定します。 最初の要素では、roseがキーであり、redが値です。

連想リストとそれらを操作する関数について詳しい説明は、 See Association Lists


Node:Array Type, Next:, Previous:Cons Cell Type, Up:Programming Types

配列型

配列(array)は、任意のLispオブジェクトを指すための 任意個のスロットから成り、メモリの連続した場所に取ります。 配列のどの要素を参照しても、ほぼ同じ時間かかります。 一方、リストの要素を参照するときには、 リスト内の要素の位置に比例した時間が必要です。 (リストの末尾の要素を参照するには、 リストの先頭の要素を参照するより時間がかかる。)

Emacsには、4つの配列型、つまり、 文字列、ベクトル、ブールベクトル、文字テーブルがあります。

文字列は文字の配列であり、 ベクトルは任意のオブジェクトの配列です。 ブールベクトルは、tnilだけを保持できます。 これらの種類の配列は、最大の整数値までなら、任意の長さにできます。 文字テーブルは、正しい文字コードで添字付けする疎な配列であり、 任意のオブジェクトを保持できます。

配列の最初の要素は0で添字付けする、 2番目の要素は1で添字付けする、というようになります。 これをゼロ原点(zero-origin)の添字付けと呼びます。 たとえば、4つの要素からなる配列の添字は、0、1、2、そして、3です。 最大の添字は、配列の長さより1だけ小さくなります。 いったん配列を作成すると、その長さは固定されます。

Emacs Lispのすべての配列は1次元です。 (多くの他のプログラム言語では多次元配列を扱えるが、 それは本質的ではない。 配列の配列を作れば同じ効果を得られる。) 配列のそれぞれの型に応じて、専用の入力構文があります。 詳しくは、以下を参照してください。

配列型はシーケンス型に含まれ、 配列型は、文字型、ベクトル型、ブールベクトル型、文字テーブル型を含みます。


Node:String Type, Next:, Previous:Array Type, Up:Programming Types

文字列型

文字列(string)とは文字の配列です。 テキストエディタということから予想されるように、 Emacsではさまざまな目的に文字列を使います。 たとえば、Lispシンボルの名前として、 ユーザーへのメッセージとして、 バッファから取り出したテキストを表現するためなどです。 Lispの文字列は定数です。 つまり、文字列を評価すると同じ文字列になります。

文字列を操作する関数については、See Strings and Characters


Node:Syntax for Strings, Next:, Up:String Type

文字列の構文

文字列の入力構文は、"like this"のように、 ダブルクォートで始めて、任意個の文字を書き、ダブルクォートで終えます。 文字列の中にダブルクォートを含めるには、 バックスラッシュを直前に置きます。 つまり、"\""は、ダブルクォート1個だけから成る文字列です。 同様に、バックスラッシュを含めるには、 "this \\ is a single embedded backslash"のように、 バックスラッシュを直前に置きます。

文字列の入力構文において、改行文字は特別ではありません。 ダブルクォートのあいだに改行を書けば、 改行は文字列の文字になります。 一方、エスケープした改行、つまり、\を直前に書くと、 文字列の一部にはなりません。 すなわち、Lispリーダは、文字列を読む際にエスケープした改行を無視します。 エスケープした空白も、同様に無視します。

"It is useful to include newlines
in documentation strings,
but the newline is \
ignored if escaped."
     => "It is useful to include newlines
in documentation strings,
but the newline is ignored if escaped."


Node:Non-ASCII in Strings, Next:, Previous:Syntax for Strings, Up:String Type

文字列内の非ASCII文字

ASCIIである国際化文字を文字列に含めるには、 その文字をそのまま書きます。 Emacsの文字列(および、バッファ)では、 非ASCIIの表現方法が2つあります。 ユニバイトとマルチバイトです。 マルチバイトバッファやマルチバイト文字列、あるいは、 マルチバイトとして訪問しているファイルなどの マルチバイトのソースから文字列定数を読み取るときには、 文字をマルチバイト文字として読み取り、 マルチバイト文字列にします。 ユニバイトのソースから文字列定数を読み取るときには、 文字をユニバイト文字として読み取り、 文字列はユニバイトになります。

マルチバイトの非ASCII文字は、 必要な桁数の16進エスケープ\xnnnnnnnを用いて 書くこともできます。 (マルチバイトの非ASCII文字のコードは、256より大きい。) 16進数字として正しくない文字で16進エスケープを終端します。 16進数字の文字があとに続く場合には、(バックスラッシュと空白)と 書いて16進エスケープを終端します。 たとえば、\x8e0\ は、グレーブアクセント付きのaを表します。 文字列定数内のは、バックスラッシュ+改行と同じです。 文字列内の文字には含まれませんが、先行する16進エスケープを終えます。

マルチバイトの16進エスケープを使うと、 文字列はマルチバイトになります。 ユニバイトの非ASCIIを文字コードで表現することもできますが、 文字コードは128(8進0200)から255(8進0377)の範囲である必要があります。 こうすると、文字列はユニバイトになります。

2種類のテキストの表現方法について詳しくは、See Text Representations


Node:Nonprinting Characters, Next:, Previous:Non-ASCII in Strings, Up:String Type

文字列内の非印字文字

文字定数と同じバックスラッシュのエスケープシーケンスを文字列定数でも 使えます(ただし、文字定数を開始する疑問符は書かない)。 たとえば、コンマと空白で区切った非印字文字のタブとC-aを 含む文字列を書くには、"\t, \C-a"のようにします。 文字の入力構文については、See Character Type

しかしながら、バックスラッシュのエスケープシーケンスすべてが、 文字列において正しいとは限りません。 文字列に含めることが可能なコントロール文字は、 ASCIIコントロール文字に限ります。 文字列では、ASCIIコントロール文字の大文字小文字を区別しません。

正確にいえば、文字列はメタ文字を保持できません。 しかし、文字列をキー列として使う場合には、 文字列内のASCII文字のメタ変種を表現するための 特別な慣習があります。 文字列定数内でメタ文字を表すために\M-の構文を使うと、 文字列内のその文字に のビットを設定します。 define-keylookup-keyに文字列を使うと、 このコードは、等価なメタ文字に変換されます。 See Character Type

文字列では、ハイパー、スーパー、アルトの修飾子を保持できません。


Node:Text Props and Strings, Previous:Nonprinting Characters, Up:String Type

文字列内のテキスト属性

文字列は、文字そのものに加えて、文字の属性も保持できます。 このため、特別なことをしなくても、 文字列とバッファのあいだでテキストをコピーするプログラムは、 テキスト属性をコピーできます。 テキスト属性の意味については、See Text Properties。 テキスト属性付きの文字列には、特別な入力構文があります。

#("characters" property-data...)

ここで、property-dataは0個以上のつぎのような3つ組みです。

beg end plist

3つ組みの要素、begendは整数であり、 文字列内の添字の範囲を表します。 plistはその範囲の属性リストです。 たとえば、

#("foo bar" 0 3 (face bold) 3 4 nil 4 7 (face italic))

は、最初の3文字がface属性としてboldを持ち、 最後の3文字がface属性としてitalicを持つ、 foo barという文字列を表します。 (4番目の文字にはテキスト属性はなく、その属性リストはnil。 デフォルトでは、範囲に含まれない文字には属性はないので、 属性リストがnilであるような範囲を言及する必要はない。)


Node:Vector Type, Next:, Previous:String Type, Up:Programming Types

ベクトル型

ベクトル(vector)は、任意の型の要素から成る1次元配列です。 ベクトルの任意の要素を参照しても、それに必要な時間は一定です。 (リストでは、ある要素を参照するために必要な時間は、 リストの先頭からの距離に比例する。)

ベクトルの表示表現は、開き角括弧、要素、閉じ角括弧です。 これは、入力構文でもあります。 数や文字列と同様に、ベクトルは評価時には定数です。

[1 "two" (three)]      ; 3要素のベクトル
     => [1 "two" (three)]

ベクトルに作用する関数については、See Vectors


Node:Char-Table Type, Next:, Previous:Vector Type, Up:Programming Types

文字テーブル型

文字テーブル(char-table)は、 任意の型の要素から成る1次元配列であり、 文字コードで添字付けします。 文字テーブルには、文字コードに情報を与えるための多くの操作を簡単にする 付加的な機能があります。 たとえば、文字テーブルは、情報を継承するための親、 デフォルト値、特定目的向けの少数の追加スロットを持てます。 文字テーブルでは、文字集合全体に対して1つの値を指定することもできます。

文字テーブルの表示表現はベクトルに似ていますが、 先頭に#^が余分に付きます。

文字テーブルを操作する特別の関数については、See Char-Tables。 文字テーブルはつぎのように使います。


Node:Bool-Vector Type, Next:, Previous:Char-Table Type, Up:Programming Types

ブールベクトル型

ブールベクトル(bool-vector)は、 tnilだけの要素から成る1次元配列です。

ブールベクトルの表示表現は文字列に似ていますが、 #&と長さで始まります。 これに続く文字列定数が、ブールベクトルの実際の内容を ビットマップで表します。 つまり、文字列の『各文字』は8ビット長のデータであり、 ブールベクトルのつぎの8個の要素を表します (1はtを表し、0はnilを表す)。 文字の最下位ビットが、ブールベクトルの小さい添字に対応します。 長さが8の倍数でない場合には、 表示表現には余計な要素が含まれますが、余計な部分に意味はありません。

(make-bool-vector 3 t)
     => #&3"\007"
(make-bool-vector 3 nil)
     => #&3"\0"
;; 最初の3ビットだけを使っているので、以下はすべて同じ
(equal #&3"\377" #&3"\007")
     => t


Node:Function Type, Next:, Previous:Bool-Vector Type, Up:Programming Types

関数型

他のプログラム言語の関数が実行可能であるように、 Lisp関数(Lisp function)は実行可能なコードです。 しかしながら、Lispにおいては、関数は基本Lispオブジェクトであり、 そのテキスト表現は副次的なものです。 これらのLispオブジェクトはラムダ式です。 つまり、先頭要素がシンボルlambdaであるリストです (see Lambda Expressions)。

ほとんどのプログラム言語では、名前のない関数を書くことは不可能です。 Lispでは、本質的には、関数に名前はありません。 ラムダ式のことを無名関数(anonymous function)とも呼びます (see Anonymous Functions)。 Lispにおける名前付き関数は、実際には、 関数セルに正しい関数を収めたシンボルです (see Defining Functions)。

多くの場合、LispプログラムのLisp式中に関数名を書くと関数が呼ばれます。 しかし、実行時に関数オブジェクトを構成したり取得して、 基本関数funcallapplyで、それを呼び出すことができます。 See Calling Functions


Node:Macro Type, Next:, Previous:Function Type, Up:Programming Types

マクロ型

Lispマクロ(Lisp macro)は、 Lisp言語を拡張するユーザー定義の構造です。 関数に似たオブジェクトで表現しますが、引数渡しの意味は異なります。 Lispマクロは、リストの最初の要素がシンボルmacroであり、 リストのCDRlambdaシンボルを 含むLisp関数オブジェクトであるフォームです。

Lispマクロオブジェクトは、通常、組み込み関数defmacroで 定義しますが、 Emacsにとっては、macroで始まるリストはマクロです。 マクロの書き方の説明は、See Macros

警告 Lispマクロとキーボードマクロ (see Keyboard Macros)は、まったく別のものです。 単に『マクロ』といった場合には、Lispマクロを意味するのであって、 キーボードマクロのことではありません。


Node:Primitive Function Type, Next:, Previous:Macro Type, Up:Programming Types

基本関数型

基本関数型(primitive function)は、 Lispから呼び出し可能な関数ですが、C言語で書いてあります。 基本関数のことをsubrとか 組み込み関数(built-in functions)とも呼びます。 (『subr』は『subroutine』からきている。) ほとんどの基本関数は、呼び出すときにすべての引数を評価します。 引数すべてを評価しない基本関数をスペシャルフォーム(special form)と 呼びます(see Special Forms)。

関数を呼び出す側からすれば、関数が基本関数かどうかは関係ありません。 しかし、Lispで書いた関数で基本関数を再定義しようとすると、 問題があります。 というのは、基本関数はCのコードから直接呼ばれるからです。 再定義した関数をLispから呼び出す場合には新しい定義を使いますが、 Cのコードは組み込みの定義を使い続けるでしょう。 したがって、基本関数を再定義しないでください

関数(function)という用語で、 LispやCで書かれたEmacsのすべての関数を指します。 Lispで書いた関数に関しては、See Function Type

基本関数には入力構文はなく、 サブルーティン名を含むハッシュ記法で表示します。

(symbol-function 'car)          ; シンボルの関数セルを参照する
     => #<subr car>
(subrp (symbol-function 'car))  ; 基本関数か?
     => t                       ; そのとおり


Node:Byte-Code Type, Next:, Previous:Primitive Function Type, Up:Programming Types

バイトコード関数型

バイトコンパイラは、バイトコード関数オブジェクト (byte-code function objects)を作り出します。 内部的には、バイトコード関数オブジェクトはベクトルによく似ています。 しかしながら、評価過程においては、関数呼び出しのように見えるときには、 このデータ型を特別に扱います。 バイトコンパイラについては、See Byte Compilation

バイトコード関数オブジェクトの表示表現と入力構文は、 ベクトルに似ていますが、開き角括弧[のまえに#が付きます。


Node:Autoload Type, Previous:Byte-Code Type, Up:Programming Types

自動ロード型

自動ロードオブジェクト(autoload object)は、 先頭要素がシンボルautoloadであるリストです。 実際の定義のかわりにシンボルの関数定義として使われ、 必要なときにロードすべき実際の定義を収めたLispコードファイルを示します。 自動ロードオブジェクトには、ファイル名に加えて、 実際の関数定義に関する他の情報も入っています。

ファイルをロードし終えると、 シンボルには、自動ロードオブジェクトではない新たな関数定義が入ります。 この新たな定義を始めからあったかのように呼び出します。 ユーザーの視点からは、ロードしたファイル内の関数定義を使って、 予想どおりに関数呼び出しが行われます。

自動ロードオブジェクトは、普通、関数autoloadで作ります。 この関数は、シンボルの関数セルにオブジェクトを格納します。 より詳しくは、See Autoload


Node:Editing Types, Next:, Previous:Programming Types, Up:Lisp Data Types

編集向けの型

前節の型は一般のプログラム向けに使うもので、 そのほとんどは、ほんどのLisp方言に共通しています。 Emacs Lispには、編集に関連した目的向けにいくつかのデータ型があります。


Node:Buffer Type, Next:, Up:Editing Types

バッファ型

バッファ(buffer)は、編集可能なテキストを保持するオブジェクトです (see Buffers)。 ほとんどのバッファは、ディスクファイル(see Files)の内容を保持して 編集できるようにしますが、他の目的に使われるものもあります。 ほとんどのバッファは、ユーザーが見るためのものであり、 ある期間、ウィンドウ(see Windows)に表示されます。 しかし、バッファがいずれかのウィンドウに必ずしも表示される必要はありません。

バッファの内容は文字列によく似ていますが、 Emacs Lispにおいては、バッファは文字列のようには使われず、 適用可能な操作も異なります。 たとえば、既存のバッファにテキストを効率よく挿入できますが、 文字列にテキストを『挿入』するには、 部分文字列を連結する必要があり、まったく新しい文字列オブジェクトになります。

各バッファには、ポイント(point)と呼ばれる特別な箇所があります (see Positions)。 どんなときにも、1つのバッファがカレントバッファ(current buffer)です。 ほとんどの編集コマンドは、カレントバッファのポイント付近の内容に作用します。 多くのEmacsの標準関数は、カレントバッファ内にある文字を操作したり検査します。 本書には、これらの関数の説明にあてた章が1つあります(see Text)。

各バッファに関連付けられたデータ構造には、つぎのものがあります。

ローカルキーマップと変数リストには、 それぞれ、グローバルな束縛や値に優先するものが入っています。 これらは、プログラムを変更せずに、各バッファごとに、 プログラムのふるまいをカスタマイズするために使われます。

バッファは間接(indirect)でもよく、その場合、 別のバッファとテキストを共有しつつ異なった表示を行えます。 See Indirect Buffers

バッファには入力構文はありません。 バッファ名を含んだハッシュ記法で表示します。

(current-buffer)
     => #<buffer objects.texi>


Node:Marker Type, Next:, Previous:Buffer Type, Up:Editing Types

マーカ型

マーカ(marker)は、特定のバッファ内の位置を表します。 したがって、マーカには2つの構成要素、つまり、 バッファを示すものと位置を示すものがあります。 バッファ内のテキストを変更すると、 マーカがバッファ内の同じ2つの文字のあいだをつねに指すことを保証するように、 位置の値を更新します。

マーカには入力構文はありません。 バッファ内の文字位置とバッファ名を含んだハッシュ記法で表示します。

(point-marker)
     => #<marker at 10779 in objects.texi>

マーカの検査、作成、コピー、移動の方法については、See Markers


Node:Window Type, Next:, Previous:Marker Type, Up:Editing Types

ウィンドウ型

ウィンドウ(window)は、 Emacsがバッファを表示するために使用する端末画面の部分のことです。 各ウィンドウには、対応付けられたバッファが1つあり、 そのバッファの内容をウィンドウに表示しています。 一方、あるバッファが、1つのウィンドウや複数のウィンドウに表示されることもあり、 どのウィンドウにも表示されないこともあります。

同時に複数のウィンドウが存在できますが、 どんなときにも1つのウィンドウだけが選択されたウィンドウ (selected window)です。 これは、Emacsがコマンドを受け付け可能なときにカーソルを(通常)表示する ウィンドウです。 選択されたウィンドウは、通常、カレントバッファを表示しますが、 これは必須ではありません。

画面上のウィンドウはフレームにまとめられています。 各ウィンドウは、たった1つのフレームに属します。 See Frame Type

ウィンドウには入力構文はありません。 ウィンドウ番号と表示中のバッファ名を含んだハッシュ記法で表示します。 ウィンドウ番号は、ウィンドウを一意に識別するためにあります。 これは、ウィンドウが表示しているバッファは頻繁に変わるからです。

(selected-window)
     => #<window 1 on objects.texi>

ウィンドウを操作する関数の説明は、See Windows


Node:Frame Type, Next:, Previous:Window Type, Up:Editing Types

フレーム型

フレーム(frame)は、画面上の矩形領域であって、 1つ以上のEmacsウィンドウを含みます。 フレームには最初は1つのウィンドウ (とミニバッファウィンドウ)が含まれますが、 これを左右や上下に小さなウィンドウに分割できます。

フレームには入力構文はありません。 フレームのタイトルとメモリ内のアドレス (フレームを一意に識別するのに有用)を含んだハッシュ記法で表示します。

(selected-frame)
     => #<frame emacs@psilocin.gnu.org 0xdac80>

フレームを操作する関数の説明は、See Frames


Node:Window Configuration Type, Next:, Previous:Frame Type, Up:Editing Types

ウィンドウ構成型

ウィンドウ構成(window configuration)は、 フレーム内のウィンドウの位置/サイズ/内容に関する情報を記録し、 同じ配置のウィンドウをあとで再度作成できるようにします。

ウィンドウ構成には入力構文はありません。 表示表現は、#<window-configuration>のようになります。 ウィンドウ構成に関連した関数の説明は、See Window Configurations


Node:Frame Configuration Type, Next:, Previous:Window Configuration Type, Up:Editing Types

フレーム構成型

フレーム構成(frame configuration)は、 すべてのフレームのウィンドウの位置/サイズ/内容に関する情報の記録です。 これは、実際には、リストのCARframe-configurationであり、 リストのCDRが連想リストであるリストです。 連想リストの各要素で、そのCARに現れるフレーム1個を記述します。

フレーム構成に関連した関数の説明は、See Frame Configurations


Node:Process Type, Next:, Previous:Frame Configuration Type, Up:Editing Types

プロセス型

単語プロセス(process)は、通常、実行中のプログラムを意味します。 Emacs自身、この種のプロセスとして実行されています。 しかし、Emacs Lispでは、プロセスとは、 Emacsプロセスが作成したサブプロセスを表すLispオブジェクトのことです。 Emacsのサブプロセスで実行される、シェル、GDB、ftp、コンパイラなどの プログラムは、Emacsの能力を拡張します。

Emacsサブプロセスは、Emacsからテキスト入力を受け取り、 さらに処理できるようにEmacsにテキスト出力を返します。 Emacsはサブプロセスにシグナルを送ることもできます。

プロセスオブジェクトに入力構文はありません。 プロセス名を含んだハッシュ記法で表示します。

(process-list)
     => (#<process shell>)

プロセスを作成したり削除したり、プロセスに関する情報を返したり、 プロセスへ入力やシグナルを送ったり、プロセスから出力を受け取る 関数に関する情報は、See Processes


Node:Stream Type, Next:, Previous:Process Type, Up:Editing Types

ストリーム型

ストリーム(stream)は、文字を出し入れする対象、 つまり、入力用に文字を供給したり、出力として文字を受け取ったりといった ことに使えるオブジェクトです。 多くの異なる型をこのように使えます。 マーカ、バッファ、文字列、関数です。 ほとんどの場合、入力ストリーム(文字の供給源)は、 キーボード、バッファ、ファイルから文字を取得します。 出力ストリーム(文字の消費先)は、*Help*バッファなどのバッファや エコー領域に文字を送ります。

オブジェクトnilは、他の意味に加えて、 ストリームとしても使えます。 変数standard-inputstandard-outputの値になります。 また、オブジェクトtも、 ミニバッファ(see Minibuffers)を使う入力ストリームや エコー領域への出力(see The Echo Area)を意味します。

ストリームには表示形式も入力構文もなく、その基本型で表示します。

構文解析関数や表示関数を含むストリームに関連した関数の説明は、 See Read and Print


Node:Keymap Type, Next:, Previous:Stream Type, Up:Editing Types

キーマップ型

キーマップ(keymap)は、ユーザーが打ったキーをコマンドに対応付けます。 この対応付けは、ユーザーのコマンド入力をどのように実行するかを制御します。 キーマップは、実際には、リストであり、 そのCARはシンボルkeymapです。

キーマップの作成、プレフィックスキーの扱い方、 グローバルやローカルなキーマップ、キーバインディングの変更に関する情報は、 See Keymaps


Node:Overlay Type, Previous:Keymap Type, Up:Editing Types

オーバレイ型

オーバレイ(overlay)は、バッファのある部分に作用する属性を指定します。 各オーバレイは、バッファの指定した範囲に作用し、 属性リスト(属性名と値の要素を交互に繰り返すリスト)を含んでいます。 オーバレイ属性は、 バッファの一部を一時的に異なった方式で表示するために使われます。 オーバレイ属性に入力構文はなく、 バッファ名と位置範囲を含んだハッシュ記法で表示します。

オーバレイの作成と使用法については、See Overlays


Node:Type Predicates, Next:, Previous:Editing Types, Up:Lisp Data Types

型述語

Emacs Lispインタープリタ自身は、関数を呼び出すときに渡す実引数の 型検査を行いません。 そうできないのは、他のプログラム言語が行うようには、 Lispの関数の引数にはデータ型の宣言がないからです。 したがって、各実引数がその関数で扱える型に属するかどうかを検査するのは、 各関数の責任です。

すべての組み込み関数は、必要なときには実引数の型検査を行い、 引数が誤った型であれば、エラーwrong-type-argumentを通知します。 たとえば、+に扱えない引数を渡すと、つぎのようになります。

(+ 2 'a)
     error--> Wrong type argument: number-or-marker-p, a

読者のプログラムで、異なる型を異なるように扱いたい場合には、 明示的に型検査を行う必要があります。 オブジェクトの型を検査するもっとも一般的な方法は、 型述語(type predicate)関数を呼び出すことです。 Emacsには、各型ごとに型述語があり、 型を組み合わせたものに対する述語もあります。

型述語関数は1つの引数を取ります。 引数が適切な型に属していればtを返し、 さもなければnilを返します。 述語関数に関するLisp一般の慣習に従って、 ほとんどの型述語の名前はpで終ります。

以下は、リストの検査に述語listpを使い、 シンボルの検査に述語symbolpを使う例です。

(defun add-on (x)
  (cond ((symbolp x)
         ;; Xがシンボルならば、それをLISTに加える
         (setq list (cons x list)))
        ((listp x)
         ;; Xがリストならば、その要素をLISTに追加する
         (setq list (append x list)))
        (t
         ;; シンボルとリストだけを扱う
         (error "Invalid argument %s in add-on" x))))

定義済みの型述語を、アルファベット順に、参照先を併記してあげておきます。

atom
see atom
arrayp
see arrayp
bool-vector-p
see bool-vector-p
bufferp
see bufferp
byte-code-function-p
see byte-code-function-p
case-table-p
see case-table-p
char-or-string-p
see char-or-string-p
char-table-p
see char-table-p
commandp
see commandp
consp
see consp
display-table-p
see display-table-p
floatp
see floatp
frame-configuration-p
see frame-configuration-p
frame-live-p
see frame-live-p
framep
see framep
functionp
see functionp
integer-or-marker-p
see integer-or-marker-p
integerp
see integerp
keymapp
see keymapp
listp
see listp
markerp
see markerp
wholenump
see wholenump
nlistp
see nlistp
numberp
see numberp
number-or-marker-p
see number-or-marker-p
overlayp
see overlayp
processp
see processp
sequencep
see sequencep
stringp
see stringp
subrp
see subrp
symbolp
see symbolp
syntax-table-p
see syntax-table-p
user-variable-p
see user-variable-p
vectorp
see vectorp
window-configuration-p
see window-configuration-p
window-live-p
see window-live-p
windowp
see windowp

オブジェクトの型を調べるもっとも一般的な方法は、 関数type-ofを呼び出すことです。 各オブジェクトはたった1つの基本型に属することを思い出してください。 type-ofはどの1つかを教えてくれます(see Lisp Data Types)。 しかし、type-ofは、基本型以外についてはなにも知りません。 多くの場合、type-ofより型述語を使うほうが便利でしょう。

type-of object Function
この関数は、objectの基本型を示すシンボルを返す。 その値は、 symbolintegerfloatstringconsvectorchar-tablebool-vectorsubrcompiled-functionmarkeroverlaywindowbufferframeprocesswindow-configurationの シンボルのうちの1つ。
(type-of 1)
     => integer
(type-of 'nil)
     => symbol
(type-of '())    ; ()nil
     => symbol
(type-of '(x))
     => cons


Node:Equality Predicates, Previous:Type Predicates, Up:Lisp Data Types

同値述語

2つのオブジェクトの同値関係を調べる2つの関数を説明します。 文字列などの特定のオブジェクトが同値であるかを調べる関数群もあります。 これらの述語については、データ型を述べている適切な章を参照してください。

eq object1 object2 Function
この関数は、object1object2が 同一オブジェクトであればtを返し、さもなければnilを返す。 『同一オブジェクト』とは、 一方を変更すると、他方にも同じ変更が反映されることを意味する。

eqは、object1object2が同じ値の整数であると tを返す。 また、シンボル名は、普通、一意であるので、 引数が同じ名前のシンボルであれば、それらはeqである。 (リスト、ベクトル、文字列などの)それ以外の型の場合、 2つの引数が同じ内容や要素であっても、 互いにeqであるとは限らない。 それらが同一オブジェクトである場合に限りeqである。

(eq 'foo 'foo)
     => t

(eq 456 456)
     => t

(eq "asdf" "asdf")
     => nil

(eq '(1 (2 (3))) '(1 (2 (3))))
     => nil

(setq foo '(1 (2 (3))))
     => (1 (2 (3)))
(eq foo foo)
     => t
(eq foo '(1 (2 (3))))
     => nil

(eq [(1 2) 3] [(1 2) 3])
     => nil

(eq (point-marker) (point-marker))
     => nil

関数make-symbolは、インターンしたシンボルを返す。 このシンボルは、Lisp式に書いた同じ名前のシンボルと区別される。 名前が同じでも区別されるシンボルはeqではない。 see Creating Symbols

(eq (make-symbol "foo") 'foo)
     => nil

equal object1 object2 Function
この関数は、 object1object2が等しい要素を持てばtを返し、 さもなければnilを返す。 eqは引数が同一オブジェクトかどうかを調べるが、 equalは、同一ではない引数の内部を調べ、 それらの要素が同じかどうかを調べる。 したがって、2つのオブジェクトがeqならば、 それらはequalであるが、その逆はつねに真とは限らない。
(equal 'foo 'foo)
     => t

(equal 456 456)
     => t

(equal "asdf" "asdf")
     => t
(eq "asdf" "asdf")
     => nil

(equal '(1 (2 (3))) '(1 (2 (3))))
     => t
(eq '(1 (2 (3))) '(1 (2 (3))))
     => nil

(equal [(1 2) 3] [(1 2) 3])
     => t
(eq [(1 2) 3] [(1 2) 3])
     => nil

(equal (point-marker) (point-marker))
     => t

(eq (point-marker) (point-marker))
     => nil

文字列の比較では大文字小文字を区別するが、テキスト属性は考慮しない。 つまり、文字列内の文字だけを比較する。 文字列の内容がすべてASCIIでなければ、 ユニバイト文字列とマルチバイト文字列が等しいことはない (see Text Representations)。

(equal "asdf" "ASDF")
     => nil

たとえ内容が同じであっても、 異なる2つのバッファがequalであることはない。

equalの検査は再帰で実装されているので、 リストに循環があると無限再帰を引き起こし(エラーになり)ます。


Node:Numbers, Next:, Previous:Lisp Data Types, Up:Top

GNU Emacsでは2種類の数値データを扱えます。 整数(integers)と浮動小数点数(floating point numbers)です。 整数は、-3、0、7、13、511のようなちょうどの数です。 これらの値は正確です。 浮動小数点数は、-4.5、0.0、2.71828のように小数部がある数です。 これらは指数表記で表します。 たとえば、1.5e2は150に等しいのです。 この例のe2は10の2乗を表し、それを1.5倍します。 浮動小数点数の値は厳密ではありません。 これらの精度には定まった限界があります。


Node:Integer Basics, Next:, Up:Numbers

整数の基本

整数の値の範囲は計算機に依存します。 最小の範囲は、-134217728から134217727まで(28ビット長、つまり から これより広い範囲を扱える計算機もあります。 本章の多くの例題では、整数は28長ビットであると仮定します。

Lispリーダは、 先頭に符号があってもよく、最後にピリオドがあってもよい、 数字の列として整数を読み取ります。

 1               ; 整数1
 1.              ; 整数1
+1               ; これも整数1
-1               ; 整数-1
 268435457       ; 桁溢れのため、これも整数1
 0               ; 整数0
-0               ; 整数0

整数を扱うさまざまな関数を理解するには、 特にビット演算(see Bitwise Operations)を理解するには、 数を2進表現で考えるとよいです。

28ビット長の2進表現では、10進整数5はつぎのようになります。

0000  0000 0000  0000 0000  0000 0101

(4ビットのまとまりごとに空白を1個、 8ビットのまとまりごとに空白を2個挿入して、読みやすくする。)

整数-1はつぎのようになります。

1111  1111 1111  1111 1111  1111 1111

-1は、28個の1で表現されます。 (これを2の補数(two's complement)表記と呼ぶ。)

負の数-5は、-1から4を引いて作れます。 10進数4は、2進表記では100です。 したがって、-5は、つぎのようになります。

1111  1111 1111  1111 1111  1111 1011

この実装では、28ビット長の2進整数の最大値は、 10進で134,217,727になります。 2進表記では、つぎのようになります。

0111  1111 1111  1111 1111  1111 1111

算術関数は、整数がその範囲外に出たかどうか検査しないので、 134,217,727に1を足すと、値は負の数-134,217,728になります。

(+ 1 134217727)
     => -134217728
     => 1000  0000 0000  0000 0000  0000 0000

本章で述べる多くの関数は、数の引数としてマーカを受け付けます。 (see Markers)。 そのような関数の実際の引数は数かマーカであるので、 それらの引数をしばしばnumber-or-markerという名前で書きます。 引数の値がマーカであるときには、その位置の値を使いバッファは無視します。


Node:Float Basics, Next:, Previous:Integer Basics, Up:Numbers

浮動小数点数の基本

浮動小数点数は、整数ではない数を表現するのに便利です。 浮動小数点数の正確な範囲は計算機に依存します。 使用している計算機のC言語のデータ型doubleの範囲と同じです。

浮動小数点数の入力構文は、小数点(に続けて1桁以上の小数部)または指数、 あるいは、その両方が必要です。 たとえば、1500.015e215.0e21.5e3.15e4は、同じ1500という値の 浮動小数点数を書き表す5つの方法です。 どれも、まったく等価です。 負の浮動小数点数を書くには、-1.0のようにマイナス符号を使います。

現代の計算機はIEEEの浮動小数点数規格に基づいています。 この規格では、浮動小数点数の値には正の無限大と負の無限大があります。 また、NaNすなわち『非数値』(not-a-number)と呼ばれる値の種類もあります。 算術関数は、正しい答えがないときには、このような値を返します。 たとえば、(sqrt -1.0)はNaNを返します。 実用的には、Emacs Lispでは異なるNaNの値に重要な違いはなく、 特定の場面で正確にはどのNaNの値を使うかの規則もないので、 Emacs Lispではそれらを区別しようとはしません。 浮動小数点数の入力構文はつぎのとおりです。

正の無限大
1.0e+INF
負の無限大
-1.0e+INF
非数値
0.0e+NaN

さらに、IEEEの浮動小数点数では値-0.0を普通のゼロと区別します (しかし、equal=は、これらを等しい値と扱う)。

浮動小数点数の2進指数を取り出すには(あるいは、整数の対数を予測するには)、 logbを使います。

logb number Function
この関数はnumberの2進指数を返す。 より正確には、その値はnumberの2を底とする対数を整数に切り下げたもの。
(logb 10)
     => 3
(logb 10.0e20)
     => 69


Node:Predicates on Numbers, Next:, Previous:Float Basics, Up:Numbers

数向けの型述語

本節の関数は、引数が数であるか、とか、特定の種類の数であるか検査します。 関数integerpfloatpは 引数として任意の型のLispオブジェクトを取ります (さもないと、述語の利用価値がない)。 しかし、述語zeropの引数には数が必要です。 Predicates on Markersinteger-or-marker-pnumber-or-marker-pも 参照してください。

floatp object Function
この述語は、引数が浮動小数点数かどうか調べ、 そうならばtを返し、さもなければnilを返す。

Emacs 18以前の版にはfloatpはない。

integerp object Function
この述語は、引数が整数かどうか調べ、 そうならばtを返し、さもなければnilを返す。

numberp object Function
この述語は、引数が数(整数か浮動小数点数)かどうか調べ、 そうならばtを返し、さもなければnilを返す。

wholenump object Function
(『whole-number-p』からきている名前の)述語wholenumpは、 引数が非負整数かどうか調べ、 そうならばtを返し、さもなければnilを返す。 0は非負整数として扱う。

natnumpは、wholenumpの廃れた同義語。

zerop number Function
この述語は、引数が0かどうか調べ、 そうならばtを返し、さもなければnilを返す。 引数は数であること。

つぎの2つのフォームは等価。 (zerop x) == (= x 0)


Node:Comparison of Numbers, Next:, Previous:Predicates on Numbers, Up:Numbers

数の比較

2つの数が数値的に等しいかどうか調べるには、普通、 eqではなく=を使うべきです。 数値的には等しい多くの異なる浮動小数点数が存在しえます。 それらの比較にeqを使うと、 2つの値が同一オブジェクトかどうか調べることになります。 対照的に、=はオブジェクトの数値だけを比較します。

現時点では、Emacs Lispにおいて、各整数値は一意なLispオブジェクトです。 したがって、整数に限ればeq=と等価です。 未知の値と整数を比較するためにeqを使うと便利な場面があります。 というのは、eqは任意の型の引数を受け付けるので、 eqは未知の値が数でなくてもエラーを報告しないからです。 対照的に、=は、引数が数やマーカでないと、エラーを通知します。 しかしながら、Emacsの将来の版で整数の表現方法を変更する場合に備えて、 整数を比較するときであっても、可能ならば、=を使うほうがよいでしょう。

equalで数を比較したほうが便利なこともあります。 equalは、2つの数が同じデータ型 (どちらも整数であるか、どちらも浮動小数点数である)で、 同じ値であれば、2つの数を等しいと扱います。 一方、=は、整数と浮動小数点数が等しいことを扱えます。

別のことがらもあります。 浮動小数点数演算は厳密ではないので、 2つの浮動小数点数が等しいかどうか調べるのは正しくありません。 普通、近似的に等しいことを調べるほうがよいのです。 つぎの関数はそのようにします。

(defvar fuzz-factor 1.0e-6)
(defun approx-equal (x y)
  (or (and (= x 0) (= y 0))
      (< (/ (abs (- x y))
            (max (abs x) (abs y)))
         fuzz-factor)))
Common Lispに関した注意: Common Lispでは、数の比較にはつねに=を使う必要がある。 というのは、Common Lispでは複数ワードの整数を実装しているため、 2つの異なる整数オブジェクトが同じ数値を表すことがありえる。 Emacs Lispでは、整数値の範囲が制限されているため、 任意の値の整数オブジェクトはそれぞれ1つしかない。

= number-or-marker1 number-or-marker2 Function
この関数は、引数が数値的に等しいか調べ、 そうならばtを返し、さもなければnilを返す。

/= number-or-marker1 number-or-marker2 Function
この関数は、引数が数値的に等しいか調べ、 等しくなければtを返し、等しければnilを返す。

< number-or-marker1 number-or-marker2 Function
この関数は、第1引数が第2引数より小さいか調べ、 そうならばtを返し、さもなければnilを返す。

<= number-or-marker1 number-or-marker2 Function
この関数は、第1引数が第2引数より小さいか、あるいは、等しいか調べ、 そうならばtを返し、さもなければnilを返す。

> number-or-marker1 number-or-marker2 Function
この関数は、第1引数が第2引数より大きいか調べ、 そうならばtを返し、さもなければnilを返す。

>= number-or-marker1 number-or-marker2 Function
この関数は、第1引数が第2引数より大きいか、あるいは、等しいか調べ、 そうならばtを返し、さもなければnilを返す。

max number-or-marker &rest numbers-or-markers Function
この関数は、引数の中で最大のものを返す。
(max 20)
     => 20
(max 1 2.5)
     => 2.5
(max 1 3 2.5)
     => 3

min number-or-marker &rest numbers-or-markers Function
この関数は、引数の中で最小のものを返す。
(min -4 1)
     => -4

abs number Function
この関数は、numberの絶対値を返す。


Node:Numeric Conversions, Next:, Previous:Comparison of Numbers, Up:Numbers

数の変換

整数を浮動小数点数に変換するには、 関数floatを使います。

float number Function
この関数は、浮動小数点数に変換したnumberを返す。 numberがすでに浮動小数点数ならば、 floatnumberを変更せずに返す。

浮動小数点数を整数に変換する関数は4つあります。 これらの関数は、整数も引数に取りますが、整数引数は変更せずに返します。

truncate number Function
これは、0に向けて切り捨てて整数に変換したnumberを返す。

floor number &optional divisor Function
これは、(負の無限大に向けて)切り下げて整数に変換したnumberを返す。

divisorを指定すると、切り下げるまえに numberdivisorで除算する。 これには、modに対応した除算を使い切り下げる。 divisorが0であると、結果はarith-errorになる。

ceiling number Function
これは、(正の無限大に向けて)切り上げて整数に変換したnumberを返す。

round number Function
これは、もっとも近い整数に丸めて整数に変換したnumberを返す。 2つの整数に等距離にある値を丸める場合には、 使用している計算機に依存して、ゼロに近いほうの整数を選ぶか偶数を選ぶ。


Node:Arithmetic Operations, Next:, Previous:Numeric Conversions, Up:Numbers

算術演算

Emacs Lispには、伝統的な四則演算、加算、減算、乗算、除算があります。 除算関数を補う、余りと剰余の関数もあります。 Lispの伝統でもあり、また、多用するので、1を加算したり減算する関数もあります。

これらの関数は、%を除いて、引数が1つでも浮動小数点数であると、 浮動小数点数を返します。

Emacs Lispでは、算術関数は桁溢れ(オーバフロー)を検査しないことに 注意してください。 つまり、読者の計算機に依存しますが、 (1+ 134217727)を評価すると-134217728になる場合もあります。

1+ number-or-marker Function
この関数は、number-or-marker足す1を返す。
(setq foo 4)
     => 4
(1+ foo)
     => 5

この関数はC言語の演算子++の類似ではない。 つまり、変数を増加しない。 したがって、つぎのようになる。

foo
     => 4

変数を増加するには、つぎのようにsetqを使う必要がある。

(setq foo (1+ foo))
     => 5

1- number-or-marker Function
この関数は、number-or-marker引く1を返す。

+ &rest numbers-or-markers Function
この関数は、引数をすべて加算する。 引数を指定しないと+は0を返す。
(+)
     => 0
(+ 1)
     => 1
(+ 1 2 3 4)
     => 10

- &optional number-or-marker &rest more-numbers-or-markers Function
関数-は、2つの役割、つまり、符号反転と減算を果たす。 -に1つの引数を指定すると、 その値は、引数の符号を反転したものである。 複数個の引数を指定すると、-は、 number-or-markerからmore-numbers-or-markersの1つ1つを減算する。 引数を指定しないと結果は0である。
(- 10 1 2 3 4)
     => 0
(- 10)
     => -10
(-)
     => 0

* &rest numbers-or-markers Function
この関数は、引数をすべて掛け合わせた乗算結果を返す。 引数を指定しないと*は1を返す。
(*)
     => 1
(* 1)
     => 1
(* 1 2 3 4)
     => 24

/ dividend divisor &rest divisors Function
この関数は、dividenddivisorで除し商を返す。 追加の引数divisorsを指定してあると、 dividenddivisorsの1つ1つで除す。 各引数は数かマーカである。

すべての引数が整数である場合、結果も整数となる。 つまり、結果は切り捨てになる。 ほとんどの計算機では各除算の結果は0に向けて切り捨てになるが、 負の引数を別の方法で丸める計算機もある。 これは、Lisp関数/をC言語の除算演算子で実装しているからであり、 C言語の除算演算子では計算機依存に丸めることを許しているからである。 実用上、すべての既知の計算機は標準的な方法で丸める。

整数を0で除算すると、エラーarith-errorを通知する。 (see Errors。) 浮動小数点数を0で除算すると、IEEE浮動小数点数を使う計算機では、 無限大かNaNを返す。 さもなければエラーarith-errorを通知する。

(/ 6 2)
     => 3
(/ 5 2)
     => 2
(/ 5.0 2)
     => 2.5
(/ 5 2.0)
     => 2.5
(/ 5.0 2.0)
     => 2.5
(/ 25 3 2)
     => 4
(/ -17 6)
     => -2

原理的には、(/ -17 6)が-3になる計算機もある。

% dividend divisor Function
この関数は、dividenddivisorで除したあとの整数の余りを返す。 引数は整数かマーカである必要がある。

負の引数では、余りは原理的に計算機依存である。 実用上、すべての既知の計算機は同じようにふるまう。

divisorが0であるとarith-errorになる。

(% 9 4)
     => 1
(% -9 4)
     => -1
(% 9 -4)
     => 1
(% -9 -4)
     => -1

2つの任意の整数dividenddivisorにおいて、

(+ (% dividend divisor)
   (* (/ dividend divisor) divisor))

は、つねにdividendに等しい。

mod dividend divisor Function
この関数は、dividenddivisorによる剰余を返す。 いいかえれば、dividenddivisorで除した余りを返す。 ただし、その符号はdivisorと同じ。 引数は数かマーカである必要がある。

%と違い、 modは負の引数に対しても厳密に定義された結果を返す。 浮動小数点の引数も許す。 商を(負の無限大に向けて)切り下げて整数にし、 その商を用いて余りを計算する。

divisorが0であるとarith-errorになる。

(mod 9 4)
     => 1
(mod -9 4)
     => 3
(mod 9 -4)
     => -3
(mod -9 -4)
     => -1
(mod 5.5 2.5)
     => .5

2つの任意の整数dividenddivisorにおいて、

(+ (mod dividend divisor)
   (* (floor dividend divisor) divisor))

は、つねにdividendに等しい。 ただし、どちらかの引数が浮動小数点数の場合には、 丸め誤差の範囲内で等しい。 floorについては、Numeric Conversionsを参照。


Node:Rounding Operations, Next:, Previous:Arithmetic Operations, Up:Numbers

丸め演算

関数、ffloorfceilingfroundftruncateは、 浮動小数点数引数を受け取り、その値に近い整数を値とする浮動小数点数を返します。 ffloorは、もっとも近いより小さな整数を返します。 fceilingは、もっとも近いより大きな整数を返します。 ftruncateは、0に向けて切り捨てたもっとも近い整数を返します。 froundは、もっとも近い整数を返します。

ffloor float Function
この関数は、floatをこれより小さな整数値に切り下げ、 その値を浮動小数点数として返す。

fceiling float Function
この関数は、floatをこれより大きな整数値に切り上げ、 その値を浮動小数点数として返す。

ftruncate float Function
この関数は、floatを0に向けて整数値に切り捨て、 その値を浮動小数点数として返す。

fround float Function
この関数は、floatをもっとも近い整数値に丸め、 その値を浮動小数点数として返す。


Node:Bitwise Operations, Next:, Previous:Rounding Operations, Up:Numbers

整数のビット演算

計算機内部では、整数は2進数、つまり、 ビット(bit、各桁は0か1)列で表現されます。 ビット演算は、そのようなビット列の各ビットごとに作用します。 たとえば、シフト(shifting)は、ビット列を全体として左や右に 1桁以上移動して、その『移動後の』パターンを結果とします。

Emacs Lispにおけるビット演算は整数に限ります。

lsh integer1 count Function
論理シフト(logical shift)の略からきているlshは、 integer1のビット列をcount桁左へ、 あるいは、countが負ならば右へずらし、空いたビットには0を詰める。 countが負であれば、lshは最左(最上位)ビットに0を詰め、 integer1が負であっても結果は正になる。 これと対照的なのが下のash

lshの例を2つ示す。 ビットパターンを1桁左へずらす。 ビットパターンの上位ビットはすべて0なので下位8ビットだけを示す。

(lsh 5 1)
     => 10
;; 10進数5は、 10進数10になる
00000101 => 00001010

(lsh 7 1)
     => 14
;; 10進数7は、10進数14になる
00000111 => 00001110

例からわかるように、ビットパターンを1桁左へずらすと、 もとの数値の2倍の数になる。

ビットパターンを2桁左へずらすと、(8ビット長の2進数では)つぎのようになる。

(lsh 3 2)
     => 12
;; 10進数3は、10進数12になる
00000011 => 00001100

一方、右へずらすとつぎのようになる。

(lsh 6 -1)
     => 3
;; 10進数6は、10進数3になる
00000110 => 00000011

(lsh 5 -1)
     => 2
;; 10進数5は、10進数2になる
00000101 => 00000010

例からわかるように、ビットパターンを1桁右へずらすと、 正の整数の数を2で除して切り下げる。

Emacs Lispのすべての算術関数と同様に、 関数lshは桁溢れ(オーバフロー)を検査しないので、 左へずらすと上位ビットを捨てさり数の符号を変えてしまうことがある。 たとえば、28ビット長の計算機では、 134,217,727を左へずらすと-2になる。

(lsh 134217727 1)          ; 左シフト
     => -2

28ビット長の実装の2進数では、引数はつぎのようになっている。

;; 10進数134,217,727
0111  1111 1111  1111 1111  1111 1111

これを左へずらすと、つぎのようになる

;; 10進数-2
1111  1111 1111  1111 1111  1111 1110

ash integer1 count Function
ash算術シフト(arithmetic shift))は、 integer1のビットをcount桁左へ、あるいは、 countが負ならば右へずらす。

ashlshと同じ結果になるが、 integer1countの両者が負の場合を除く。 この場合、ashは左の空いたビットには1を入れるが、 lshはそのようなビットには0を入れる。

したがって、ashでビットパターンを1桁右へずらすとつぎのようになる。

(ash -6 -1) => -3
;; 10進数-6は、10進数-3になる
1111  1111 1111  1111 1111  1111 1010
     =>
1111  1111 1111  1111 1111  1111 1101

対照的に、lshでビットパターンを1桁右へずらすとつぎのようになる。

(lsh -6 -1) => 134217725
;; 10進数-6は、10進数134,217,725になる
1111  1111 1111  1111 1111  1111 1010
     =>
0111  1111 1111  1111 1111  1111 1101

他の例を以下にしめす。

                   ;               28ビット2進値

(lsh 5 2)          ;   5  =  0000  0000 0000  0000 0000  0000 0101
     => 20         ;      =  0000  0000 0000  0000 0000  0001 0100
(ash 5 2)
     => 20
(lsh -5 2)         ;  -5  =  1111  1111 1111  1111 1111  1111 1011
     => -20        ;      =  1111  1111 1111  1111 1111  1110 1100
(ash -5 2)
     => -20
(lsh 5 -2)         ;   5  =  0000  0000 0000  0000 0000  0000 0101
     => 1          ;      =  0000  0000 0000  0000 0000  0000 0001
(ash 5 -2)
     => 1
(lsh -5 -2)        ;  -5  =  1111  1111 1111  1111 1111  1111 1011
     => 4194302    ;      =  0011  1111 1111  1111 1111  1111 1110
(ash -5 -2)        ;  -5  =  1111  1111 1111  1111 1111  1111 1011
     => -2         ;      =  1111  1111 1111  1111 1111  1111 1110

logand &rest ints-or-markers Function
この関数は引数の『論理積』を返す。 つまり、すべての引数のn番目のビットが1である場合に限り、 結果のn番目のビットも1になる。

たとえば、4ビットの2進数で考えると、 13と12の『論理積』は12になる。 つまり、1101に1100を組み合わせると1100になる。 どちらの2進数も最左の2ビットは1なので、戻り値の最左の2ビットも1になる。 しかし、最右の2ビットは、一方の引数ではそれぞれが0なので、 戻り値の最右の2ビットも0になる。

したがって、つぎのとおり。

(logand 13 12)
     => 12

logandにまったく引数を指定しないと値-1を返す。 この数は2進表現ではすべて1だけなので、 logandの恒等元である。 logandに引数を1つだけ指定するとその引数を返す。

                   ;                28ビット2進値

(logand 14 13)     ; 14  =  0000  0000 0000  0000 0000  0000 1110
                   ; 13  =  0000  0000 0000  0000 0000  0000 1101
     => 12         ; 12  =  0000  0000 0000  0000 0000  0000 1100

(logand 14 13 4)   ; 14  =  0000  0000 0000  0000 0000  0000 1110
                   ; 13  =  0000  0000 0000  0000 0000  0000 1101
                   ;  4  =  0000  0000 0000  0000 0000  0000 0100
     => 4          ;  4  =  0000  0000 0000  0000 0000  0000 0100

(logand)
     => -1         ; -1  =  1111  1111 1111  1111 1111  1111 1111

logior &rest ints-or-markers Function
この関数は引数の『論理和』を返す。 つまり、少なくともどれか1つの引数のn番目のビットが1である場合に限り、 結果のn番目のビットも1になる。 引数を指定しないと0を返すが、これはこの演算の恒等元である。 logiorに引数を1つだけ指定するとその引数を返す。
                   ;                28ビット2進値

(logior 12 5)      ; 12  =  0000  0000 0000  0000 0000  0000 1100
                   ;  5  =  0000  0000 0000  0000 0000  0000 0101
     => 13         ; 13  =  0000  0000 0000  0000 0000  0000 1101

(logior 12 5 7)    ; 12  =  0000  0000 0000  0000 0000  0000 1100
                   ;  5  =  0000  0000 0000  0000 0000  0000 0101
                   ;  7  =  0000  0000 0000  0000 0000  0000 0111
     => 15         ; 15  =  0000  0000 0000  0000 0000  0000 1111

logxor &rest ints-or-markers Function
この関数は引数の『排他的論理和』を返す。 つまり、引数のn番目のビットが1であるものが奇数個の場合に限り、 結果のn番目のビットも1になる。 引数を指定しないと0を返すが、これはこの演算の恒等元である。 logxorに引数を1つだけ指定するとその引数を返す。
                   ;               28ビット2進値

(logxor 12 5)      ; 12  =  0000  0000 0000  0000 0000  0000 1100
                   ;  5  =  0000  0000 0000  0000 0000  0000 0101
     => 9          ;  9  =  0000  0000 0000  0000 0000  0000 1001

(logxor 12 5 7)    ; 12  =  0000  0000 0000  0000 0000  0000 1100
                   ;  5  =  0000  0000 0000  0000 0000  0000 0101
                   ;  7  =  0000  0000 0000  0000 0000  0000 0111
     => 14         ; 14  =  0000  0000 0000  0000 0000  0000 1110

lognot integer Function
この関数は引数の論理的な補数を返す。 つまり、integern番目のビットが0である場合に限り、 結果のn番目のビットは1になる。
(lognot 5)
     => -6
;;  5  =  0000  0000 0000  0000 0000  0000 0101
;; becomes
;; -6  =  1111  1111 1111  1111 1111  1111 1010


Node:Math Functions, Next:, Previous:Bitwise Operations, Up:Numbers

標準数学関数

これらの数学関数は浮動小数点数に加えて整数も引数として受け付けます。

sin arg Function
cos arg Function
tan arg Function
これらは普通の三角関数であり、引数は弧度法で表す。

asin arg Function
(asin arg)の値は-pi/2からpi/2までの数であり、 その正弦(sin)はargに等しい。 しかし、argが([-1, 1]の)範囲を越えていると結果はNaN。

acos arg Function
(acos arg)の値は0からpiまでの数であり、 その余弦(cos)はargに等しい。 しかし、argが([-1, 1]の)範囲を越えていると結果はNaN。

atan arg Function
(atan arg)の値は-pi/2からpi/2までの数であり、 その正接(tan)はargに等しい。

exp arg Function
これは指数関数であり、 のarg乗を返す。 は数学の基本定数であり、自然対数の底とも呼ぶ。

log arg &optional base Function
この関数はargbaseを底とする対数を返す。 baseを指定しなければ、底として を使う。 argが負であると結果はNaN。

log10 arg Function
この関数はargの10を底とする対数を返す。 argが負であると結果はNaN。 少なくとも誤差を考慮すれば、 (log10 x) == (log x 10)

expt x y Function
この関数はxy乗を返す。 どちらの引数も整数でありyが正ならば、結果は整数。 この場合、結果は整数値の可能な範囲に切り詰められる。

sqrt arg Function
この関数はargの平方根を返す。 argが負であると値はNaN。


Node:Random Numbers, Previous:Math Functions, Up:Numbers

乱数

決定論的な計算機プログラムは真の乱数を発生できません。 しかし、ほとんどの目的には疑似乱数(pseudo-random numbers)で十分です。 一連の疑似乱数を決定論的な方法で生成します。 それらの数は真の乱数ではありませんが、 乱数列のある種の性質に似た性質があります。 たとえば、疑似乱数列でもすべての可能な数がしばしば等しく生起します。

Emacsでは、疑似乱数は『種』となる数から生成します。 指定した任意の種から始めても、関数randomは同じ数の列を生成します。 Emacsはつねに同じ種の値で計算し始めるため、 それぞれのEmacsの実行でもrandomは実際には同じ数の列を生成します。 たとえば、あるオペレーティングシステムで、 Emacs開始直後にrandomを呼ぶとつねに-1457731を返し、 つぎに呼ぶとつねに-7692030を返します。 このような再現性はデバッグには有利です。

予測不可能な乱数が必要ならば(random t)を実行します。 これは、現在時刻とEmacsプロセスのID番号に基づいて、 新たな種の値を選びます。

random &optional limit Function
この関数は疑似乱数の整数を返す。 繰り返し呼び出すと一連の疑似乱数の整数を返す。

limitが正整数ならば、非負でlimit未満になるように値を選ぶ。

limittならば、 現在時刻とEmacsプロセスのID番号に基づいて、 新たな種の値を選ぶことを意味する。

randomの結果は、Lispにおいて表現可能な任意の整数になる計算機もある。 他の計算機では、結果はある最大値と(負数)最小値のあいだにある。


Node:Strings and Characters, Next:, Previous:Numbers, Up:Top

文字列と文字

Emacs Lispの文字列は文字の順序列を保持している配列です。 文字列は、シンボル、バッファ、ファイルのそれぞれの名前として、 ユーザーへメッセージを送るため、 バッファ間でコピーするテキストを保持するため、 その他さまざまな目的に使われます。 文字列はとても重要なので、 Emacs Lispには文字列を操作する関数が数多くあります。 Emacs Lispのプログラムでは、個々の文字よりも文字列を多用します。

キーボード文字イベントを表す文字列に関する特別な配慮については、 See Strings of Events


Node:String Basics, Next:, Up:Strings and Characters

文字列と文字の基本

Emacs Lispの文字列は文字の順序列を保持している配列です。 Emacs Lispでは文字を整数で表現します。 整数が文字であるかどうかは、その使われ方からしか判断できません。 したがって、文字列は、実際には、整数群を保持しているのです。

(任意の配列と同様に)文字列の長さは固定されていて、 文字列をいったん作成すると変更できません。 Lispの文字列は特別な文字コードで終端されるのではありません。 (対照的に、C言語の文字列はASCIIコード0で終端される。)

文字列は配列ですからシーケンスでもあり、 一般の配列関数やシーケンス関数で文字列を操作できます。 (see Sequences Arrays Vectors。) たとえば、関数arefaset(see Array Functions)を 用いて、文字列内の個々の文字を参照したり変更できます。

Emacs文字列(およびバッファ)内の非ASCII文字のテキスト表現は 2種類あります。 ユニバイトとマルチバイトです(see Text Representations)。 ASCII文字は、文字列内ではつねに1バイトを占めます。 実際、すべてがASCII文字である文字列では、2つの表現に違いはありません。 ほとんどのLispプログラムでは、 読者はこれらの2つの表現を考慮する必要はないでしょう。

キー列を文字列として表現することがあります。 文字列がキー列を表す場合、128から255の範囲にある文字列の要素は、 その範囲の文字コードとしてではなく、 (非常に大きな整数になる)メタ文字を表現します。

文字列は、ハイパー、スーパー、アルトの修飾子を持つ文字を保持できません。 文字列はASCIIコントロール文字を保持できますが、 それ以外のコントロール文字を保持できません。 文字列では、ASCIIコントロール文字の大文字小文字を区別できません。 キー列などのそのような文字をシーケンスに収めるには、 文字列のかわりにベクトルを使う必要があります。 キーボード入力文字に対するメタなどの修飾子の表現については、 See Character Type

文字列は正規表現を保持するのにも便利です。 文字列に対して正規表現の一致を取ることもできます(see Regexp Search)。 関数match-string(see Simple Match Data)と replace-match(see Replacing Match)は、 正規表現の一致に基づいて文字列を分解したり変更するのに便利です。

バッファと同様に、文字列は、 文字そのものに加えて文字列内の文字に対するテキスト属性を保持できます。 See Text Properties。 文字列からバッファや他の文字列へテキストをコピーするすべてのLisp基本関数は、 コピーする文字の属性もコピーします。

文字列を表示したりバッファへコピーする関数については、See Text。 文字と文字列の構文については、Character TypeとSee String Type。 テキスト表現を変換したり、文字コードを符号化/復号化する関数については、 See Non-ASCII Characters


Node:Predicates for Strings, Next:, Previous:String Basics, Up:Strings and Characters

文字列向けの述語

一般のシーケンスや配列に対する述語について詳しくは、 Sequences Arrays VectorsとSee Arrays

stringp object Function
この関数は、objectが文字列ならばtを返し、 さもなければnilを返す。

char-or-string-p object Function
この関数は、objectが文字列か文字(つまり、整数)ならば tを返し、さもなければnilを返す。


Node:Creating Strings, Next:, Previous:Predicates for Strings, Up:Strings and Characters

文字列の作成

以下の関数は、新たに文字列を作成したり、 文字列を連結したり分解して文字列を作成します。

make-string count character Function
この関数は、文字charactercount回繰り返して作成した文字列を返す。 countが負であるとエラーを通知する。
(make-string 5 ?x)
     => "xxxxx"
(make-string 0 ?x)
     => ""

この関数に対比するものに、 char-to-string(see String Conversion)、 make-vector(see Vectors)、 make-list(see Building Lists)などがある。

string &rest characters Function
これは、複数個の文字群charactersが入った文字列を返す。
(string ?a ?b ?c)
     => "abc"

substring string start &optional end Function
この関数は、stringstartから end(の直前)までの範囲にある文字から成る新たな文字列を返す。 先頭の文字を0で添字付けする。
(substring "abcdefg" 0 3)
     => "abc"

ここで、aの添字は0、bの添字は1、cの添字は2である。 したがって、文字列"abcdefg"から3文字abcをコピーする。 添字3はコピーする部分文字列の境界の文字位置を表す。 添字が3である文字は、実際には文字列内の4番目の文字である。

負の数は文字列の末尾から数える。 したがって、-1は文字列の最後の文字の添字である。 たとえば、

(substring "abcdefg" -3 -1)
     => "ef"

この例では、eの添字は-3、fの添字は-2、 gの添字は-1である。 したがって、efを含むがgは含まない。

添字にnilを使うと、文字列の長さを意味する。 したがって、つぎのようになる。

(substring "abcdefg" -3 nil)
     => "efg"

引数endを省略することは、nilを指定することと等価である。 そのため、(substring string 0)は、 string全体をコピーしたものを返す。

(substring "abcdefg" 0)
     => "abcdefg"

しかし、このような目的にはcopy-sequenceを勧める (see Sequence Functions)。

stringからコピーした文字にテキスト属性があれば、 新たな文字列にもそのテキスト属性をコピーする。 see Text Properties

substringは第1引数としてベクトルも受け付ける。 たとえば、つぎのとおり。

(substring [a b (c) "d"] 1 3)
     => [b (c)]

startendが整数でもnilでもないと、 エラーwrong-type-argumentを通知する。 startendよりうしろの文字を指していたり、 いずれかの整数がstringの範囲外であると エラーargs-out-of-rangeを通知する。

この関数と対照的なのがbuffer-substring (see Buffer Contents)であり、 カレントバッファ内のテキストの一部を収めた文字列を返す。 文字列の先頭は0で添字付けするが、バッファの先頭は1で添字付けする。

concat &rest sequences Function
この関数は、渡した引数の文字から成る (テキスト属性があればそれも含めて)新たな文字列を返す。 引数は、文字列、数のリスト、数のベクトルである。 引数自身は変更しない。 concatに引数を指定しないと空文字列を返す。
(concat "abc" "-def")
     => "abc-def"
(concat "abc" (list 120 121) [122])
     => "abcxyz"
;; nilは空シーケンス
(concat "abc" nil "-def")
     => "abc-def"
(concat "The " "quick brown " "fox.")
     => "The quick brown fox."
(concat)
     => ""

関数concatは、 既存の文字列とeqではない新たな文字列をつねに作り出す。

引数が(整数のシーケンスではなく)整数であると、 その整数の表示表現を構成する文字列に変換する。 この機能を使わないでほしい。 削除する予定である。 読者がこの機能を使っていたら、今すぐプログラムを直すこと! 整数をこのような10進数に変換する正しい方法は、 format(see Formatting Strings)や number-to-string(see String Conversion)を使うことである。

(concat 137)
     => "137"
(concat 54 321)
     => "54321"

他の連結関数については、 Mapping FunctionsmapconcatVectorsvconcatBuilding Listsappendを参照。

split-string string separators Function
stringを正規表現separatorsの一致箇所で区切って 部分文字列に分解する。 separatorsに一致するそれぞれの部分が分割箇所を定義する。 分割箇所のあいだにある部分文字列をリストにまとめ、これを値とする。 separatorsnilである(つまり、省略する)と、 デフォルトは"[ \f\t\n\r\v]+"である。

たとえば、つぎのようになる。

(split-string "Soup is good food" "o")
=> ("S" "up is g" "" "d f" "" "d")
(split-string "Soup is good food" "o+")
=> ("S" "up is g" "d f" "d")

文字列の先頭や末尾で一致した場合には、 リストの先頭や末尾に空文字列は現れない。

(split-string "out to moo" "o+")
=> ("ut t" " m")

空の一致箇所は、それらが連続していない限り分割点になる。

(split-string "Soup is good food" "o*")
=>("S" "u" "p" " " "i" "s" " " "g" "d" " " "f" "d")
(split-string "Nice doggy!" "")
=>("N" "i" "c" "e" " " "d" "o" "g" "g" "y" "!")


Node:Modifying Strings, Next:, Previous:Creating Strings, Up:Strings and Characters

文字列の変更

既存の文字列の内容を変更するもっとも基本的な方法は、 aset(see Array Functions)を使うことです。 (aset string idx char)は、 stringの添字idx位置にcharを格納します。 各文字は1バイト以上を占めます。 charが必要とするバイト数が指定した添字位置の文字が占めるバイト数と 異なる場合には、asetはエラーを通知します。

より強力な関数はstore-substringです。

store-substring string idx obj Function
この関数は、文字列stringの添字idx位置から始まる部分にobjを 格納することで、文字列stringの内容の一部分を変更する。 引数objは文字であるか(より小さな)文字列。

既存の文字列の長さを変更することは不可能なので、 新たな文字に必要なバイト数がstringの当該箇所の文字のバイト数と 異なるなどして、 objstringの実際の長さに収まらないときにはエラーである。


Node:Text Comparison, Next:, Previous:Modifying Strings, Up:Strings and Characters

文字と文字列の比較

char-equal character1 character2 Function
この関数は、引数が同じ文字を表していればtを返し、 さもなければnilを返す。 case-fold-searchnil以外であると、 この関数は大文字小文字の違いを区別しない。
(char-equal ?x ?x)
     => t
(let ((case-fold-search nil))
  (char-equal ?x ?X))
     => nil

string= string1 string2 Function
この関数は、2つの文字列の各文字が正確に一致すればtを返す。 大文字小文字を区別する。
(string= "abc" "abc")
     => t
(string= "abc" "ABC")
     => nil
(string= "ab" "ABC")
     => nil

関数string=は2つの文字列のテキスト属性を無視する。 equal(see Equality Predicates)が2つの文字列を比較する際には、 string=を使う。

文字列に非ASCII文字が含まれ、 一方がユニバイトであり他方がマルチバイトである場合、 それらが等しいことはない。 see Text Representations

string-equal string1 string2 Function
string-equalstring=の別名。

string< string1 string2 Function
この関数は2つの文字列を1文字ずつ比較する。 まず、文字列を走査し、対応する文字同士の対で一致しないものを探す。 そのような対の文字の小さいほうがstring1の文字であるならば、 string1が小さく、この関数はtを返す。 文字の小さいほうがstring2の文字であるならば、 string1が大きく、この関数はnilを返す。 2つの文字列が完全に一致する場合、値はnilである。

文字の対は、それらの文字コードで比較する。 ASCII文字集合では、小文字は大文字より大きな数値であり、 数字文字や多くの句読点文字は大文字より小さな数値であることに注意。 ASCII文字はどんな非ASCII文字よりも小さい。 ユニバイト非ASCII文字はマルチバイト非ASCII文字よりもつねに小さい。 (see Text Representations)。

(string< "abc" "abd")
     => t
(string< "abd" "abc")
     => nil
(string< "123" "abc")
     => t

文字列の長さが異なりstring1の長さまで一致する場合、 結果はtである。 string2の長さまで一致する場合、結果はnilである。 空文字列は他のどんな文字列よりも小さい。

(string< "" "abc")
     => t
(string< "ab" "abc")
     => t
(string< "abc" "")
     => nil
(string< "abc" "ab")
     => nil
(string< "" "")
     => nil

string-lessp string1 string2 Function
string-lesspstring<の別名。

compare-strings string1 start1 end1 string2 start2 end2 &optional ignore-case Function
この関数は、string1の指定部分とstring2の指定部分を比較する。 string1の指定部分は、 添字start1位置から始まり添字end1位置までである (デフォルトは文字列の末尾)。 string2の指定部分は、 添字start2位置から始まり添字end2位置までである (デフォルトは文字列の末尾)。

どちらの文字列も比較のためにマルチバイトに変換するので (see Text Representations)、 ユニバイト文字列とマルチバイトが等しくなる場合もある。 ignore-casenilでなければ、大文字小文字を区別しないので、 大文字は小文字に等しくなる

2つの文字列の指定部分が一致すれば、値はt。 さもなければ、値は何文字目までが一致してどちらの文字列が小さいかを示す。 その絶対値は、2つの文字列の始めから一致した文字の個数に1を加えたもの。 string1(の指定部分)が小さいならば符号は負になる。

assoc-ignore-case key alist Function
この関数は、assocと同様に動作するが、 keyは文字列である必要があり、 compare-stringsを用いて比較する点が異なる。 大文字小文字を区別しないで比較する。

assoc-ignore-representation key alist Function
この関数は、assocと同様に動作するが、 keyは文字列である必要があり、 compare-stringsを用いて比較する点が異なる。 大文字小文字を区別して比較する。

バッファ内のテキストを比較する Comparing Textcompare-buffer-substringsも参照してください。 文字列に対して正規表現の一致を取る関数string-matchは、 ある種の文字列比較に使えます。 See Regexp Search


Node:String Conversion, Next:, Previous:Text Comparison, Up:Strings and Characters

文字と文字列の変換

本節では、文字や文字列と整数のあいだの変換関数について説明します。 formatprin1-to-string(see Output Functions)は、 Lispオブジェクトを文字列に変換するために使えます。 read-from-string(see Input Functions)は、 Lispオブジェクトの文字列表現をオブジェクトに『変換』できます。 関数string-make-multibytestring-make-unibyteは、 文字列のテキスト表現を変換します(see Converting Representations)。

テキスト文字と一般の入力イベントのテキスト表現を生成する関数 (single-key-descriptiontext-char-description)については、 See Documentation。 これらの関数は、主に、ヘルプメッセージの作成に使います。

char-to-string character Function
この関数は、1つの文字characterだけを含む新たな文字列を返す。 関数stringのほうがより汎用であるので、 この関数はほぼ廃れている。 see Creating Strings

string-to-char string Function
この関数は、stringの先頭文字を返す。 文字列が空であると関数は0を返す。 文字列stringの先頭文字が、ASCIIコードが0のナル文字であるときも、 値は0である。
(string-to-char "ABC")
     => 65
(string-to-char "xyz")
     => 120
(string-to-char "")
     => 0
(string-to-char "\000")
     => 0

この関数は、存続させるほど有用でなければ、将来、取り除くかもしれない。

number-to-string number Function
この関数は、numberの表示表現である文字列を返す。 numberは整数か浮動小数点数。 引数が負であれば値の文字列は符号で始まる。
(number-to-string 256)
     => "256"
(number-to-string -23)
     => "-23"
(number-to-string -23.5)
     => "-23.5"

int-to-stringは、この関数のほぼ廃れている別名。 Formatting Stringsformatも参照。

string-to-number string &optional base Function
この関数は、string内の文字群が表す数値を返す。 basenil以外ならば、これを基数として整数に変換する。 basenilならば10を基数とする。 浮動小数点数の変換はつねに10を基数とする。 浮動小数点数に対しては別の基数を実装していない。 作業量も多くそのわりには有用とも思えないからである。

解析するとき、stringの先頭にある空白やタブは無視し、 数と解釈できる限りをstringから読み取る。 (先頭の空白やタブ以外の他の白文字を無視するシステムもある。) 無視した白文字のあとの最初の文字が、数字文字、プラス記号、 マイナス記号でなければ、この関数は0を返す。

(string-to-number "256")
     => 256
(string-to-number "25 is a perfect square.")
     => 25
(string-to-number "X256")
     => 0
(string-to-number "-4.5")
     => -4.5

string-to-intはこの関数の廃れた別名。

文字列へ/から変換するその他の関数を以下にあげておきます。

concat
concatは、ベクトルやリストを文字列へ変換する。 see Creating Strings
vconcat
vconcatは、文字列をベクトルへ変換する。 see Vector Functions
append
appendは、文字列をリストへ変換する。 see Building Lists


Node:Formatting Strings, Next:, Previous:String Conversion, Up:Strings and Characters

文字列の書式付け

書式付け(formatting)とは、 定数文字列内のさまざま部分を計算値で置き換えた文字列を作ることです。 この文字列は、文字列自体に加えて、 他の値をどのように表示するかも制御します。 この文字列を書式付け文字列(format string)と呼びます。

書式付けは、表示するメッセージを計算する場合に便利です。 実際、関数messageと関数errorには、 ここで説明するのと同じ書式付け機能があります。 それらとformatとの違いは、 書式付けした結果をどのように利用するかです。

format string &rest objects Function
この関数は、stringをコピーし、 コピー内の書式付け指定を対応するobjectsの表現で置き換えた 新たな文字列を返す。 引数objectsは書式付けすべき計算値である。

書式付け指定は%で始まる文字の列です。 したがって、string内に%dがあると、 関数formatはそれを書式付けすべき値の1つ (引数objectsの1つ)の表示表現で置き換えます。 たとえば、つぎのとおりです。

(format "The value of fill-column is %d." fill-column)
     => "The value of fill-column is 72."

stringに2個以上の書式付け指定がある場合、 書式付け指定はobjectsの後続の値に対応します。 つまり、stringの最初の書式付け指定は最初の値を使い、 2番目の書式付け指定は2番目の値を使い、といった具合です。 (値が対応しない)余計な書式付け指定は、 予測不可能なふるまいを引き起こします。 余計な値は無視します。

特定の書式付け指定は、特定の型の値を必要とします。 要求に適合しない値を読者が指定するとエラーを通知します。

有効な書式付け指定をつぎに示します。

%s
書式付け指定をオブジェクトのクォートしない (つまり、prin1ではなくprincを用いる。see Output Functions) 表示表現で置き換える。 したがって、文字列は"文字なしでその内容を表示し、 シンボルは\文字なしで表示する。

対応するオブジェクトがなければ空文字列を使う。

%S
書式付け指定をオブジェクトのクォートした (つまり、prin1を用いる。see Output Functions) 表示表現で置き換える。 したがって、文字列は"文字で囲んで表示し、 シンボルは特別な文字のまえには\文字を付けて表示する。

対応するオブジェクトがなければ空文字列を使う。

%o
書式付け指定を整数の基数8の表示表現で置き換える。
%d
書式付け指定を整数の基数10の表示表現で置き換える。
%x
書式付け指定を整数の基数16の表示表現で置き換える。
%c
書式付け指定を指定値の文字で置き換える。
%e
書式付け指定を浮動小数点数の指数表記で置き換える。
%f
書式付け指定を浮動小数点数の小数点表記で置き換える。
%g
書式付け指定を浮動小数点数の指数表記か小数点表記のどちらか短いほうで 置き換える。
%%
文字列に1個の%を入れる。 この書式付け指定は、値を使わない点で特別である。 たとえば、(format "%% %d" 30)"% 30"を返す。

上記以外の書式付け文字は、エラーInvalid format operationになります。

例をいくつか示します。

(format "The name of this buffer is %s." (buffer-name))
     => "The name of this buffer is strings.texi."

(format "The buffer object prints as %s." (current-buffer))
     => "The buffer object prints as strings.texi."

(format "The octal value of %d is %o,
         and the hex value is %x." 18 18 18)
     => "The octal value of 18 is 22,
         and the hex value is 12."

すべての書式付け文字には、%とその文字のあいだに、 数前置子を指定できます。 省略可能な数前置子はオブジェクトの最小幅を指定します。 オブジェクトの表示表現がこの幅より小さい場合、パディングします。 数前置子が正ならば(あるいはゼロで始まれば)左側にパディングし、 数前置子が負ならば右側にパディングします。 パディング文字は、通常、空白ですが、 数前置子がゼロで始まれば、ゼロでパディングします。 パディングの例を示します。

(format "%06d is padded on the left with zeros" 123)
     => "000123 is padded on the left with zeros"

(format "%-6d is padded on the right" 123)
     => "123    is padded on the right"

formatは、どんな幅を指定しても、 オブジェクトの表示表現を切り詰めることはありません。 つまり、情報を失うことなく、数前置子を使って最小の桁幅を指定できます。

つぎの3つの例において、%7sは最小幅7を指定します。 最初の例では、%7sに置き換わる文字列は3文字ですから、 パディングとして空白4個を挿入します。 2番目の例では、文字列"specification"は13文字幅ですが切り詰めません。 3番目の例では、右側にパディングします。

(format "The word `%7s' actually has %d letters in it."
        "foo" (length "foo"))
     => "The word `    foo' actually has 3 letters in it."

(format "The word `%7s' actually has %d letters in it."
        "specification" (length "specification"))
     => "The word `specification' actually has 13 letters in it."

(format "The word `%-7s' actually has %d letters in it."
        "foo" (length "foo"))
     => "The word `foo    ' actually has 3 letters in it."


Node:Case Conversion, Next:, Previous:Formatting Strings, Up:Strings and Characters

Lispの大文字小文字変換

大文字小文字変換関数は、1文字や文字列内の大文字小文字を変更します。 関数は、通常、アルファベット文字 (非ASCII文字のアルファベットに加えて、 AからZaからz)だけを変換します。 それ以外の文字は変わりません。 (大文字小文字テーブルを指定して異なる大文字小文字変換を指定できる。 see Case Tables

これらの関数は、引数として渡した文字列は変更しません。

以下の例では、文字Xxを使います。 ASCIIコードは、それぞれ、88と120です。

downcase string-or-char Function
この関数は、文字や文字列を小文字に変換する。

downcaseの引数が文字列であると、 この関数は、引数の各文字の大文字を小文字に変換した新たな文字列を作成する。 downcaseの引数が文字であると、 downcaseは対応する小文字を返す。 この値は整数である。 もとの文字が小文字であったりアルファベット文字でなければ、 値はもとの文字に等しい。

(downcase "The cat in the hat")
     => "the cat in the hat"

(downcase ?X)
     => 120

upcase string-or-char Function
この関数は、文字や文字列を大文字に変換する。

upcaseの引数が文字列であると、 この関数は、引数の各文字の小文字を大文字に変換した新たな文字列を作成する。

upcaseの引数が文字であると、 upcaseは対応する大文字を返す。 この値は整数である。 もとの文字が大文字であったりアルファベット文字でなければ、 値はもとの文字に等しい。

(upcase "The cat in the hat")
     => "THE CAT IN THE HAT"

(upcase ?x)
     => 88

capitalize string-or-char Function
この関数は、文字列や文字をキャピタライズ(先頭文字だけを大文字に)する。 string-or-charが文字列ならば、 この関数は、string-or-charのコピーの各単語をキャピタライズしたものを 内容とする新たな文字列を作成して返す。 つまり、各単語の先頭文字だけを大文字にして残りを小文字にする。

単語の定義は、現在の構文テーブル(See Syntax Class Table)において 単語構成文字に分類された文字が連続した列である。

capitalizeの引数が文字の場合には、 capitalizeupcaseの結果と同じである。

(capitalize "The cat in the hat")
     => "The Cat In The Hat"

(capitalize "THE 77TH-HATTED CAT")
     => "The 77th-Hatted Cat"

(capitalize ?x)
     => 88

upcase-initials string Function
この関数は、string内の単語の先頭文字だけを大文字にし、 先頭文字以外の文字は変更しない。 この関数は、stringのコピーの各単語の先頭文字を大文字に変換したものを 内容とする新たな文字列を返す。

単語の定義は、現在の構文テーブル(See Syntax Class Table)において 単語構成文字に分類された文字が連続した列である。

(upcase-initials "The CAT in the hAt")
     => "The CAT In The HAt"

文字列を比較する関数については、See Text Comparison。 これらは、大文字小文字を区別しないものもあれば、 場合によって大文字小文字を区別しないものもある。


Node:Case Tables, Previous:Case Conversion, Up:Strings and Characters

大文字小文字テーブル

特別な大文字小文字テーブル(case table)をインストールすれば、 大文字小文字変換をカスタマイズできます。 大文字小文字テーブルは、大文字と小文字の対応関係を指定します。 このテーブルは、Lispオブジェクトの大文字小文字変換関数(前節参照)と バッファ内のテキストに作用する大文字小文字変換関数(see Case Changes)の 両方に影響します。 各バッファごとに大文字小文字テーブルがあります。 新たなバッファの大文字小文字テーブルを初期化するために使う 標準の大文字小文字テーブルもあります。

大文字小文字テーブルは、サブタイプがcase-tableである 文字テーブル(see Char-Tables)です。 この文字テーブルは、各文字を対応する小文字に対応付けます。 これには3つの追加スロットがあり、関連するテーブルを保持します。

upcase
upcase(大文字)テーブルは、各文字を対応する大文字に対応付ける。
canonicalize
canonicalize(正則)テーブルは大文字小文字に関連する1組の文字群を その文字群の特定のメンバに対応付ける。
equivalences
equivalences(同値)テーブルは、大文字小文字に関連する1組の文字群の各要素を その文字群内のつぎの文字に対応付ける。

単純な場合、必要なことは、小文字への対応付けを指定するだけです。 関連する3つのテーブルはこの対応付けから自動的に計算されます。

言語によっては、大文字と小文字の対応関係が1対1でないことがあります。 2つの異なる小文字が同じ大文字に対応することがあります。 このような場合、大文字から小文字への対応付けと、 小文字から大文字への対応付けの両方を指定する必要があります。

追加のテーブルcanonicalize(正則)は、各文字を正則文字に対応付けます。 2つの任意の文字が大文字小文字変換で関連付けられている場合、 その2つの文字は同一の正則文字を持ちます。 たとえば、aAは、大文字小文字変換で関連付けられているので、 これらは同一の正則文字を持つはずです (両方の文字に対してaであるか、両方の文字に対してAである)。

追加のテーブルequivalences(同値)は、 同じ正則クラス(同一の正則文字を持つ文字群)の文字を巡回して対応付けます。 (普通のASCIIでは、aAに対応付け、 Aaに対応付ける。 各正則クラスについても同様。)

大文字小文字テーブルを作成するときには、 canonicalize(正則)にはnilを指定できます。 そうすると、Emacsはこのスロットを小文字と大文字の対応付けから埋めます。 equivalences(同値)にもnilを指定できます。 そうすると、Emacsはこのスロットをcanonicalize(正則)から埋めます。 実際に使用している大文字小文字テーブルでは、 これらの要素はnil以外です。 canonicalize(正則)を指定せずに equivalences(同値)を指定しないでください、

つぎに、大文字小文字テーブルを操作する関数を示します。

case-table-p object Function
この述語は、objectが正しい 大文字小文字テーブルならばnil以外を返す。

set-standard-case-table table Function
この関数は、tableを標準の大文字小文字テーブルとし、 これ以降に作成する任意のバッファに使用できるようにする。

standard-case-table Function
これは、標準の大文字小文字テーブルを返す。

current-case-table Function
この関数は、カレントバッファの大文字小文字テーブルを返す。

set-case-table table Function
これは、カレントバッファの大文字小文字テーブルをtableとする。

以下の3つ関数は、非ASCII文字集合を定義するパッケージ向けの 便利なサブルーティンです。 これらは、指定した大文字小文字テーブルcase-tableを変更します。 さらに、標準の構文テーブルも変更します。 See Syntax Tables。 普通、標準の大文字小文字テーブルを変更するためにこれらの関数を使います。

set-case-syntax-pair uc lc case-table Function
この関数は対応する大文字と小文字を指定する。

set-case-syntax-delims l r case-table Function
この関数は、文字lrを 大文字小文字不変区切りの対応する対にする。

set-case-syntax char syntax case-table Function
この関数は、charを構文syntaxの大文字小文字不変にする。

describe-buffer-case-table コマンド
このコマンドは、カレントバッファの大文字小文字テーブルの内容を記述する。


Node:Lists, Next:, Previous:Strings and Characters, Up:Top

リスト

リスト(list)は、0個以上の(任意のLispオブジェクトの)要素の列を 表現します。 リストとベクトルの重要な相違点は、 複数のリストがそれらの構造の一部を共有できることです。 さらに、リスト全体をコピーすることなく、 リストに要素を追加したり削除できることです。


Node:Cons Cells, Next:, Up:Lists

リストとコンスセル

Lispのリストは基本データ型ではありません。 リストはコンスセル(cons cells)で構成されます。 コンスセルはドット対を表現するデータオブジェクトです。 ドット対は2つのLispオブジェクトを保持、つまり、『指し』ます。 その2つのLispオブジェクトの一方をCAR、他方をCDRといいます。 これらの名前は歴史的なものです。 See Cons Cell TypeCDRは『クダー』と読みます。

リストはコンスセルを連ねたものであり、 リストの各要素ごとにコンスセルが1つあります。 慣習として、コンスセルのCARはリストの要素であり、 CDRはリストを繋ぐために使います。 つまり、各コンスセルのCDRは後続のコンスセルです。 最後のコンスセルのCDRnilです。 CARCDRの非対称性は単なる慣習によるものです。 コンスセルのレベルでは、CARCDRには同じ性質があります。

ほとんどのコンスセルはリストの一部として使われるので、 リスト構造(list structure)という用語は、 コンスセルで構成した任意の構造を意味するようになりました。

シンボルnilは、シンボルであるとともにリストでもあるとみなします。 これは要素を持たないリストです。 慣習として、シンボルnilCDR(およびCAR)は nilであるとみなします。

空でない任意のリストlCDRは、 lの先頭要素を除くすべての要素を含んだリストです。


Node:Lists as Boxes, Next:, Previous:Cons Cells, Up:Lists

箱の対を連ねたリスト

コンスセルは1対の箱で図示できます。 最初の箱はCARを表し、2番目の箱はCDRを表します。 つぎは、2つのコンスセルから成る 2要素のリスト(tulip lily)を図示したものです。

 ---------------         ---------------
| car   | cdr   |       | car   | cdr   |
| tulip |   o---------->| lily  |  nil  |
|       |       |       |       |       |
 ---------------         ---------------

各1対の箱がコンスセルを表します。 各箱は、Lispオブジェクトを『参照する』、『指す』、『含む』のです。 (これらの用語は同義語。) 最初のコンスセルのCARを表す最初の箱は、 シンボルtulipを含みます。 最初のコンスセルのCDR箱から2番目のコンスセルへ向かう矢印は、 最初のコンスセルのCDRが2番目のコンスセルであることを表します。

同じリストは、つぎのような別の箱記法でも図示できます。

    --- ---      --- ---
   |   |   |--> |   |   |--> nil
    --- ---      --- ---
     |            |
     |            |
      --> tulip    --> lily

つぎは、より複雑で、最初の要素が2要素リストであるような 3要素リストを図示したものです。

    --- ---      --- ---      --- ---
   |   |   |--> |   |   |--> |   |   |--> nil
    --- ---      --- ---      --- ---
     |            |            |
     |            |            |
     |             --> oak      --> maple
     |
     |     --- ---      --- ---
      --> |   |   |--> |   |   |--> nil
           --- ---      --- ---
            |            |
            |            |
             --> pine     --> needles

同じリストを最初の箱記法で表現するとつぎのようになります。

 --------------       --------------       --------------
| car   | cdr  |     | car   | cdr  |     | car   | cdr  |
|   o   |   o------->| oak   |   o------->| maple |  nil |
|   |   |      |     |       |      |     |       |      |
 -- | ---------       --------------       --------------
    |
    |
    |        --------------       ----------------
    |       | car   | cdr  |     | car     | cdr  |
     ------>| pine  |   o------->| needles |  nil |
            |       |      |     |         |      |
             --------------       ----------------

コンスセルとリストの入力構文と表示表現、および、 『箱と矢印』によるリストの図示については、See Cons Cell Type


Node:List-related Predicates, Next:, Previous:Lists as Boxes, Up:Lists

リスト向け述語

以下の述語は、Lispオブジェクトが、アトムであるか、 コンスセル、つまり、リストであるか、 特別なオブジェクトnilであるか調べます。 (これらの多く述語は、それぞれ残りの述語で定義可能である。 しかし、多用するため、これらすべてを用意しておく価値がある。)

consp object Function
この関数は、objectがコンスセルならばtを返し、 さもなければnilを返す。 nilはコンスセルではないが、空リストである

atom object Function
この関数は、objectがアトムならばtを返し、 さもなければnilを返す。 コンスセルを除くすべてのオブジェクトはアトムである。 シンボルnilはアトムでもありリストでもある。 このようなLispオブジェクトはnilだけである。
(atom object) == (not (consp object))

listp object Function
この関数は、objectがコンスセルかnilならばtを返す。 さもなければnilを返す。
(listp '(1))
     => t
(listp '())
     => t

nlistp object Function
この関数は、listpの反対である。 objectがリストでなければtを返す。 さもなければnilを返す。
(listp object) == (not (nlistp object))

null object Function
この関数は、objectnilならばtを返し、 さもなければnilを返す。 この関数は、notと同一であるが、意図を明確にするために、 objectをリストと考えるときにはnullを使い、 objectを真理値と考えるときにはnotを使う (Combining Conditionsnotを参照)
(null '(1))
     => nil
(null '())
     => t


Node:List Elements, Next:, Previous:List-related Predicates, Up:Lists

リストの要素の参照

car cons-cell Function
この関数は、コンスセルcons-cellの最初のポインタが指す値を返す。 別のいい方をすれば、cons-cellCARを返す。

特別な場合として、cons-cellnilのときには、 carnilを返すと定義する。 したがって、任意のリストはcarの正しい引数である。 引数がコンスセルでもnilでもなければエラーを通知する。

(car '(a b c))
     => a
(car '())
     => nil

cdr cons-cell Function
この関数は、コンスセルcons-cellの2番目のポインタが指す値を返す。 別のいい方をすれば、cons-cellCDRを返す。

特別な場合として、cons-cellnilのときには、 cdrnilを返すと定義する。 したがって、任意のリストはcdrの正しい引数である。 引数がコンスセルでもnilでもなければエラーを通知する。

(cdr '(a b c))
     => (b c)
(cdr '())
     => nil

car-safe object Function
この関数は、コンスセルのCARを取り出すが、 他のデータ型に対するエラーを回避する。 objectがコンスセルならばobjectCARを返すが、 さもなければnilを返す。 これはcarと対照的であり、 carobjectがリストでないとエラーを通知する。
(car-safe object)
==
(let ((x object))
  (if (consp x)
      (car x)
    nil))

cdr-safe object Function
この関数は、コンスセルのCDRを取り出すが、 他のデータ型に対するエラーを回避する。 objectがコンスセルならばobjectCDRを返すが、 さもなければnilを返す。 これはcdrと対照的であり、 cdrobjectがリストでないとエラーを通知する。
(cdr-safe object)
==
(let ((x object))
  (if (consp x)
      (cdr x)
    nil))

nth n list Function
この関数は、listn番目の要素を返す。 要素は0から数えるので、listCARは要素番号0。 listの長さがnかそれ未満であると、値はnilになる。

nが負であると、nthlistの最初の要素を返す。

(nth 2 '(1 2 3 4))
     => 3
(nth 10 '(1 2 3 4))
     => nil
(nth -3 '(1 2 3 4))
     => 1

(nth n x) == (car (nthcdr n x))

関数eltも同様であるが、任意のシーケンスに適用できる。 歴史的な理由で引数の順序は逆である。 see Sequence Functions

nthcdr n list Function
この関数は、listn番目のCDRを返す。 いいかえれば、listの始めのn個のリンクを飛び越えて、 そのあとにあるものを返す。

nが0か負であると、nthcdrlist全体を返す。 listの長さがnかそれ未満であると、 nthcdrnilを返す。

(nthcdr 1 '(1 2 3 4))
     => (2 3 4)
(nthcdr 10 '(1 2 3 4))
     => nil
(nthcdr -3 '(1 2 3 4))
     => (1 2 3 4)

safe-length list Function
この関数は、エラーや無限ループを回避して、listの長さを返す。

listが実際にはリストでない場合には、safe-lengthは0を返す。 listに循環があると、少なくとも異なる要素の個数を表す有限値を返す。

循環はないと思われるリストの長さを計算するもっとも一般的な方法は、 lengthです。 See Sequence Functions

caar cons-cell Function
これは(car (car cons-cell))と同じ。

cadr cons-cell Function
これは(car (cdr cons-cell))(nth 1 cons-cell)と同じ。

cdar cons-cell Function
これは(cdr (car cons-cell))と同じ。

cddr cons-cell Function
これは(cdr (cdr cons-cell))(nthcdr 2 cons-cell)と同じ。


Node:Building Lists, Next:, Previous:List Elements, Up:Lists

コンスセルとリストの構築

リストはLispの中核なので、多くの関数はリストを構築します。 consは基本的なリスト構築関数です。 しかし、Emacsのソースコードでは、consよりlistを 多用していることは興味深いことです。

cons object1 object2 Function
この関数は、新たなリスト構造を構築するために使う基本関数。 object1CARobject2CDRとする 新たなコンスセルを作成し、このコンスセルを返す。 引数object1object2はどんなLispオブジェクトでもよいが、 ほとんどの場合、object2はリストである。
(cons 1 '(2))
     => (1 2)
(cons 1 '())
     => (1)
(cons 1 2)
     => (1 . 2)

consは、リストの先頭に要素を1つ追加するために しばしば使われる。 これを要素をリストにコンスするという。 たとえば、つぎのとおり。

(setq list (cons newelt list))

この例におけるlistという名前の変数と 以下に述べるlistという名前の関数とは衝突しない。 任意のシンボルはどちらの目的にも使える。

list &rest objects Function
この関数は、objectsを要素とするリストを作成する。 結果のリストはつねにnil終端になる。 objectsを指定しないと空リストを返す。
(list 1 2 3 4 5)
     => (1 2 3 4 5)
(list 1 2 '(3 4 5) 'foo)
     => (1 2 (3 4 5) foo)
(list)
     => nil

make-list length object Function
この関数は、すべての要素が同一の値objectであり 長さがlengthのリストを作成する。 make-stringと比較してほしい(see Creating Strings)。
(make-list 3 'pigs)
     => (pigs pigs pigs)
(make-list 0 'pigs)
     => nil

append &rest sequences Function
この関数はsequencesのすべての要素から成るリストを返す。 sequencesは、リスト、ベクトル、ブールベクトル、文字列のいずれかであるが、 普通、最後の要素はリストである。 最後の引数を除いてすべての引数をコピーするので、どの引数も変更しない (コピーせずにリストを繋ぐ方法については、 Rearrangementnconcを参照。)

一般には、appendの最後の引数はどんなLispオブジェクトでもよい。 最後の引数をコピーしたり変換したりしない。 それは、新たなリストの最後のコンスセルのCDRになる。 最後の引数がそれ自体リストであれば、それらの要素は、実質的には、 結果のリストの要素になる。 最後の要素がリストでなければ、結果は『ドット対』になる。 なぜなら、結果の最後のCDRは、 真のリストに必要とされるnilではないからである。

関数appendは、引数として整数も受け付ける。 整数を10進の表示表現の文字列に変換してから、 その文字列を整数のかわりに使う。 この機能を使わないでほしい。 削除する予定である。 読者がこの機能を使っていたら、今すぐプログラムを直すこと! 整数をこのような10進数に変換する正しい方法は、 format(see Formatting Strings)や number-to-string(see String Conversion)を使うことである。

appendの使用例をつぎに示します。

(setq trees '(pine oak))
     => (pine oak)
(setq more-trees (append '(maple birch) trees))
     => (maple birch pine oak)

trees
     => (pine oak)
more-trees
     => (maple birch pine oak)
(eq trees (cdr (cdr more-trees)))
     => t

箱表示を見ればappendの動作を理解できるでしょう。 変数treesにリスト(pine oak)を設定し、ついで、 変数more-treesにはリスト(maple birch pine oak)を設定します。 しかし、変数treesはもとのリストを指し続けます。

more-trees                trees
|                           |
|     --- ---      --- ---   -> --- ---      --- ---
 --> |   |   |--> |   |   |--> |   |   |--> |   |   |--> nil
      --- ---      --- ---      --- ---      --- ---
       |            |            |            |
       |            |            |            |
        --> maple    -->birch     --> pine     --> oak

空シーケンスはappendが返す値にはまったく寄与しません。 この結果、最後のnil引数は直前の引数をコピーするように強制します。

trees
     => (pine oak)
(setq wood (append trees nil))
     => (pine oak)
wood
     => (pine oak)
(eq wood trees)
     => nil

この方法は、関数copy-sequenceを導入するまでは、 リストをコピーする普通の方法でした。 See Sequences Arrays Vectors

appendの引数にベクトルと文字列を使った例をつぎに示します。

(append [a b] "cd" nil)
     => (a b 99 100)

apply(see Calling Functions)の助けを借りれば、 リストのリストの中にあるすべてのリストを連結できます。

(apply 'append '((a b c) nil (x y z) nil))
     => (a b c x y z)

sequencesをまったく指定しないとnilを返します。

(append)
     => nil

最後の引数がリストではない例をいくつか示します。

(append '(x y) 'z)
     => (x y . z)
(append '(x y) [z])
     => (x y . [z])

最後の引数がリストではなくシーケンスである2番目の例は、 シーケンスの要素が結果のリストの要素にはならないことを示しています。 そのかわりに、最後の引数がリストでない場合と同様に、 シーケンスが最後のCDRになります。

reverse list Function
この関数は、listの要素を逆順にした新たなリストを作成する。 もとの引数listは変更しない
(setq x '(1 2 3 4))
     => (1 2 3 4)
(reverse x)
     => (4 3 2 1)
x
     => (1 2 3 4)


Node:Modifying Lists, Next:, Previous:Building Lists, Up:Lists

既存のリスト構造の修正

基本関数setcarsetcdrを使って、 コンスセルのCARCDRの内容を変更できます。 これらは、既存のリスト構造を変更するので、 『破壊的』な操作と呼びます。

Common Lispに関した注意: Common Lispでは、 リスト構造を変更するにはrplacarplacdを使う。 これらはsetcarsetcdrと同様に構造を変更する。 しかし、Common Lispの関数はコンスセルを返すが、 setcarsetcdrは新たなCARCDRを返す。


Node:Setcar, Next:, Up:Modifying Lists

setcarによるリスト要素の変更

コンスセルのCARを変更するには、setcarを使います。 リストに対して使用すると、 setcarはリストの1つの要素を別の要素に置き換えます。

setcar cons object Function
この関数は、consの新たなCARとしてobjectを格納し、 以前のCARを置き換える。 いいかえれば、consCARスロットがobjectを指すように変更する。 この関数は値objectを返す。 たとえば、つぎのようになる。
(setq x '(1 2))
     => (1 2)
(setcar x 4)
     => 4
x
     => (4 2)

コンスセルが複数のリストの共有構造の一部であるときには、 コンスセルに新たなCARを格納すると、 そのような各リストの1つの要素を変更することになります。

;; 共有部分がある2つのリストを作る
(setq x1 '(a b c))
     => (a b c)
(setq x2 (cons 'z (cdr x1)))
     => (z b c)

;; 共有部分のCARを置き換える
(setcar (cdr x1) 'foo)
     => foo
x1                           ; 両方のリストが変更されている
     => (a foo c)
x2
     => (z foo c)

;; 非共有部分のCARを置き換える
(setcar x1 'baz)
     => baz
x1                           ; 1つのリストだけが変更されている
     => (baz foo c)
x2
     => (z foo c)

変数x1x2に入っている共有部分を持つ2つのリストを図示すると つぎのようになります。 bを置き換えるとなぜ両者が変更されるのかわかるでしょう。

        --- ---        --- ---      --- ---
x1---> |   |   |----> |   |   |--> |   |   |--> nil
        --- ---        --- ---      --- ---
         |        -->   |            |
         |       |      |            |
          --> a  |       --> b        --> c
                 |
       --- ---   |
x2--> |   |   |--
       --- ---
        |
        |
         --> z

同じ関係を別の箱表示で示します。

x1:
 --------------       --------------       --------------
| car   | cdr  |     | car   | cdr  |     | car   | cdr  |
|   a   |   o------->|   b   |   o------->|   c   |  nil |
|       |      |  -->|       |      |     |       |      |
 --------------  |    --------------       --------------
                 |
x2:              |
 --------------  |
| car   | cdr  | |
|   z   |   o----
|       |      |
 --------------


Node:Setcdr, Next:, Previous:Setcar, Up:Modifying Lists

リストのCDRの変更

CDRを修正するもっとも低レベルの基本関数はsetcdrです。

setcdr cons object Function
この関数は、consの新たなCDRとしてobjectを格納し、 以前のCDRを置き換える。 いいかえれば、consCDRスロットがobjectを指すように変更する。 この関数は値objectを返す。

リストのCDRを別のリストで置き換える例を示します。 リストの最初の要素以外は取り除かれ、 要素の別のシーケンスになります。 最初の要素は変更されません。 というのは、それはリストのCARの中にあり、 CDRからは辿れないからです。

(setq x '(1 2 3))
     => (1 2 3)
(setcdr x '(4))
     => (4)
x
     => (1 4)

リスト内のコンスセル群のCDRを変更することで、 リストの中ほどの要素を削除できます。 つぎの例は、リスト(a b c)の最初のコンスセルのCDRを変更することで、 このリストの第2要素bを削除します。

(setq x1 '(a b c))
     => (a b c)
(setcdr x1 (cdr (cdr x1)))
     => (c)
x1
     => (a c)

箱表記では、この結果はつぎのようになります。

                   --------------------
                  |                    |
 --------------   |   --------------   |    --------------
| car   | cdr  |  |  | car   | cdr  |   -->| car   | cdr  |
|   a   |   o-----   |   b   |   o-------->|   c   |  nil |
|       |      |     |       |      |      |       |      |
 --------------       --------------        --------------

以前に要素bを保持していた2番目のコンスセルはまだ存在していて、 そのCARもまだbですが、このリストの一部ではありません。

CDRを変更して新たな要素を挿入するのも同様に簡単です。

(setq x1 '(a b c))
     => (a b c)
(setcdr x1 (cons 'd (cdr x1)))
     => (d b c)
x1
     => (a d b c)

箱表記では、この結果はつぎのようになります。

 --------------        -------------       -------------
| car  | cdr   |      | car  | cdr  |     | car  | cdr  |
|   a  |   o   |   -->|   b  |   o------->|   c  |  nil |
|      |   |   |  |   |      |      |     |      |      |
 --------- | --   |    -------------       -------------
           |      |
     -----         --------
    |                      |
    |    ---------------   |
    |   | car   | cdr   |  |
     -->|   d   |   o------
        |       |       |
         ---------------


Node:Rearrangement, Previous:Setcdr, Up:Modifying Lists

リストの順序を変更する関数

以下は、リストを構成するコンスセルのCDRを変更することで、 『破壊的に』リストの順序を変更する関数です。 これらの関数を『破壊的』と呼ぶのは、 渡された引数であるもとのリストのコンスセルを繋ぎ換えて新たなリストに 変えるからです。

nconc &rest lists Function
この関数は、listsのすべての要素を入れたリストを返す。 append(see Building Lists)と異なり、 listsをコピーしない。 そのかわりに、各listsの最後のCDRを後続のリストを指すように変更する。 listsの最後は変更しない。 たとえば、つぎのようになる。
(setq x '(1 2 3))
     => (1 2 3)
(nconc x '(4 5))
     => (1 2 3 4 5)
x
     => (1 2 3 4 5)

nconcは最後の引数を変更しないので、 上述の例のように、'(4 5)などの定数リストを使ってよい。 同じ理由で最後の引数はリストである必要もない。

(setq x '(1 2 3))
     => (1 2 3)
(nconc x 'z)
     => (1 2 3 . z)
x
     => (1 2 3 . z)

しかしながら、すべての引数は(最後のものを除いて)リストである必要がある。

よくある落し穴は、nconcの最後以外の引数に、 クォートした定数リストを使うことである。 こうすると、読者のプログラムは実行するたびに定数を変えてしまう。 たとえば、つぎのようになる。

(defun add-foo (x)            ; この関数は引数の先頭に
  (nconc '(foo) x))           ;   fooを追加する、としたい

(symbol-function 'add-foo)
     => (lambda (x) (nconc (quote (foo)) x))

(setq xx (add-foo '(1 2)))    ; 動いているように見える
     => (foo 1 2)
(setq xy (add-foo '(3 4)))    ; どうなってるの?
     => (foo 1 2 3 4)
(eq xx xy)
     => t

(symbol-function 'add-foo)
     => (lambda (x) (nconc (quote (foo 1 2 3 4) x)))

nreverse list Function
この関数は、listの要素の順番を逆順にする。 reverseと異なり、nreverseは リストを構成するコンスセルのCDRを逆向きにして引数を変えてしまう。 listの最後にあったコンスセルは戻り値の最初のコンスセルになる。

たとえば、つぎのようになる。

(setq x '(1 2 3 4))
     => (1 2 3 4)
x
     => (1 2 3 4)
(nreverse x)
     => (4 3 2 1)
;; 先頭にあったコンスセルは、今、最後になっている
x
     => (1)

混乱を避けるために、nreverseの結果は、 もとのリストを収めていたものと同じ変数に格納する。

(setq x (nreverse x))

nreverse(a b c)に適用した結果を図示すると つぎのようになる。

もとのリストの先頭                        逆順にしたリスト
 -------------        -------------        ------------
| car  | cdr  |      | car  | cdr  |      | car | cdr  |
|   a  |  nil |<--   |   b  |   o  |<--   |   c |   o  |
|      |      |   |  |      |   |  |   |  |     |   |  |
 -------------    |   --------- | -    |   -------- | -
                  |             |      |            |
                   -------------        ------------

sort list predicate Function
この関数は、破壊的にではあるが、 listを順序を保ってソートしたリストを返す。 要素の比較にはpredicateを使う。 順序を保ったソートとは、同じソートキーを持つ要素の相対順序を、 ソート実行前後で変更しないソートである。 異なる基準でつぎつぎにソートするときには、 順序を保つことは重要である。

引数predicateは、2つの引数を取る関数である必要がある。 この関数は、listの2つの要素で呼び出される。 昇順のソートでは、predicateは、 第1引数が第2引数より『小さい』ときにtを返し、 さもなければnilを返す必要がある。

比較関数predicateは、少なくとも単一のsortの呼び出し中は、 引数の任意の対に対して信頼できる結果を返す必要がある。 まず、反対称であること。 つまり、abより小さいときには、 baより小さくてはいけない。 また、遷移則が成り立つこと。 つまり、abより小さく、かつ、bcより小さいときには、 acより小さくなければならない。 これらの要請を満たさない比較関数を用いると、 sortの結果は予測できない。

sortが破壊的であるというのは、 listを構成するコンスセルのCDRを変更して、 コンスセルの順序を変更するからである。 非破壊的なソート関数では、ソートした要素を格納するために新たなコンスセルを 作成するであろう。 もとのリストを破壊せずにソートしたければ、 まずcopy-sequenceでコピーを作り、それをソートする。

ソートする際、listのコンスセルのCARは変更しない。 list内の要素aを入れていたコンスセルは、 ソート後にもそのCARにはaが入っている。 しかし、CDRを変更してあるので、リスト内では異なる場所に現れる。 たとえば、つぎのようになる。

(setq nums '(1 3 2 6 5 4 0))
     => (1 3 2 6 5 4 0)
(sort nums '<)
     => (0 1 2 3 4 5 6)
nums
     => (1 2 3 4 5 6)

警告 numsのリストには 0が入っていないことに注意。 (numsが指す)コンスセルはソート前と同じコンスセルだが、 それはもはやリストの先頭にはない。 引数を保持していた変数が、 ソートしたリスト全体を保持していると仮定しないこと! かわりに、sortの結果を保存して、それを使う。 多くの場合、つぎのように、もとのリストを保持していた変数に結果を保存し直す。

(setq nums (sort nums '<))

ソートを行う他の関数については、see Sortingsortの有用な例については、 Accessing Documentationdocumentationを参照。


Node:Sets And Lists, Next:, Previous:Modifying Lists, Up:Lists

集合としてのリストの利用

リストで、数学の順序のない集合を表現できます。 つまり、リストに現れる要素を集合の要素と考え、 リスト内での順序は無視します。 2つの集合の和集合を作るには、 (要素が重複することを気にしなければ)appendを使います。 集合向けの他の有用な関数には、memqdelq、および、 これらのequal版であるmemberdeleteがあります。

Common Lispに関した注意: Common Lispには、集合演算向けに (要素の重複を避ける)関数unionintersectionがあるが、 GNU Emacs Lispにはない。 必要ならば、読者みずからLispでこれらを書ける。

memq object list Function
この関数は、objectlistの要素かどうか調べる。 そうならば、 memqobjectが最初に現れるところから始まるリストを返す。 さもなければnilを返す。 memqの文字qは、リストの要素に対するobjectの比較に eqを使うことを意味する。 たとえば、
(memq 'b '(a b c b a))
     => (b c b a)
(memq '(2) '((1) (2)))    ; (2)(2)eqではない
     => nil

delq object list Function
この関数は、listからobjecteqであるすべての要素を 破壊的に削除する。 delqの文字qは、memqと同様に、 リストの要素に対するobjectの比較にeqを使うことを意味する。

delqがリストの先頭から要素を削除する場合には、 単にリストを辿って削除した要素のつぎから始まる部分リストを返します。

(delq 'a '(a b c)) == (cdr '(a b c))

リストの中ほどの要素を削除する場合には、 削除にはCDRの変更を伴います(see Setcdr)。

(setq sample-list '(a b c (4)))
     => (a b c (4))
(delq 'a sample-list)
     => (b c (4))
sample-list
     => (a b c (4))
(delq 'c sample-list)
     => (a b (4))
sample-list
     => (a b (4))

(delq 'c sample-list)は、 3番目の要素を切り取ってsample-listを変更しますが、 (delq 'a sample-list)では、 なにも切り取らずに単に短いリストを返すことに注意してください。 引数listを保持していた変数が、実行後には少ない要素を持つと仮定したり、 もとのリストを保持し続けていると仮定したりしないでください! そのかわりに、delqの結果を保存して、それを使ってください。 多くの場合、つぎのように、 もとのリストを保持していた変数に結果を保存し直します。

(setq flowers (delq 'rose flowers))

つぎの例では、delqが一致を取ろうとしている(4)sample-list(4)とはeqではありません。

(delq '(4) sample-list)
     => (a c (4))

つぎの2つの関数は、memqdelqに似ていますが、 比較にはeqのかわりにequalを使います。 See Equality Predicates

member object list Function
関数memberは、equalを使ってobjectと要素を比較して、 objectlistの要素かどうか調べる。 objectが要素であれば、 memberlist内でそれが最初に現れるところから始まるリストを返す。 さもなければnilを返す。

memqと比較してほしい。

(member '(2) '((1) (2)))  ; (2)(2)equalである
     => ((2))
(memq '(2) '((1) (2)))    ; (2)(2)eqではない
     => nil
;; 同じ内容の2つの文字列はequalである
(member "foo" '("foo" "bar"))
     => ("foo" "bar")

delete object list Function
この関数は、listからobjectequalであるすべての要素を 破壊的に削除する。 membermemeqに対応するように、delqに対応する。 memberと同様に、 要素とobjectとの比較にはequalを使う。 一致する要素をみつけると、delqと同様に要素を削除する。 たとえば、つぎのとおり。
(delete '(2) '((2) (1) (2)))
     => ((1))

Common Lispに関した注意: GNU Emacs Lispの関数memberと関数deleteは Maclispから受け継いだものであり、Common Lispからではない。 Common Lisp版では要素の比較にはequalを使わない。

変数に格納したリストに要素を追加する別の方法については、 Setting Variablesの関数add-to-listを参照してください。


Node:Association Lists, Previous:Sets And Lists, Up:Lists

連想リスト

連想リスト(association list)、略してalistは、 キーから値への対応付けを記録しています。 これは連想(associations)と呼ばれるコンスセルのリストです。 各コンスセルのCARkeyであり、 CDR連想値(associated value)です。 6

連想リストの例を示します。 キーpineを値conesに、キーoakを値acornsに、 キーmapleを値seedsに対応付けています。

'((pine . cones)
  (oak . acorns)
  (maple . seeds))

連想リスト内の連想値は任意のLispオブジェクトでよく、キーもそうです。 たとえば、つぎの連想リストでは、シンボルaに数1を、 文字列"b"リスト(2 3)を対応付けています。 リスト(2 3)は連想リストの要素のCDRです。

((a . 1) ("b" 2 3))

要素のCDRCARに連想値を格納するように 連想リストを設計したほうがよい場合もあります。 つぎのようにします。

'((rose red) (lily white) (buttercup yellow))

ここで、redroseに対応付けた値と考えます。 この種の連想リストの利点の1つは、関連する別の情報を、 他の項目から成るリストでさえも、CDRCDRに格納できることです。 1つの欠点は、rassq(下記参照)を使って 指定した値を含む要素を探せないことです。 これらの条件が重要でない場合には、1つの連想リストに関する限り、 一貫性があればどちらを選ぶかは好みの問題です。

上に示した連想リストは、要素のCDRに連想値が収めてあると 考えることもできます。 roseの連想値はリスト(red)になります。

連想リストはスタックなどに置くような情報の記録に使います。 というには、リストの先頭に新たな連想を追加するのが簡単だからです。 指定したキーに対する連想を連想リストから探すとき、 それらが複数個存在する場合には、最初にみつかったものを返します。

Emacs Listでは、連想リストの要素がコンスセルでなくても エラーではありません。 連想リスト探索関数はそのような要素を単に無視します。 他の多くのLispでは、そのような場面ではエラーを通知します。

属性リストもいろいろな意味で連想リストに類似しています。 属性リストは、キーが一度しか現れない連想リストのようにふるまいます。 属性リストと連想リストの比較については、See Property Lists

assoc key alist Function
この関数は、alist内のkeyに対する最初の連想を返す。 keyと連想リストの各要素との比較には、 equal(see Equality Predicates)を用いる。 alistの中にCARkeyequalである連想が 存在しなければ、nilを返す。 たとえば、つぎのとおり。
(setq trees '((pine . cones) (oak . acorns) (maple . seeds)))
     => ((pine . cones) (oak . acorns) (maple . seeds))
(assoc 'oak trees)
     => (oak . acorns)
(cdr (assoc 'oak trees))
     => acorns
(assoc 'birch trees)
     => nil

つぎは、キーと値がシンボルではない例。

(setq needles-per-cluster
      '((2 "Austrian Pine" "Red Pine")
        (3 "Pitch Pine")
        (5 "White Pine")))

(cdr (assoc 3 needles-per-cluster))
     => ("Pitch Pine")
(cdr (assoc 2 needles-per-cluster))
     => ("Austrian Pine" "Red Pine")

関数assoc-ignore-representationassoc-ignore-caseassocに似ていますが、 それらは比較にcompare-stringsを使う点が異なります。 See Text Comparison

rassoc value alist Function
この関数は、alistの中でvalueを値とする最初の連想を返す。 alistの中にCDRvalueequalである連想が 存在しなければ、nilを返す。

rassocassocに似ているが、 alistの各連想のCARのかわりにCDRを比較する点が異なる。 指定した値に対するキーを探す『assocの逆演算』と考えることができる。

assq key alist Function
この関数は、alist内のkeyに対する最初の連想を返すという意味で assocに似ているが、equalのかわりにeqで比較する。 alist内の連想のCARkeyeqであるものが存在しないと、 assqnilを返す。 この関数はassocより多用される。 というのは、eqequalより高速であり、 ほとんどの連想リストではキーとしてシンボルを使うからである。
(setq trees '((pine . cones) (oak . acorns) (maple . seeds)))
     => ((pine . cones) (oak . acorns) (maple . seeds))
(assq 'pine trees)
     => (pine . cones)

一方で、キーがシンボルではない連想リストでは、 assqは、通常、有用ではない。

(setq leaves
      '(("simple leaves" . oak)
        ("compound leaves" . horsechestnut)))

(assq "simple leaves" leaves)
     => nil
(assoc "simple leaves" leaves)
     => ("simple leaves" . oak)

rassq value alist Function
この関数は、alistの中でvalueを値とする最初の連想を返す。 alistの中にCDRvalueeqである連想が 存在しなければ、nilを返す。

rassqassqに似ているが、 alistの各連想のCARのかわりにCDRを比較する点が異なる。 指定した値に対するキーを探す『assqの逆演算』と考えることができる。

たとえばつぎのとおり。

(setq trees '((pine . cones) (oak . acorns) (maple . seeds)))

(rassq 'acorns trees)
     => (oak . acorns)
(rassq 'spores trees)
     => nil

rassqでは、 要素のCDRCARに格納された値を探せないことに注意。

(setq colors '((rose red) (lily white) (buttercup yellow)))

(rassq 'white colors)
     => nil

この場合、連想(lily white)CDRは、 シンボルwhiteではなくリスト(white)である。 連想をドット対記法で書くとこれが明確になる。

(lily white) == (lily . (white))

assoc-default key alist test default Function
この関数は、keyに一致するものをalistから探す。 alistの各要素について、(アトムならば)要素とkeyを、 あるいは、(コンスならば)要素のCARkeyを比較する。 比較にはこれらを2つの引数としてtestを呼び出す。 引数を渡す順序はこの順なので、 正規表現(see Regexp Search)を収めた連想リストに対して string-matchを使うと有益な結果を得られる。 testを省略したりnilであると、比較にはequalを用いる。

上の条件で連想リストの要素がkeyに一致するならば、 assoc-defaultはその要素に基づく値を返す。 要素がコンスならば値は要素のCDR。 さもなければ、戻り値はdefault

keyに一致する連想リストの要素が存在しなければ、 assoc-defaultnilを返す。

copy-alist alist Function
この関数は、alistを2レベルの深さまでコピーしたものを返す。 各連想ごとに新たなコピーを作るので、 新たな連想リストの連想を変更しても、もとの連想リストは変更しない。
(setq needles-per-cluster
      '((2 . ("Austrian Pine" "Red Pine"))
        (3 . ("Pitch Pine"))
        (5 . ("White Pine"))))
=>
((2 "Austrian Pine" "Red Pine")
 (3 "Pitch Pine")
 (5 "White Pine"))

(setq copy (copy-alist needles-per-cluster))
=>
((2 "Austrian Pine" "Red Pine")
 (3 "Pitch Pine")
 (5 "White Pine"))

(eq needles-per-cluster copy)
     => nil
(equal needles-per-cluster copy)
     => t
(eq (car needles-per-cluster) (car copy))
     => nil
(cdr (car (cdr needles-per-cluster)))
     => ("Pitch Pine")
(eq (cdr (car (cdr needles-per-cluster)))
    (cdr (car (cdr copy))))
     => t

この例は、copy-alistにより、 コピーの連想を変更して他のものになぜ影響しないかを示す。

(setcdr (assq 3 copy) '("Martian Vacuum Pine"))
(cdr (assq 3 needles-per-cluster))
     => ("Pitch Pine")


Node:Sequences Arrays Vectors, Next:, Previous:Lists, Up:Top

シーケンス、配列、ベクトル

シーケンス(sequence)型とは、Lispの2つの異なる型の和であることを 思い出してください。 いいかえれば、任意のリストはシーケンスであり、 任意の配列もシーケンスです。 すべてのシーケンスに共通する性質は、 それぞれ、要素の順序付けた集まりであるということです。

配列(array)は、各要素ごとに1つ1つスロットを用意してある 単一の基本オブジェクトです。 すべての要素は一定時間内に参照できますが、既存の配列の長さは変更できません。 文字列、ベクトル、文字テーブル、ブールベクトルは、配列型の4つの型です。

リストは、要素を並べたものですが、 単一の基本オブジェクトではありません。 コンスセルから作られていて、1つの要素あたり1つのセルがあります。 n番目の要素を探すには、n個のコンスセルを調べる必要があるので、 リストの先頭から遠い要素を参照するには余計に時間がかかります。 しかし、リストには要素を追加したり削除したりできます。

以下の図は、これらの型の関係を示します。

     ┌────────────────────────┐
     │      シーケンス             │
     │┌───┐ ┌───────────────┐ │
     ││   │ │               │ │
     ││リスト│ │      配列       │ │
     ││   │ │ ┌────┐ ┌───┐  │ │
     ││   │ │ │    │ │   |  │ │
     │└───┘ │ │ベクトル│ │文字列|  │ │
     │      │ │    │ │   |  │ │
     │      │ └────┘ └───┘  │ │
     │      │ ┌────┐ ┌────┐ │ │
     │      │ │文字  │ │ブール │ │ │
     │      │ │テーブル│ │ベクトル│ │ │
     │      │ └────┘ └────┘ │ │
     │      └───────────────┘ │
     └────────────────────────┘

ベクトルやリストの要素は、どんなLispオブジェクトでもかまいません。 文字列の要素はすべて文字です。


Node:Sequence Functions, Next:, Up:Sequences Arrays Vectors

シーケンス

Emacs Lispでは、シーケンス(sequence)とはリストか配列のことです。 すべてのシーケンスに共通する性質は、 要素の順序付けた集まりであるということです。 本節では任意のシーケンスを受け付ける関数を説明します。

sequencep object Function
objectが、リスト、ベクトル、あるいは、文字列ならばtを返し、 さもなければnilを返す。

length sequence Function
この関数はsequence内の要素の個数を返す。 sequenceが(最後のCDRnilではないため) リストではないコンスセルであると、 エラーwrong-type-argumentを通知する。

関連する関数safe-lengthについては、see List Elements

(length '(1 2 3))
    => 3
(length ())
    => 0
(length "foobar")
    => 6
(length [1 2 3])
    => 3
(length (make-bool-vector 5 nil))
    => 5

elt sequence index Function
この関数はindexで添字付けされるsequenceの要素を返す。 indexの正当な値は、0からsequenceの長さより1小さい範囲の 整数である。 sequenceがリストである場合には、 範囲外のindexに対してはnilを返す。 さもなければエラーargs-out-of-rangeを引き起こす。
(elt [1 2 3 4] 2)
     => 3
(elt '(1 2 3 4) 2)
     => 3
;; stringを用いてeltが返す文字を明確にする
(string (elt "1234" 2))
     => "3"
(elt [1 2 3 4] 4)
     error--> Args out of range: [1 2 3 4], 4
(elt [1 2 3 4] -1)
     error--> Args out of range: [1 2 3 4], -1

この関数は、aref(see Array Functions)や nth(see List Elements)を汎用にしたものである。

copy-sequence sequence Function
sequenceのコピーを返す。 コピーは、もとのシーケンスと同じ型のオブジェクトであり、 同じ要素が同じ順序で入っている。

コピーに新たな要素を格納しても、もとのsequenceには影響せず、 その逆もそうである。 しかし、新たなシーケンスの要素はコピーしていない。 つまり、それらはもとの要素と同一(eq)である。 したがって、シーケンスのコピーにおいて、 それらの要素の内部を変更すると、もとのシーケンスでもその変更がわかる。

シーケンスがテキスト属性を持つ文字列である場合には、 コピーの中の属性リストそのものもコピーであり、 もとの属性リストを共有するのではない。 しかし、属性の実際の値は共有される。

シーケンスをコピーする別の方法については、 Building ListsappendCreating StringsconcatVectorsvconcatを参照。

(setq bar '(1 2))
     => (1 2)
(setq x (vector 'foo bar))
     => [foo (1 2)]
(setq y (copy-sequence x))
     => [foo (1 2)]

(eq x y)
     => nil
(equal x y)
     => t
(eq (elt x 1) (elt y 1))
     => t

;; 1つのシーケンスの1つの要素を置き換える
(aset x 0 'quux)
x => [quux (1 2)]
y => [foo (1 2)]

;; 共有された要素の内部を修正する
(setcar (aref x 1) 69)
x => [quux (69 2)]
y => [foo (69 2)]


Node:Arrays, Next:, Previous:Sequence Functions, Up:Sequences Arrays Vectors

配列

配列(array)オブジェクトには、配列の要素と呼ばれる Lispオブジェクトを保持するためのスロットがいくつかあります。 配列の任意の要素は一定時間で参照できます。 一方、リストの要素の参照には、 リスト内でのその要素の位置に比例した時間が必要です。

Emacsには4つの型の配列があり、すべて1次元です。 文字列(strings)、ベクトル(vectors)、 ブールベクトル(bool-vectors)、文字テーブル(char-tables)です。 ベクトルは汎用の配列であり、 その要素は任意のLispオブジェクトでかまいません。 文字列は特化された配列であり、その要素は文字(つまり、0から255までの整数)で ある必要があります。 配列のそれぞれの型には、独自の入力構文があります。 String TypeとSee Vector Type

配列の4つの型すべてには、以下の性質があります。

文字テーブル以外の配列を作成するときには、 その長さを指定する必要があります。 文字テーブルの長さは指定できません。 というのは、その長さは文字コードの範囲で決まるからです。

原理的には、テキスト文字の配列が必要ならば文字列かベクトルを使います。 実用上は、以下の4つの理由から、そのような場合には文字列を使います。

一方、(キー列のような)キーボード入力文字の配列には、 ベクトルが必要です。 というのは、キーボード入力文字の多くは、文字列に納まる範囲外だからです。 See Key Sequence Input


Node:Array Functions, Next:, Previous:Arrays, Up:Sequences Arrays Vectors

配列操作関数

本節では任意の配列型を受け付ける関数を説明します。

arrayp object Function
この関数はobjectが配列 (つまり、ベクトル、文字列、ブールベクトル、あるいは、文字テーブル)ならば、 tを返す。
(arrayp [a])
     => t
(arrayp "asdf")
     => t
(arrayp (syntax-table))    ;; 文字テーブル
     => t

aref array index Function
この関数はarrayindex番目の要素を返す。 最初の要素の添字は0。
(setq primes [2 3 5 7 11 13])
     => [2 3 5 7 11 13]
(aref primes 4)
     => 11
(aref "abcdefg" 1)
     => 98           ; bは、ASCIIコード98
Sequence Functionsの関数eltも参照。

aset array index object Function
この関数は配列arrayindex番目の要素にobjectを設定する。 objectを返す。
(setq w [foo bar baz])
     => [foo bar baz]
(aset w 0 'fu)
     => fu
w
     => [fu bar baz]

(setq x "asdfasfd")
     => "asdfasfd"
(aset x 3 ?Z)
     => 90
x
     => "asdZasfd"

arrayが文字列であり、かつ、objectが文字でなければ、 結果はエラーwrong-type-argumentとなる。 arrayが文字列であり、かつ、objectが文字であっても、 現在(aref object index)に保存されている文字のバイト数と objectが使うバイト数が異なれば、やはり、エラーとなる。 see Splitting Characters

fillarray array object Function
この関数は、配列arrayobjectで埋め、 arrayの各要素がobjectとなるようにする。 arrayを返す。
(setq a [a b c d e f g])
     => [a b c d e f g]
(fillarray a 0)
     => [0 0 0 0 0 0 0]
a
     => [0 0 0 0 0 0 0]
(setq s "When in the course")
     => "When in the course"
(fillarray s ?-)
     => "------------------"

arrayが文字列であり、かつ、objectが文字でなければ、 結果はエラーwrong-type-argumentになる。

配列であることが既知のオブジェクトに対しては、 汎用のシーケンス関数copy-sequencelengthがしばしば有用です。 See Sequence Functions


Node:Vectors, Next:, Previous:Array Functions, Up:Sequences Arrays Vectors

ベクトル

Lispの配列は、ほとんどの言語の配列と同様に、 その要素を一定時間で参照可能なメモリのブロックです。 ベクトル(vector)は指定長の汎用配列です。 その要素はどんなLispオブジェクトでもかまいません。 (対照的に、文字列は要素としては文字だけを保持する。) Emacsでは、オブジェクト配列obarray(シンボルのベクトル)、 キーマップ(コマンドのベクトル)の一部にベクトルを使っています。 これらは、内部的には、バイトコード関数の表現の一部にも使っています。 そのような関数を表示すると、その中にベクトルがあるのがわかります。

Emacs Lispでは、ベクトルの要素の添字は0から始まります。

ベクトルは要素を角括弧で囲んで表示します。 したがって、要素がシンボルabaであるベクトルは、 [a b a]と表示されます。 Lispへの入力では同じようにベクトルを書きます。

文字列や数と同様に、評価上、ベクトルは定数とみなします。 それを評価した結果は、同じベクトルです。 この評価では、ベクトルの要素を評価したり調べたりはしません。

以下は、これらの原理を例示するものです。

(setq avector [1 two '(three) "four" [five]])
     => [1 two (quote (three)) "four" [five]]
(eval avector)
     => [1 two (quote (three)) "four" [five]]
(eq avector (eval avector))
     => t


Node:Vector Functions, Next:, Previous:Vectors, Up:Sequences Arrays Vectors

ベクトル向け関数

ベクトルに関連した関数はつぎのとおりです。

vectorp object Function
この関数は、objectがベクトルならばtを返す。
(vectorp [a])
     => t
(vectorp "asdf")
     => nil

vector &rest objects Function
この関数は、引数objectsを要素とするベクトルを作成しそれを返す。
(vector 'foo 23 [bar baz] "rats")
     => [foo 23 [bar baz] "rats"]
(vector)
     => []

make-vector length object Function
この関数は、各要素をobjectに初期化した length個の要素から成る新たなベクトルを返す。
(setq sleepy (make-vector 9 'Z))
     => [Z Z Z Z Z Z Z Z Z]

vconcat &rest sequences Function
この関数は、sequencesのすべての要素を入れた新たなベクトルを返す。 引数sequencesは、リスト、ベクトル、文字列を含む任意の配列でよい。 sequencesを指定しないと空ベクトルを返す。

その値は、既存のベクトルとeqでない新たに作成したベクトルである。

(setq a (vconcat '(A B C) '(D E F)))
     => [A B C D E F]
(eq a (vconcat a))
     => nil
(vconcat)
     => []
(vconcat [A B C] "aa" '(foo (6 7)))
     => [A B C 97 97 foo (6 7)]

関数vconcatは、引数としてバイトコード関数でも受け付ける。 これは、バイトコード関数オブジェクトの全内容を簡単に参照できるように するための特別な機能である。 see Byte-Code Objects

関数vconcatは、引数として整数も受け付ける。 整数はその10進の表示表現の文字列に変換してから、 その文字列を整数のかわりに使う。 この機能を使わないでほしい。 削除する予定である。 読者がこの機能を使っていたら、今すぐプログラムを直すこと! 整数をこのような10進数に変換する正しい方法は、 format(see Formatting Strings)や number-to-string(see String Conversion)を使うことである。

他の連結関数については、 Mapping FunctionsmapconcatCreating StringsconcatBuilding Listsappendを参照。

関数appendは、ベクトルを同じ要素から成るリストへ変換する便利な方法です (see Building Lists)。

(setq avector [1 two (quote (three)) "four" [five]])
     => [1 two (quote (three)) "four" [five]]
(append avector nil)
     => (1 two (quote (three)) "four" [five])


Node:Char-Tables, Next:, Previous:Vector Functions, Up:Sequences Arrays Vectors

文字テーブル

文字テーブルはベクトルによく似ていますが、 文字コードで添字付けする点が異なります。 修飾子を伴わない任意の正当な文字コードは、文字テーブルの添字に使えます。 文字テーブルの要素は、任意の配列のように、arefasetで 参照できます。 さらに、文字テーブルでは、 特定の文字コードには対応しない追加データを保持するための追加スロットを 保持できます。 評価時には、文字テーブルは定数です。

各文字テーブルには、シンボルであるサブタイプ(subtype)があります。 サブタイプには2つの目的があります。 異なる使い方をする文字テーブルを区別するためと、 追加スロットの個数を制御するためです。 たとえば、表示テーブルはサブタイプがdisplay-tableである 文字テーブルであり、 構文テーブルはサブタイプがsyntax-tableである文字テーブルです。 正当なサブタイプには、char-table-extra-slots属性があるはずで、 その値は0から10までの整数です。 この整数が文字テーブルの追加スロットの個数を指定します。

文字テーブルは、別の文字テーブルであるを持てます。 その場合、特定の文字cに対する文字テーブルの指定がnilのときには、 親において指定された値を継承します。 いいかえれば、char-table自体にnilを指定してあると、 (aref char-table c)は、 char-tableの親の値を返します。

文字テーブルは、デフォルト値も持てます。 その場合、文字テーブルが指定する値がnilであると、 (aref char-table c)はデフォルト値を返します。

make-char-table subtype &optional init Function
サブタイプがsubtypeである新たに作成した文字テーブルを返す。 各要素をinitで初期化する。 なお、initのデフォルトはnilである。 文字テーブル作成後には、文字テーブルのサブタイプは変更できない。

文字テーブルの長さを指定する引数はない。 なぜなら、すべての文字テーブルでは、 任意の正当な文字コードを添字として使えるからである。

char-table-p object Function
この関数は、objectが文字テーブルならばtを返し、 さもなければnilを返す。

char-table-subtype char-table Function
この関数はchar-tableのサブタイプを表すシンボルを返す。

set-char-table-default char-table new-default Function
この関数はchar-tableのデフォルト値をnew-defaultにする。

文字テーブルのデフォルト値を参照するための特別な関数はない。 それには(char-table-range char-table nil)を使う。

char-table-parent char-table Function
この関数はchar-tableの親を返す。 親は、nilであるか他の文字テーブルである。

set-char-table-parent char-table new-parent Function
この関数はchar-tableの親をnew-parentにする。

char-table-extra-slot char-table n Function
この関数はchar-tableの追加スロットnの内容を返す。 文字テーブル内の追加スロットの個数はそのサブタイプで決まる。

set-char-table-extra-slot char-table n value Function
この関数はchar-tableの追加スロットnvalueを格納する。

文字テーブルでは、1つの文字コードに対して1つの要素値を指定できます。 また、文字集合全体に対して1つの値を指定することもできます。

char-table-range char-table range Function
これは、char-tableにおいて文字範囲rangeに指定されている値を返す。 rangeとして可能なものは以下のとおり。
nil
デフォルト値を指す。
char
charが正当な文字コードであると仮定して) 文字charに対する要素を指す。
charset
文字集合charset全体に対して指定してある値を指す (see Character Sets)。
generic-char
文字集合に対する汎用文字を表す。 引数として汎用文字を指定することは、文字集合名を指定することと同値。 汎用文字の説明は、see Splitting Characters

set-char-table-range char-table range value Function
この関数は文字範囲rangeに対するchar-tableの値を設定する。 rangeとして可能なものは以下のとおり。
nil
デフォルト値を指す。
t
文字コードの範囲全体を指す。
char
charが正当な文字コードであると仮定して) 文字charに対する要素を指す。
charset
文字集合charset全体に対して指定してある値を指す (see Character Sets)。
generic-char
文字集合に対する汎用文字を表す。 引数として汎用文字を指定することは、文字集合名を指定することと同値。 汎用文字の説明は、see Splitting Characters

map-char-table function char-table Function
この関数は、char-tableの各要素についてfunctionを呼び出す。 functionをキーと値の2つの引数で呼び出す。 キーはchar-table-rangeに対する可能なrange引数であり、 正当な文字か汎用文字である。 値は(char-table-range char-table key)である。

全体として、functionに渡すキー・値の対は、 char-tableに格納されたすべての値を表す。

戻り値はつねにnilである。 この関数が有用であるようにするには、 functionには副作用があるべきである。 たとえば、つぎは構文テーブルの各要素の調べ方である。

(let (accumulator)
  (map-char-table
   #'(lambda (key value)
       (setq accumulator
             (cons (list key value) accumulator)))
   (syntax-table))
  accumulator)
=>
((475008 nil) (474880 nil) (474752 nil) (474624 nil)
 ... (5 (3)) (4 (3)) (3 (3)) (2 (3)) (1 (3)) (0 (3)))


Node:Bool-Vectors, Previous:Char-Tables, Up:Sequences Arrays Vectors

ブールベクトル

ブールベクトルはベクトルによく似ていますが、 tnilの値だけを保存できる点が異なります。 ブールベクトルの要素にnil以外の値を保存しようとすると、 その効果はtを保存することになります。 すべての配列と同様に、ブールベクトルの添字は0から始まり、 ブールベクトルをいったん作成すると長さは変更できません。 評価時には、ブールベクトルは定数です。

ブールベクトルを操作する特別な関数は2つあります。 それに加えて、他の種類の配列を扱う関数でも操作できます。

make-bool-vector length initial Function
initialに初期化した長さlengthの新たなブールベクトルを返す。

bool-vector-p object Function
objectがブールベクトルであればtを返し、 さもなければnilを返す。


Node:Symbols, Next:, Previous:Sequences Arrays Vectors, Up:Top

シンボル

シンボル(symbol)とは、一意な名前が付いたオブジェクトです。 本章では、シンボル、その構成要素、属性リスト、作成方法とインターン方法に ついて説明します。 シンボルの変数としての使用方法、関数名としての使用方法について説明した 別の章もあります。 VariablesとSee Functions。 シンボルの正確な入力構文については、See Symbol Type

symbolpで、任意のLispオブジェクトがシンボルかどうか調べられます。

symbolp object Function
この関数は、objectがシンボルならばtを返し、 さもなければnilを返す。


Node:Symbol Components, Next:, Previous:Symbols, Up:Symbols

シンボルの構成要素

各シンボルには4つの構成要素(つまり、『セル』)があり、 それぞれで別のオブジェクトを参照します。

表示名(print name)
表示名セル(print name cell)には、 シンボルの入力や表示に使う名前である文字列が入っている。 Creating Symbolssymbol-nameを参照。
値(value)
値セル(value cell)には、 シンボルの変数としての現在値が入っている。 シンボルをフォームとして使用したとき、 フォームの値はシンボルの値セルの内容である。 Accessing Variablessymbol-valueを参照。
関数(function)
関数セル(function cell)には、シンボルの関数定義が入っている。 シンボルを関数として使用したとき、その関数定義を使う。 シンボルが、編集コマンドを実行するためのキーマップやキーボードマクロを 表すときもこのセルを使う。 各シンボルには値セルと関数セルが別々にあるので、 変数名と関数名は衝突しない。 Function Cellssymbol-functionを参照。
属性リスト(property list)
属性リストセル(property list cell)には、 シンボルの属性リストが入っている。 Property Listssymbol-plistを参照。

表示名セルはつねに文字列を保持していて、変更できません。 他の3つのセルには、任意の指定したLispオブジェクトを個別に設定できます。

表示名セルは、シンボルの名前である文字列を保持しています。 シンボルはテキスト上はその名前で表現されるので、 2つのシンボルが同じ名前を持たないことが重要です。 Lispリーダがこのことを保証します。 シンボルを読み取るたびに、新たにシンボルを作成するまえに、 指定した名前のシンボルが存在するかどうか調べます。 (GNU Emacs Lispでは、これにはハッシュアルゴリズムと オブジェクト配列obarrayを使う。 see Creating Symbols。)

普通の使い方では、関数セルには関数(see Functions)や マクロ(see Macros)が入っていて、 Lispインタープリタはそのように仮定します(see Evaluation)。 シンボルの関数セルには、 キーボードマクロ(see Keyboard Macros)、キーマップ(see Keymaps)、 自動ロードオブジェクト(see Autoloading)が入っていることもあります。 『関数foo』といった場合、実際には、シンボルfooの関数セルに 入っている関数を意味します。 必要な場合に限って区別します。

属性リストセルは、通常、正しい形式の属性リスト(see Property Lists)が 入っている必要があり、さまざまな関数がそのように仮定しています。

関数セルや値セルは(void)でもかまいません。 つまり、セルはどんなオブジェクトも指していません。 (このことは、シンボルvoidを保持しているとか、 シンボルnilを保持しているのとは違う。) 空である関数セルや値セルを参照すると、 その結果はSymbol's value as variable is void (「変数としてのシンボルの値は空」)のようなエラーになります。

4つの関数、symbol-namesymbol-valuesymbol-plistsymbol-functionは、 シンボルの4つのセルの内容を返します。 以下に、シンボルbuffer-file-nameの 4つのセルの内容を表示する例を示します。

(symbol-name 'buffer-file-name)
     => "buffer-file-name"
(symbol-value 'buffer-file-name)
     => "/gnu/elisp/symbols.texi"
(symbol-plist 'buffer-file-name)
     => (variable-documentation 29529)
(symbol-function 'buffer-file-name)
     => #<subr buffer-file-name>

このシンボルは、カレントバッファで訪問しているファイルの名前を保持するので、 値セルの内容は本書Emacs Lispマニュアルの本章のソースファイルの名前です。 属性リストセルには、リスト(variable-documentation 29529)が入っていて、 ドキュメント関数に対してファイルDOC-versionのどこに 変数buffer-file-nameの説明文字列が入っているか伝えます。 (29529は、当該説明文字列の開始位置を表す DOC-versionの先頭からのオフセット。 Documentation Basicsを参照。) 関数セルには、ファイルの名前を返す関数が入っています。 buffer-file-nameは基本関数の名前です。 これには入力構文はなく、 ハッシュ記法(see Primitive Function Type)で表示されています。 Lispで書いた関数を表すシンボルでは、 このセルにラムダ式(あるいはバイトコードオブジェクト)が入っています。


Node:Definitions, Next:, Previous:Symbol Components, Up:Symbols

シンボルを定義する

Lispにおける定義(definition)とは、 特定のシンボルをどのように使うかを意思表示するスペシャルフォームです。 Emacs Lispでは、シンボルを変数と定義したり、 関数(あるいはマクロ)と定義したり、あるいは、それらを独立に定義できます。

定義を行う構文では、典型的には、値を指定したり、 シンボルを特定の使い方をすると指定したりし、 さらに、そのような使い方をしたときの意味を表すための説明文字列を指定します。 したがって、シンボルを変数として定義するときには、 変数に初期値を与え、その変数の説明文字列を指定できます。

defvardefconstは、シンボルをグローバル変数として定義する スペシャルフォームです。 これらはDefining Variablesで詳しく説明してあります。 カスタマイズ可能なようにユーザーオプション用の変数を定義するには、 defcustom(see Customization)を使います。

defunは、シンボルを関数として定義し、 ラムダ式を作ってシンボルの関数セルに格納します。 したがって、このラムダ式がシンボルの関数定義になります。 (用語『関数定義』は、関数セルの内容を意味し、 defunがシンボルに関数としての定義を与えることからきている。) defsubstdefaliasは、関数を定義する別の2つの方法です。 See Functions

defmacroは、シンボルをマクロとして定義します。 マクロオブジェクトを作ってシンボルの関数セルに格納します。 シンボルは、マクロか関数のいずれかであって、 同時に両方にはならないことに注意してください。 というのは、マクロ定義も関数定義も関数セルに収められ、 そのセルにはどんなときでもたった1つのLispオブジェクトしか 保持できないからです。 See Macros

Emacs Lispでは、シンボルを変数や関数として使うための 定義は必須ではありません。 したがって、シンボルをあらかじめ定義しようがしまいが、 setqを使ってシンボルをグローバル変数にできます。 定義の真の目的は、プログラマに対する指針であり、プログラミングツールなのです。 これらは、コードを読むプログラマに対して、 特定のシンボルを変数として使うのか関数として使うのか、 その意図を伝えます。 さらに、etagsmake-docfileなどのユーティリティは、 定義を認識してタグテーブルやファイルDOC-versionに 適切な情報を追加します。 See Accessing Documentation


Node:Creating Symbols, Next:, Previous:Definitions, Up:Symbols

シンボルの作成とインターン

GNU Emacs Lispにおいて、どのようにシンボルを作成するかを理解するには、 Lispがそれらをどのように読むかを知る必要があります。 Lispは、同じ文字群を読み取るたびに、同じシンボルをみつけることを保証する 必要があります。 これに失敗すると完全に混乱します。

Lispリーダがシンボルに出会うと、名前の文字群をすべて読み取ります。 そして、これらの文字群を『ハッシュ化』して、 オブジェクト配列(obarray)と呼ばれる表の添字を探します。 ハッシュ化は効率的に探索する手法です。 たとえば、Jan Jonesを電話番号簿の表紙から1ページずつ順に探すかわりに、 Jのページから探し始めます。 これは単純なハッシュ化です。 オブジェクト配列の各要素は、 あるハッシュコードを有するすべてのシンボルを格納した バケット(bucket)です。 ある名前を探すには、その名前のハッシュコードに対応するバケット内の すべてのシンボルを調べるだけで十分です。

目的の名前のシンボルがみつかれば、リーダはそのシンボルを使います。 オブジェクト配列に目的の名前のシンボルがなければ、 リーダは新たなシンボルを作成し、それをオブジェクト配列に追加します。 ある名前のシンボルを探したり追加することをシンボルを インターン(interning)するといい、 そのシンボルをインターンしたシンボル(interned symbol)と呼びます。

インターンすることで、各オブジェクト配列には 特定の名前のシンボルが1個だけあることを保証します。 他の似たような名前のシンボルが存在しても、 同じオブジェクト配列には入っていません。 したがって、同じオブジェクト配列を使って読む限り、 リーダは同じ名前に対して同じシンボルを得ることができます。

すべてのシンボルがオブジェクト配列に入っているとは限りません。 実際、どのオブジェクト配列にも属さないシンボルがいくつかあります。 これらをインターンしてないシンボル(uninterned symbols)と呼びます。 インターンしてないシンボルにも、他のシンボルと同様に4つのセルがあります。 しかし、それを参照する手段は、他のオブジェクトを介して探すか、 変数の値として探すしかありません。

Emacs Lispでは、オブジェクト配列は実際にはベクトルです。 ベクトルの各要素はバケットです。 その値は、そのバケットにハッシュ化される名前のインターンしたシンボルであるか、 そのバケットが空ならば0です。 インターンした各シンボルには、バケットのつぎのシンボルを指す (ユーザーには見えない)内部的なリンクがあります。 このリンクは見えないので、mapatoms(下記)を使う以外には、 オブジェクト配列内のすべてのシンボルを探す方法はありません。 バケット内でのシンボルの順序は関係ありません。

空のオブジェクト配列では、各要素は0です。 (make-vector length 0)でオブジェクト配列を作成できます。 これは、オブジェクト配列を作成する唯一の正当な方法です。 長さとして素数を用いると、ハッシュ化の結果がよい傾向があります。 2の巾より1小さい長さもよい結果になります。

読者自身でオブジェクト配列にシンボルを入れないでください。 うまくいきません。 オブジェクト配列にシンボルを正しく入れられるのはinternだけです。

Common Lispに関した注意: Common Lispでは、1つのシンボルを複数のオブジェクト配列に入れることができる。

下記の関数のほとんどは、引数に名前を取り、 場合によってはオブジェクト配列を引数に取ります。 名前が文字列でなかったり、オブジェクト配列がベクトルでないと、 エラーwrong-type-argumentを通知します。

symbol-name symbol Function
この関数は、symbolの名前を表す文字列を返す。 たとえば、つぎのとおり。
(symbol-name 'foo)
     => "foo"

警告: 文字列の文字を置き換えるとシンボルの名前を変更するが、 オブジェクト配列は更新できないので変更しないこと!

make-symbol name Function
この関数は、name(文字列であること)を名前とする 新たに割り付けたインターンしていないシンボルを返す。 その値と関数定義は空であり、属性リストはnilである。 以下の例では、symの値はfooeqではない。 なぜなら、名前はfooではあるが、 インターンしていない別のシンボルであるため。
(setq sym (make-symbol "foo"))
     => foo
(eq sym 'foo)
     => nil

intern name &optional obarray Function
この関数は、nameを名前とするインターンしたシンボルを返す。 そのようなシンボルがオブジェクト配列obarrayに存在しなければ、 internは新たなものを作成し、それをオブジェクト配列に追加してから、 それを返す。 obarrayを省略すると、グローバル変数obarrayの値を使う。
(setq sym (intern "foo"))
     => foo
(eq sym 'foo)
     => t

(setq sym1 (intern "foo" other-obarray))
     => foo
(eq sym 'foo)
     => nil

Common Lispに関した注意: Common Lispでは、既存のシンボルをオブジェクト配列にインターンできる。 Emacs Lispでは、これはできない。 なぜなら、internの引数は文字列である必要があり、 シンボルではない。

intern-soft name &optional obarray Function
この関数は、obarray内のnameを名前とするシンボルを返す。 ただし、その名前のシンボルがobarrayになければnilを返す。 したがって、intern-softを用いて、指定した名前のシンボルが インターンされているかどうか調べられる。 obarrayを省略すると、グローバル変数obarrayの値を使う。
(intern-soft "frazzle")        ; そのようなシンボルは存在しない
     => nil
(make-symbol "frazzle")        ; インターンしないものを作る
     => frazzle
(intern-soft "frazzle")        ; そのようなものはみつからない
     => nil
(setq sym (intern "frazzle"))  ; インターンしたものを作る
     => frazzle
(intern-soft "frazzle")        ; そのようなものがみつかった!
     => frazzle
(eq sym 'frazzle)              ; しかも、それらは同一
     => t

obarray Variable
この変数は、internreadが使う標準のオブジェクト配列。

mapatoms function &optional obarray Function
この関数は、オブジェクト配列obarrayの各シンボルについて、 1回ずつfunctionを呼び出す。 そして、nilを返す。 obarrayを省略すると、通常のシンボル向けの標準のオブジェクト配列である obarrayの値をデフォルトにする。
(setq count 0)
     => 0
(defun count-syms (s)
  (setq count (1+ count)))
     => count-syms
(mapatoms 'count-syms)
     => nil
count
     => 1871

mapatomsを使った別の例については、 Accessing Documentationdocumentationを参照。

unintern symbol &optional obarray Function
この関数は、オブジェクト配列obarrayからsymbolを削除する。 symbolが実際にはオブジェクト配列内になければ、 uninternはなにもしない。 obarraynilであると、現在のオブジェクト配列を使う。

symbolのシンボルのかわりに文字列を指定すると、 それはシンボルの名前を表す。 そして、uninternはその名前のシンボルを(あれば)オブジェクト配列から 削除する。 そのようなシンボルがなければ、uninternはなにもしない。

uninternは、シンボルを削除したときにはtを返す。 さもなければnilを返す。


Node:Property Lists, Previous:Creating Symbols, Up:Symbols

属性リスト

属性リスト(property list、略してplist)とは、 シンボルの属性リストセルに格納された対になった要素から成るリストです。 各対は、属性名(通常、シンボル)を属性、すなわち、属性値に対応付けます。 属性リストは、一般に、シンボルに関する情報を記録します。 変数としての説明文字列、定義されているファイルの名前、 言語理解システムにおいては(語を表す)シンボルの文法クラスなどです。

文字列内やバッファ内の文字位置も属性リストを持てます。 See Text Properties

属性リスト内の属性名と属性値は、任意のLispオブジェクトでかまいませんが、 普通、属性名はシンボルです。 属性リスト関数は、eqを使って属性名を比較します。 コンパイラをロードした際のシンボルprognの属性リストをつぎに示します。

(lisp-indent-function 0 byte-compile byte-compile-progn)

ここで、lisp-indent-functionbyte-compileは属性名であり、 他の2つの要素は対応する属性値です。


Node:Plists and Alists, Next:, Up:Property Lists

属性リストと連想リスト

連想リスト(see Association Lists)は、 属性リストに非常によく似ています。 連想リストと異なり、属性名は一意である必要があるので、 属性リスト内での対の出現順序は関係ありません。

さまざまなLisp関数やLisp変数に情報を付加するには、 属性リストは連想リストより優れています。 読者のプログラムで1つの連想リストにすべての連想を入れておいたとすると、 1つの連想を探すたびに、リスト全体を探索する必要があります。 これには時間がかかります。 一方、同じ情報を関数名や変数自身の属性リストに保持しておけば、 各探索では1つの属性リストを走査するだけでよく、 属性リストは、普通、短いものです。 このため、変数の説明文字列をvariable-documentationという名前の 属性に記録しているのです。 同様に、バイトコンパイラも、 特別な処理が必要な関数を属性を使って記録しています。

しかしながら、連想リストにもそれ独自の利点があります。 読者のアプリケーションに依存しますが、 属性を更新するより、連想リストの先頭に連想を追加するほうが速いです。 あるシンボルのすべての属性は同一の属性リストに格納してあるので、 1つの属性名を異なる目的に使うと衝突します。 (この理由から、プログラムで普通に使う 変数名や関数名の接頭辞で始まる属性名を選ぶなどして、 一意な属性名を選ぶのがよい。) 連想リストは、リストの先頭に要素を追加し、先頭から要素を削除するので、 スタックのように使えます。 属性リストでは、これは不可能です。


Node:Symbol Plists, Next:, Previous:Plists and Alists, Up:Property Lists

シンボル向け属性リスト関数

symbol-plist symbol Function
この関数はsymbolの属性リストを返す。

setplist symbol plist Function
この関数は、symbolの属性リストをplistとする。 通常、plistは正しい形の属性リストであるべきだが強要されない。
(setplist 'foo '(a 1 b (2 3) c nil))
     => (a 1 b (2 3) c nil)
(symbol-plist 'foo)
     => (a 1 b (2 3) c nil)

普通の使い方を意図していない特別なオブジェクト配列内のシンボルに対しては、 属性リストセルの非標準な使い方にも意味があろう。 実際、略語機構(see Abbrevs)ではそのようにしている。

get symbol property Function
この関数は、symbolの属性リストから propertyという名前の属性の値を探す。 そのような属性がなければ、nilを返す。 つまり、nilという値と属性の欠如を区別できない。

名前propertyは既存の属性名とeqで比較するため、 どんなオブジェクトでも正当な属性である。

例については、putを参照。

put symbol property value Function
この関数は、symbolの属性リストにおいて、 属性名propertyの古い属性値をvalueで置き換える。 関数putvalueを返す。
(put 'fly 'verb 'transitive)
     =>'transitive
(put 'fly 'noun '(a buzzing little bug))
     => (a buzzing little bug)
(get 'fly 'verb)
     => transitive
(symbol-plist 'fly)
     => (verb transitive noun (a buzzing little bug))


Node:Other Plists, Previous:Symbol Plists, Up:Property Lists

シンボルの外部の属性リスト

シンボル以外の場所に保存した属性リストの操作に便利な2つの関数があります。

plist-get plist property Function
これは、属性リストplistに保存されている属性propertyの値を返す。 たとえば、つぎのとおり。
(plist-get '(foo 4) 'foo)
     => 4

plist-put plist property value Function
これは、属性リストplistに、 propertyの値としてvalueを格納する。 これはplistを破壊的に変更するか、あるいは、 古いものを変更せずに新たなリスト構造を構築する。 関数は変更した属性リストを返すので、 plistを保持していたところへ保存し直せる。 たとえば、つぎのとおり。
(setq my-plist '(bar t foo 4))
     => (bar t foo 4)
(setq my-plist (plist-put my-plist 'foo 69))
     => (bar t foo 69)
(setq my-plist (plist-put my-plist 'quux '(a)))
     => (bar t foo 69 quux (a))

つぎのようにして、plist-putを用いてputを定義できます。

(defun put (symbol prop value)
  (setplist symbol
            (plist-put (symbol-plist symbol) prop value)))


Node:Evaluation, Next:, Previous:Symbols, Up:Top

評価

Emacs Lispにおける式の評価(evaluation)は、 Lispインタープリタ(Lisp interpreter)が行います。 これは、入力としてLispオブジェクトを受け取り、 式としての値を計算するプログラムです。 計算方法は、本章で述べる規則に従ってオブジェクトのデータ型に依存します。 インタープリタは、読者のプログラムのある部分を評価するために 自動的に動作しますが、Lisp基本関数evalを介して インタープリタを明示的に呼ぶ出すこともできます。

評価することを意図したLispオブジェクトを (expression)とかフォーム(form)と呼びます。 式はデータオブジェクトであり単なるテキストではないという事実は、 Lisp様言語と典型的なプログラム言語との基本的な違いの1つです。 どんなオブジェクトでも評価できますが、実用上は、 数、シンボル、リスト、文字列を評価することが多いのです。

Lisp式を読み取りその式を評価することはとても一般的なことですが、 読み取りと評価は別々の動作であり、それぞれを別々に実行することもできます。 読み取り自体では、なにも評価しません。 Lispオブジェクトの表示表現をオブジェクトそのものに変換します。 このオブジェクトを評価すべきフォームとするか、 まったく別の目的に使うかは、readの呼び出し側で決まります。

評価とコマンドキーの解釈を混同しないでください。 エディタコマンドループは、有効なキーマップを用いて キーボード入力をコマンド(対話的に呼び出し可能な関数)に変換し、 call-interactivelyを使ってコマンドを起動します。 コマンドがLispで書いてあれば、 コマンド自体の実行には評価が関わってきますが、 そのことは、コマンドキーの解釈自体には含まれていません。

評価は再帰的な処理です。 つまり、フォームの評価では、 evalを呼び出してそのフォームの一部分を評価することもあります。 たとえば、関数呼び出しの評価においては、まず、 関数呼び出しの各引数を評価してから、関数本体の各フォームを評価します。 (car x)の評価を考えてみましょう。 まず最初にxを再帰的に評価する必要があります。 その値を関数carの引数として渡せるようにするのです。

関数呼び出しの評価においては、最終的に指定した関数を呼び出します。 See Functions。 関数の実行そのものも、関数定義を評価する場合もあります。 あるいは、関数はC言語で実装されたLisp基本関数かもしれませんし、 バイトコード関数かもしれません(see Byte Compilation)。

フォームの評価は、環境(environment)と呼ばれる文脈において 行われます。 環境とは、すべてのLisp変数の現在値と束縛です 7。 フォームが新たな束縛を作らずに変数を参照する場合には、 現在の環境におけるその変数の束縛の値を使います。 See Variables

フォームを評価すると、変数(see Local Variables)を束縛して、 再帰的評価のための新たな環境を作ることがあります。 これらの環境は一時的なもので、そのフォームの評価を完了すると 消えてしまいます。 フォームは恒久的な変更を行ってもかまいません。 このような変更を副作用(side effects)と呼びます。 副作用を持つフォームの例は、(setq foo 1)です。

フォームの各種類ごとの評価の意味の詳細は、 以下で説明します(see Forms)。


Node:Forms

フォームの種類

評価することを意図したLispオブジェクトをフォーム(form)と呼びます。 Emacsがどのようにフォームを評価するかは、そのデータ型に依存します。 Emacsには、評価方法が異なる3種類のフォームがあります。 シンボル、リスト、および、『その他すべての型』です。 本節では、3種類すべてについて1つ1つ説明します。 まず、自己評価型フォームである『その他すべての型』から説明します。


Node:Self-Evaluating Forms, Next:, Up:Forms

自己評価型フォーム

自己評価型フォーム(self-evaluating form)とは、 リストでもシンボルでもない任意のフォームのことです。 自己評価型フォームはそれ自身に評価され、 評価結果は評価されるオブジェクトと同じものです。 つまり、数25は25と評価され、 文字列"foo"は文字列"foo"と評価されます。 同様に、ベクトルを評価してもベクトルの個々の要素を評価することはありません。 その内容をまったく変更することなく、同じベクトルを返します。

'123               ; 評価していない数
     => 123
123                ; 普通どおり評価。結果は同じ
     => 123
(eval '123)        ; 『手で』評価。結果は同じ
     => 123
(eval (eval '123)) ; 2回評価してもなにも変わらない
     => 123

Lispコードにおいては、数、文字、文字列、さらにベクトルでさえも、 それらが自己評価型である事実を利用して書くのが普通です。 しかし、入力構文を持たない型については、このようにしません。 というのは、それらをテキストとして書く方法がないからです。 そのような型を含むLisp式を構成するには、Lispプログラムを使います。

;; バッファオブジェクトを含む式を作る
(setq print-exp (list 'print (current-buffer)))
     => (print #<buffer eval.texi>)
;; それを評価する
(eval print-exp)
     -| #<buffer eval.texi>
     => #<buffer eval.texi>


Node:Symbol Forms, Next:, Previous:Self-Evaluating Forms, Up:Forms

シンボルフォーム

シンボルを評価するときには、シンボルを変数として扱います。 その結果は、値があれば、変数の値です。 (値セルが空であり)値がなければ、エラーを通知します。 変数の使い方について詳しくは、See Variables

つぎの例では、setqを使ってシンボルの値を設定します。 そのあとでシンボルを評価すると、setqで保存した値を取り出せます。

(setq a 123)
     => 123
(eval 'a)
     => 123
a
     => 123

シンボルniltは特別に扱い、 nilの値はつねにnilであり、 tの値はつねにtです。 これらに別の値を設定したり、別の値を束縛することはできません。 したがって、evalはこれらを他のシンボルと同様に扱いますが、 これら2つのシンボルは自己評価型フォームのようにふるまいます。 :で始まる名前のシンボルも同じ意味で自己評価型であり、 同様に、その値を変更できません。 See Constant Variables


Node:Classifying Lists, Next:, Previous:Symbol Forms, Up:Forms

リストフォームの分類

フォームが空ではないリストならば、その最初の要素に依存して、 関数呼び出し、マクロ呼び出し、スペシャルフォームのいずれかです。 これらの3種類のフォームは、以下に説明するように、異なる方法で評価されます。 リストの残りの要素は、関数、マクロ、スペシャルフォームの 引数(arguments)になります。

空ではないリストを評価する最初の手順は、 その先頭要素を調べることです。 この要素は、それだけで、空ではないリストのフォームの種類を決定し、 リストの残りをどのように処理するかを決定します。 SchemeなどのLispの一部の方言と違って、先頭要素は評価しません


Node:Function Indirection, Next:, Previous:Classifying Lists, Up:Forms

シンボルの関数間接

リストの先頭要素がシンボルであると、 評価処理ではシンボルの関数セルを調べ、 もとのシンボルのかわりにその内容を使います。 その内容が別のシンボルであると、 シンボルの関数間接(symbol function indirection)と呼ばれる この処理をシンボルでないものを得るまで繰り返します。 シンボルの関数セルに格納された関数名としてのシンボルの使い方について 詳しくは、See Function Names

この処理の結果、無限ループになる場合もあります。 つまり、シンボルの関数セルが同じシンボルを指している場合です。 あるいは、シンボルの関数セルが空の場合もありえます。 その場合、サブルーティンsymbol-functionは、 エラーvoid-functionを通知します。 いずれの場合でもなければ、最終的にはシンボルでないものを取得し、 それは関数などの適切なオブジェクトであるはずです。

より正確にいえば、Lisp関数(ラムダ式)、バイトコード関数、 基本関数、Lispマクロ、スペシャルフォーム、自動ロードオブジェクトの いずれかを取得しているはずです。 これらの各種類ごとに、以下の1つ1つの節で説明します。 オブジェクトがこれらのいずれの型でもない場合には、 エラーinvalid-functionを通知します。

つぎの例は、シンボルの関数間接の処理を図示したものです。 fsetを使ってシンボルの関数セルに設定し、 symbol-functionを使って関数セルの内容を取り出します (see Function Cells)。 具体的には、シンボルcarfirstの関数セルに格納し、 シンボルfirstersteの関数セルに格納します。

;; このような関数セルのリンクを作る
;;   -------------       -----        -------        -------
;;  | #<subr car> | <-- | car |  <-- | first |  <-- | erste |
;;   -------------       -----        -------        -------
(symbol-function 'car)
     => #<subr car>
(fset 'first 'car)
     => car
(fset 'erste 'first)
     => first
(erste '(1 2 3))   ; ersteが指す関数を呼び出す
     => 1

一方、つぎの例では、シンボルの関数間接を使わずに関数を呼び出します。 というのは、先頭引数はLispの無名関数であって、 シンボルではないからです。

((lambda (arg) (erste arg))
 '(1 2 3))
     => 1

関数を実行することは、その本体を評価することです。 この過程では、ersteを呼び出すときにシンボルの関数間接が関わります。

組み込み関数indirect-functionは、 明示的にシンボルの関数間接を行う簡単な方法です。

indirect-function function Function
この関数は、関数としてのfunctionの意味を返す。 functionがシンボルであればfunctionの関数定義を探し、 その値から再度繰り返す。 functionがシンボルでなければfunctionそのものを返す。

Lispでindirect-functionを定義するとつぎのようになる。

(defun indirect-function (function)
  (if (symbolp function)
      (indirect-function (symbol-function function))
    function))


Node:Function Forms, Next:, Previous:Function Indirection, Up:Forms

関数フォームの評価

評価すべきリストの先頭要素が、Lisp関数オブジェクト、 バイトコードオブジェクト、基本関数オブジェクトの場合、 そのリストは関数呼び出し(function call)です。 たとえば、つぎは、関数+の呼び出しです。

(+ 1 x)

関数呼び出しを評価する最初の手順は、 リストの残りの要素を左から右へ順に評価することです。 その結果は実引数の値になり、1つの値がリストの1つの要素に対応します。 つぎの手順は、引数のリストで関数を呼び出すことで、 実質的には、関数apply(see Calling Functions)を使います。 関数がLispで書いてあれば、関数の引数変数を束縛するために引数を使います (see Lambda Expressions)。 そして、関数本体のフォーム群を順番に評価し、 本体の最後のフォームの値が関数呼び出しの値になります。


Node:Macro Forms, Next:, Previous:Function Forms, Up:Forms

Lispマクロの評価

評価すべきリストの先頭要素がマクロオブジェクトの場合、 そのリストはマクロ呼び出し(macro call)です。 マクロ呼び出しを評価するときは、リストの残りの要素を評価しません。 そのかわりに、要素そのものをマクロの引数として使います。 マクロ定義は、 マクロの展開形(expansion)と呼ばれる置換フォームを計算し、 もとのフォームのかわりに展開形を評価します。 展開形は、どんな種類のフォームでもかまいません。 自己評価型の定数、シンボル、あるいは、リストです。 展開形そのものがマクロ呼び出しであると、 マクロ呼び出し以外のフォームを得られるまで、 展開形を得る処理を繰り返します。

通常のマクロ呼び出しの評価は、展開形を評価することで完了します。 しかし、マクロの展開形を必ずしもただちに評価する必要はなく、 まったく評価しなくてもかまいません。 というのは、別のプログラムもマクロ呼び出しを展開し、 それらは展開形を評価するものもあれば、評価しないものもあるからです。

普通、引数の式は、マクロ展開の計算過程では評価せず、 展開形の一部として現れます。 そして、展開形を評価するときに引数が計算されます。

たとえば、つぎのようなマクロ定義があったとします。

(defmacro cadr (x)
  (list 'car (list 'cdr x)))

(cadr (assq 'handler list))のような式はマクロ呼び出しであり、 つぎのような展開形になります。

(car (cdr (assq 'handler list)))

引数(assq 'handler list)が展開形に現れていることに 注意してください。

Emacs Lispのマクロに関する完全な記述は、See Macros


Node:Special Forms, Next:, Previous:Macro Forms, Up:Forms

スペシャルフォーム

スペシャルフォーム(special form)は、 その引数を評価しないように特別な印が付いた基本関数です。 ほとんどのスペシャルフォームは、制御構造を定義したり、 変数を束縛したりします。 これらはどれも関数ではできないことです。

各スペシャルフォームには、どの引数は評価し、 どの引数は評価せずに使うかといったそれぞれに独自の規則があります。 特定の引数を評価するかどうかは、他の引数の評価結果に依存することもあります。

以下に、Emacs Lispのすべてのスペシャルフォームをアルファベット順に、 参照箇所とともにあげておきます。

and
see Combining Conditions
catch
see Catch and Throw
cond
see Conditionals
condition-case
see Handling Errors
defconst
see Defining Variables
defmacro
see Defining Macros
defun
see Defining Functions
defvar
see Defining Variables
function
see Anonymous Functions
if
see Conditionals
interactive
see Interactive Call
let
let*
see Local Variables
or
see Combining Conditions
prog1
prog2
progn
see Sequencing
quote
see Quoting
save-current-buffer
see Current Buffer
save-excursion
see Excursions
save-restriction
see Narrowing
save-window-excursion
see Window Configurations
setq
see Setting Variables
setq-default
see Creating Buffer-Local
track-mouse
see Mouse Tracking
unwind-protect
see Nonlocal Exits
while
see Iteration
with-output-to-temp-buffer
see Temporary Displays
Common Lispに関した注意: GNU Emacs LispとCommon Lispのスペシャルフォームを比較してみる。 setqif、および、catchは、Emacs Lispでも Common Lispでもスペシャルフォームである。 defunは、Emacs Lispではスペシャルフォームであるが、 Common Lispではマクロである。 save-excursionは、Emacs Lispではスペシャルフォームであるが、 Common Lispには存在しない。 throwは、Common Lispでは(複数の値を返す必要があるため) スペシャルフォームであるが、 Emacs Lispでは(複数の値はないため)関数である。


Node:Autoloading, Previous:Special Forms, Up:Forms

自動ロード

自動ロード(autoload)は、 関数やマクロの関数定義をEmacsにまだロードしていなくても、 関数やマクロを呼び出せるようにする機構です。 定義を収めたファイルを指定します。 シンボルの関数定義に自動ロードオブジェクトあるとき、 そのシンボルを関数として呼び出すと、指定したファイルを自動的にロードします。 そうしてから、当該ファイルからロードした実際の定義を呼び出します。 See Autoload


Node:Quoting

クォート

スペシャルフォームquoteは、単一の引数を 評価せずに書かれたとおりに返します。 これは、自己評価型オブジェクトではない 定数シンボルや定数リストをプログラム内に書く手段です。 (数、文字列、ベクトルなどの自己評価型オブジェクトをクォートする必要はない。)

quote object Special Form
このフォームはobjectを評価せずに返す。

quoteはプログラム内で頻繁に使うので、 Lispには便利な入力構文が用意してあります。 アポストロフ文字(')に続けた(入力構文で書いた)Lispオブジェクトは、 先頭要素がquoteであり2番目の要素がそのオブジェクトである リストに展開されます。 したがって、入力構文'xは、(quote x)の省略形です。

quoteを使った式の例をいくつかあげておきます。

(quote (+ 1 2))
     => (+ 1 2)
(quote foo)
     => foo
'foo
     => foo
''foo
     => (quote foo)
'(quote foo)
     => (quote foo)
['foo]
     => [(quote foo)]

他のクォートの書き方には、function(see Anonymous Functions)が あります。 これは、Lispで書いた無名ラムダ式をコンパイルするようにします。 また、`(see Backquote)は、 リストの一部分をクォートし、他の部分は計算結果で置き換えるために使います。


Node:Eval

評価(eval)

ほとんどの場合、実行中のプログラムにフォームが現れると フォームは自動的に評価されます。 稀なことですが、実行時に計算したフォームを評価するように コードを書く必要があるかもしれません。 たとえば、編集中のテキストからフォームを読み取ったり、 属性リストからフォームを取り出した場合などです。 このような場合には、関数evalを使います。

本節で説明した関数や変数は、フォームを評価したり、 評価処理に制限を課したり、最後の戻り値を記録したりします。 ファイルをロードしても評価が行われます(see Loading)。

注意: データ構造の中に関数を格納して それをfuncallapplyで呼び出すほうが、 データ構造の中に式を格納してそれを評価するより、 一般に明確で柔軟性があります。 関数を使うとそれらに引数として情報を渡すことができます。

eval form Function
この関数は、式を評価する基本的な関数である。 formを現在の環境において評価し、その結果を返す。 評価処理はオブジェクトの型に依存する(see Forms)。

evalは関数なので、evalの呼び出しに現れる 引数の式は2度評価される。 evalを呼び出すまえの準備で1回、 関数eval自身による評価でもう1回である。 例を示す。

(setq foo 'bar)
     => bar
(setq bar 'baz)
     => baz
;; evalは引数fooを受け取る
(eval 'foo)
     => bar
;; evalは引数barを受け取る。それはfooの値
(eval foo)
     => baz

evalの呼び出しの深さは、 max-lisp-eval-depth(下記参照)に制限される。

eval-region start end &optional stream read-function コマンド
この関数は、カレントバッファのstartendで指定した リージョン内のフォーム群を評価する。 リージョンからフォームを読み取り、 それらに対してevalを呼び出すことを リージョンの末尾に達するまで、あるいは、処理されないエラーが通知されるまで 繰り返す。

streamnil以外ならば、 リージョン内の式を評価した結果の値はstreamを使って表示する。 see Output Streams

read-functionnil以外にならば、 それは関数である必要があり、 readのかわりに式を1つ1つ読むために使われる。 この関数は、入力用のストリームである1つの引数で呼び出される。 変数load-read-function(see How Programs Do Loading)を 使ってこの関数を指定することもできるが、 引数read-functionを用いたほうが堅牢である。

eval-regionはつねにnilを返す。

eval-current-buffer &optional stream コマンド
これはeval-regionと同様だが、バッファ全体に作用する。

max-lisp-eval-depth Variable
この変数は、 (エラーメッセージ"Lisp nesting exceeds max-lisp-eval-depth"で) エラーを通知までのevalapplyfuncallの呼び出しの 最大の深さを制限する。 この制限、および、これを超えたときのエラーは、 不正に定義された関数によってLispが無限に再帰することを防止する 1つの方法である。

深さ制限は、Lispコードによる明示的な呼び出しに加えて、 Lisp式で書かれた関数の呼び出しや関数呼び出しの引数や関数本体のフォームの 再帰的な評価などの内部的なevalapplyfuncallの 呼び出しも数える。

この変数のデフォルト値は300。 これに100未満の値を設定すると、指定した値に達するとLispは100に設定し直す。 Lispデバッガに入ったとき、 制限に近い場合にはデバッガ自身が実行できることを保証するために値を増やす。

max-specpdl-sizeは、入れ子の深さを制限する別の方法である。 see Local Variables

values Variable
この変数の値は、 バッファから式を読み取り、評価し、結果を表示するEmacsの標準コマンドが行った すべての式の戻り値のリストである。 リストの順序は、最新のものが最初にくる。
(setq x 1)
     => 1
(list 'A (1+ 2) auto-save-default)
     => (A 3 t)
values
     => ((A 3 t) 1 ...)

この変数は、最近評価したフォームの値を参照するのに便利である。 valuesそのものの値の表示は非常に長くなる可能性があるので、 その値を表示するのはよくない。 そのかわりに、つぎのようにして特定の要素を調べる。

;; もっとも最近の評価結果を参照する
(nth 0 values)
     => (A 3 t)
;; こうすると、新たな要素が追加され、
;;   すべての要素が1つうしろへさがる
(nth 1 values)
     => (A 3 t)
;; この例を実行するまえの最新のもののつぎの要素を取得する
(nth 3 values)
     => 1


Node:Control Structures, Next:, Previous:Evaluation, Up:Top

制御構造

Lispプログラムは、式、すなわち、フォーム(forms、see Forms)から 成ります。 フォームを制御構造(control structures)で囲むことで、 フォームの実行順序を制御します。 制御構造はスペシャルフォームであり、 その内側にあるフォームの実行をいつ行うか、行わないか、 何回行うかを制御します。

もっとも単純な実行順序は逐次実行です。 最初のフォームaを実行し、 それからつぎのフォームbを実行し、といった具合です。 関数の本体やLispコードのファイルのトップレベルに複数のフォームを順に書くと、 このようになります。 つまり、書かれている順番にフォームを実行します。 これをテキスト上の順序(textual order)と呼びます。 たとえば、関数本体が2つのフォームabから成る場合、 関数を評価すると、まずaを評価し、つぎにbを評価して、 関数の値はbの値になります。

明示的な制御構造により、逐次実行以外の実行順序が可能になります。

Emacs Lispには数種類の制御構造があり、 逐次実行の変形、条件付き実行、繰り返し実行、 (制御された)ジャンプなどです。 これらすべては、以下に説明します。 組み込みの制御構造はスペシャルフォームです。 というのは、それらのサブフォームは必ずしも評価しませんし、 逐次評価するわけでもないからです。 マクロを使えば、独自の制御構造の構文を定義できます(see Macros)。


Node:Sequencing, Next:, Up:Control Structures

逐次実行

現れる順番にフォームを評価することは、 1つのフォームから別のフォームへ制御を移すもっとも一般的な方法です。 関数本体などのある種の文脈では、自動的にこのようになります。 それ以外では、これを行う制御構造の構文を使う必要があります。 prognがその制御構造で、Lispのもっとも単純な制御構造です。

スペシャルフォームprognはつぎのような形です。

(progn a b c ...)

これは、フォーム、abc、…をこの順に評価します。 これらのフォームをprognフォームの本体と呼びます。 本体の最後のフォームの値が、progn全体の値になります。

初期のころのLispでは、prognは、 2つ以上のフォームを逐次実行しそれらの最後の値を使う唯一の方法でした。 しかし、プログラマは、(当時は)1つのフォームしか許されていない 関数の本体では、 prognを使う必要がしばしばあることに気づきました。 そのため、関数本体を『暗黙のprogn』にしたのです。 つまり、実際のprognの本体のように、 複数のフォームを許すようにしたのです。 多くの他の制御構造も、同様に、暗黙のprognです。 その結果、prognは、かつてほどは多用されません。 現在では、unwind-protectandorの内側や、 ifthen部分で必要とされるのがほとんどです。

progn forms... Special Form
このスペシャルフォームは、formsのフォームすべてを テキスト上の順に評価し、最後のフォームの結果を返す。
(progn (print "The first form")
       (print "The second form")
       (print "The third form"))
     -| "The first form"
     -| "The second form"
     -| "The third form"
=> "The third form"

他の2つの制御構造も同様にフォームを逐次評価しますが、 返す値が異なります。

prog1 form1 forms... Special Form
このスペシャルフォームは、form1formsのフォームすべてを テキスト上の順に評価し、form1の結果を返す。
(prog1 (print "The first form")
       (print "The second form")
       (print "The third form"))
     -| "The first form"
     -| "The second form"
     -| "The third form"
=> "The first form"

変数のリストから先頭要素を取り除き、取り除いた要素を返すにはつぎのように書く。

(prog1 (car x) (setq x (cdr x)))

prog2 form1 form2 forms... Special Form
このスペシャルフォームは、form1form2formsの フォームすべてをテキスト上の順に評価し、form2の結果を返す。
(prog2 (print "The first form")
       (print "The second form")
       (print "The third form"))
     -| "The first form"
     -| "The second form"
     -| "The third form"
=> "The second form"


Node:Conditionals, Next:, Previous:Sequencing, Up:Control Structures

条件付き実行

条件付き制御構造は、選択肢を選びます。 Emacs Lispには、4つの条件付きフォームがあります。 他の言語のものとほとんど同じififの変形であるwhenunless、 一般化したcase文であるcondです。

if condition then-form else-forms... Special Form
ifは、conditionをもとにして、 then-formelse-formsを選ぶ。 conditionnil以外に評価されると、 then-formを評価し、その結果を返す。 さもなければ、else-formsをテキスト上の順に評価し、 その最後のものの値を返す。 (ifelse部分は、暗黙のprognの例である。 see Sequencing。)

conditionが値nilであり、かつ、else-formsがないと、 ifnilを返す。

ifがスペシャルフォームであるのは、 選択しなかった分岐をけっして評価しないからである。 したがって、つぎの例では、 printはけっして呼ばれないためtrueは表示されない。

(if nil
    (print 'true)
  'very-false)
=> very-false

when condition then-forms... Macro
これはifの変形であり、else-formsがなく、 then-formsは複数のフォームでもよい。 特に、
(when condition a b c)

は、つぎとまったく等価である。

(if condition (progn a b c) nil)

unless condition forms... Macro
これはthen-formがないifの変形である。
(unless condition a b c)

は、つぎとまったく等価である。

(if condition nil
   a b c)

cond clause... Special Form
condは任意個数の選択肢から1つを選ぶ。 condの各節clauseはリストである必要がある。 このリストのCARcondition(条件)である。 残りの要素は、あれば、body-forms(本体フォーム)である。 つまり、各節はつぎのようになる。
(condition body-forms...)

condは、各節のconditionを評価して、 各節をテキスト上の順に試す。 conditionの値がnil以外であれば、 その節は『成功』する。 そうすると、condはその節のbody-formsを評価し、 body-formsの最後の値がcondの値となる。 残りの節は無視する。

conditionの値がnilであると、 その節は『失敗』し、 condはつぎの節へ移りそのconditionを試す。

conditionnilに評価されると、 すべての節が失敗し、condnilを返す。

clauseは、つぎの形式でもよい。

(condition)

この場合、conditionnil以外であると、 conditioncondフォームの値になる。

以下の例には4つの節があり、 xの値が、数、文字列、バッファ、シンボルかどうか調べる。

(cond ((numberp x) x)
      ((stringp x) x)
      ((bufferp x)
       (setq temporary-hack x) ; 1つの節に
       (buffer-name x))        ; 複数個の本体フォーム
      ((symbolp x) (symbol-value x)))

最後の節を除くそれよりまえの節がどれも成功しないときには、 最後の節を実行したいことがしばしばある。 これを行うには、(t body-forms)のように 最後の節のconditiontを使う。 フォームttと評価され、けっしてnilではない。 そのため、condがこの節に達したときには、 この節が失敗することはない。

たとえば、つぎのとおり。

(cond ((eq a 'hack) 'foo)
      (t "default"))
=> "default"

この式は、aの値がhackのときにはfooを返し、 さもなければ文字列"default"を返すcondである。

任意の条件付き構造は、condifで表現できます。 したがって、どちらを使うかは好みの問題です。 たとえば、つぎのとおりです。

(if a b c)
==
(cond (a b) (t c))


Node:Combining Conditions, Next:, Previous:Conditionals, Up:Control Structures

条件の組み合わせ

本節では、ifcondとともに用いて複雑な条件を表現するために しばしば使われる3つの構造を説明します。 andorの構造は、 複数の条件付き構造の一種として単独で使うこともできます。

not condition Function
この関数は、conditionが偽であるかどうか調べる。 conditionnilであればtを返し、 さもなければnilを返す。 関数notnullと同一であるが、 空リストかどうか調べる場合には、nullを使うことを勧める。

and conditions... Special Form
スペシャルフォームandは、 すべてのconditionsが真であるかどうか調べる。 conditionsを1つ1つ書かれた順に評価して調べる。

conditionsのどれかがnilに評価されると、 andの結果は、残りのconditionsに関係なく、nilになる。 つまり、andはただちに完了し、 conditionsの残りを無視する。

conditionsすべてがnil以外であることがわかると、 それらの最後の値がフォームandの値となる。

例を示そう。 最初の条件は整数1を返し、これはnilではない。 同様に、2番目の条件は整数2を返し、nilではない。 3番目の条件はnilなので、残りの条件を評価しない。

(and (print 1) (print 2) nil (print 3))
     -| 1
     -| 2
=> nil

andを使ったより現実的な例はつぎのとおり。

(if (and (consp foo) (eq (car foo) 'x))
    (message "foo is a list starting with x"))

(consp foo)nilを返すと(car foo)は実行されず、 そのためエラーを回避することに注意。

andは、ifcondで表現できる。 たとえば、つぎのとおり。

(and arg1 arg2 arg3)
==
(if arg1 (if arg2 arg3))
==
(cond (arg1 (cond (arg2 arg3))))

or conditions... Special Form
スペシャルフォームorは、 conditionsの少なくとも1つが真であるかどうか調べる。 conditionsを1つ1つ書かれた順に評価して調べる。

conditionsのどれかがnil以外に評価されると、 orの結果はnil以外になる。 そして、orはただちに完了し、 conditionsの残りを無視する。 戻り値は、nil以外に評価された値である。

conditionsすべてがnilであることがわかると、 ornilを返す。

たとえば、つぎの式は、xが0かnilであることを調べる。

(or (eq x nil) (eq x 0))

and構造と同様に、orcondで書き表せる。 たとえば、つぎのとおり。

(or arg1 arg2 arg3)
==
(cond (arg1)
      (arg2)
      (arg3))

orifで書くこともだいたいできるが、 途中で抜け出せない。

(if arg1 arg1
  (if arg2 arg2
    arg3))

これは完全には同一ではない。 というのは、arg1arg2を2度評価するからである。 一方、(or arg1 arg2 arg3)は、 どの引数も一度だけ評価する。


Node:Iteration, Next:, Previous:Combining Conditions, Up:Control Structures

繰り返し

繰り返しとは、プログラムのある部分を何度も実行することです。 たとえば、リストの各要素や0からnの各整数について 1回ずつある計算を行いたい場合です。 Emacs Lispでこれを行うには、スペシャルフォームwhileを使います。

while condition forms... Special Form
whileは、まずconditionを評価する。 結果がnil以外であれば、formsをテキスト上の順で評価する。 そして、conditionを評価し直し、その結果がnil以外であれば、 再度formsを評価する。 この処理をconditionnilに評価されるまで繰り返す。

繰り返し回数に制限はない。 ループは、conditionnilに評価される、 エラーが発生する、throwによりループから抜け出す (see Nonlocal Exits)のいずれかが起こるまで繰り返される。

フォームwhileの値はつねにnilである。

(setq num 0)
     => 0
(while (< num 4)
  (princ (format "Iteration %d." num))
  (setq num (1+ num)))
     -| Iteration 0.
     -| Iteration 1.
     -| Iteration 2.
     -| Iteration 3.
     => nil

終了検査のまえに各繰り返しごとに実行したいことがあれば、 以下のように、それらと終了検査をprognでまとめたものを whileの第1引数にする。

(while (progn
         (forward-line 1)
         (not (looking-at "^$"))))

これは、1行先へ移動し、空行に達するまで、移動を繰り返す。 このwhileには本体がなく、 終了検査(かつポイントを実際に動かす)だけであるという点で、 風変わりである。


Node:Nonlocal Exits, Previous:Iteration, Up:Control Structures

非ローカル脱出

非ローカル脱出(nonlocal exit)とは、 プログラムのある場所から別の離れた場所へ制御を移すことです。 Emacs Lispでは、エラーの結果として非ローカル脱出が発生します。 非ローカル脱出は、明示的な制御にも使えます。 非ローカル脱出は、脱出対象の構造で作成したすべての変数束縛を解きます。


Node:Catch and Throw, Next:, Up:Nonlocal Exits

明示的な非ローカル脱出: catchthrow

ほとんどの制御構造は、その構造内での制御の流れだけに影響します。 関数throwは、通常のプログラム実行のこのような規則の例外です。 つまり、要求に従って非ローカルな脱出を行います。 (ほかにも例外はあるが、それらはエラー処理のためだけである。) throwcatchの内側で使い、 そのcatchへ戻ります。

(defun foo-outer ()
  (catch 'foo
    (foo-inner)))

(defun foo-inner ()
  ...
  (if x
      (throw 'foo t))
  ...)

フォームthrowを実行すると、対応するcatchへ制御が戻り、 そのcatchはただちに終了します。 throwに続くコードは実行されません。 throwの第2引数は、catchの戻り値として使われます。

関数throwは、その第1引数に基づいて対応するcatchを探します。 つまり、catchの第1引数が throwに指定されたものにeqであるcatchを探します。 そのようなcatchが複数個ある場合には、 もっとも内側のものを優先します。 したがって、上の例では、throwfooを指定し、 foo-outercatchは同じシンボルを指定しているので、 そのcatchを使います (ただし、これらのあいだには他の一致するcatchがないとして)。

throwの実行により、 対応するcatchまでのすべてのLispの構造を抜け出します。 これには関数呼び出しも含みます。 letや関数呼び出しなどの束縛を作る構造からもこのように抜け出すので、 通常どおり抜け出す場合と同様に束縛を解きます (see Local Variables)。 同様に、throwは、save-excursion(see Excursions)で 保存したバッファや位置情報、 save-restrictionで保存したナロイング状態、 save-window-excursion(see Window Configurations)で保存した ウィンドウの選択状態も復元します。 さらに、スペシャルフォームunwind-protectで設定した後始末を このフォームから抜け出すときに実行します(see Cleanups)。

throwは、テキスト上で、 ジャンプ先であるcatchの内側に現れる必要はありません。 throwは、catch内から呼ばれた別の関数からも戻ることもできます。 throwの実行が、 時間的にcatchに入ったあとで、かつ、それから抜けるまえである限り、 throwは対応するcatchを参照できます。 エディタコマンドループ(see Recursive Editing)から抜ける exit-recursive-editなどのコマンドで throwを使えるのは、このような理由からです。

Common Lispに関した注意: Common Lispを含むほとんどの他のLispには、 非逐次的に制御を移す方法がいくつかある。 たとえば、returnreturn-fromgo。 Emacs Lispにはthrowしかない。

catch tag body... Special Form
catchは、関数throw向けに戻り位置を確立する。 その戻り位置は、tagによって他の戻り位置と区別される。 tagは、nil以外ならば任意のLispオブジェクトでよい。 引数tagは、戻り位置を確立するまえに、通常どおり評価される。

戻り位置を確立してから、catchは、bodyのフォームを テキスト上の順に評価する。 エラーや非ローカル脱出なしにフォームの実行が普通に終了した場合、 catchは、最後の本体フォームの値を返す。

bodyの内側で、tagと同じ値を指定したthrowが実行されると、 catchはただちに終了する。 このとき返す値は、throwの第2引数に指定されたものである。

throw tag value Function
throwの目的は、 catchでまえもって確立しておいた戻り位置へ復帰することである。 引数tagは、さまざまな既存の戻り位置から選ぶために使う。 tagは、catchで指定した値とeqである必要がある。 tagに複数の戻り位置が一致する場合には、もっとも内側のものを使う。

引数valueは、対応するcatchの戻り値として使う。

タグtagである有効な戻り位置がなければ、 (tag value)を伴ったエラーno-catchを通知する。


Node:Examples of Catch, Next:, Previous:Catch and Throw, Up:Nonlocal Exits

catchthrowの例

catchthrowの使い方の1つは、 2重のループからの脱出です。 (ほとんどの言語では、これを『go to』で行うであろう。) ここでは、ijを0から9に変えながら、 (foo i j)を計算します。

(defun search-foo ()
  (catch 'loop
    (let ((i 0))
      (while (< i 10)
        (let ((j 0))
          (while (< j 10)
            (if (foo i j)
                (throw 'loop (list i j)))
            (setq j (1+ j))))
        (setq i (1+ i))))))

fooがある時点でnil以外を返すと、 ただちに止まってijのリストを返します。 fooがつねにnilを返すと、 catchは通常どおりに戻って、その値はnilです。 というのは、whileの結果はnilだからです。

2つの巧妙な例をあげましょう。 多少異なる2つの戻り位置が同時に存在します。 まず、同じタグhackで2つの戻り位置があります。

(defun catch2 (tag)
  (catch tag
    (throw 'hack 'yes)))
=> catch2

(catch 'hack
  (print (catch2 'hack))
  'no)
-| yes
=> no

どちらの戻り位置もthrowに一致するタグなので、 内側のもの、つまり、catch2で確立したものに戻ります。 したがって、catch2は値yesで通常どおり戻り、 この値が表示されます。 最後に、外側のcatchの2番目の本体フォーム、 つまり、'noが評価され、外側のcatchから戻ります。

今度は、catch2に指定する引数を変更してみます。

(defun catch2 (tag)
  (catch tag
    (throw 'hack 'yes)))
=> catch2

(catch 'hack
  (print (catch2 'quux))
  'no)
=> yes

ここでも2つの戻り位置がありますが、 今度は外側のものだけがタグhackです。 内側のものはタグquuxです。 したがって、throwにより、外側のcatchが値yesを返します。 関数printはけっして呼ばれず、 本体フォーム'noもけっして評価されません。


Node:Errors, Next:, Previous:Examples of Catch, Up:Nonlocal Exits

エラー

Emacs Lispが、なんらかの理由で評価できないフォームを評価しようとしたときには、 Emacs Lispはエラー(error)を通知(signals)します。

エラーが通知されると、Emacsのデフォルトの動作は、 エラーメッセージを表示し、現在のコマンドの実行を終了します。 バッファの末尾でC-fを打ったときなどのように、 これはほとんどの場合、適切なことです。

複雑なプログラムでは、単に終了するだけでは満足できないこともあります。 たとえば、プログラムではデータ構造に一時的な変更を加えていたり、 プログラム終了時には削除する必要がある一時的なバッファを作成するでしょう。 そのような場合には、unwind-protectを使って、 エラー発生時に評価される後始末式(cleanup expressions)を 確立しておきます。 (see Cleanups。) 場合によっては、サブルーティンでエラーが発生しても、 プログラムの実行を継続したいこともあるでしょう。 このような場合には、condition-caseを使って、 エラー状態から制御を回復するための エラーハンドラ(error handlers)を確立しておきます。

エラー処理を用いてプログラムのある場所から別の場所へ制御を移す、 という誘惑には耐えてください。 そのかわりにcatchthrowを使いましょう。 See Catch and Throw


Node:Signaling Errors, Next:, Up:Errors

エラーの通知方法

ほとんどのエラーは、他の目的で呼び出したLisp関数の内部で『自動的』に 通知されます。 整数のCARを計算しようとしたり、 バッファの末尾で1文字進めようとしたりしたときなどです。 関数errorや関数signalで、 明示的にエラーを通知することもできます。

ユーザーがC-gを打ったときに発生する中断は、 エラーとは考えませんが、エラーのように扱います。

error format-string &rest args Function
この関数は、format-stringargsformat(see String Conversion)を適用して作った エラーメッセージを伴ったエラーを通知する。

errorの典型的な使い方を以下に示す。

(error "That is an error -- try something else")
     error--> That is an error -- try something else

(error "You have committed %d errors" 10)
     error--> You have committed 10 errors

errorは、2つの引数、 エラーシンボルerrorformatが返す文字列を含むリスト でsignalを呼び出すことで動作する。

警告: 独自のエラーメッセージをそのまま使いたい場合に、 単に(error string)とは書かないこと。 string%が含まれていると、 それは書式付け指定と解釈され、予測不能な結果を招く。 そのかわりに、(error "%s" string)を使う。

signal error-symbol data Function
この関数は、error-symbolという名前のエラーを通知する。 引数dataは、エラーの状況に関連したLispオブジェクトのリストである。

引数error-symbolは、エラーシンボル(error symbol)である 必要がある。 つまり、属性error-conditionsを持つシンボルであり、 その属性値は条件名のリストである。 これにより、Emacsはエラーの異なる種類を分類する。

dataのオブジェクトの個数と重要性はerror-symbolに依存する。 たとえば、エラーwrong-type-argでは、 リストには2つのオブジェクトがあるはずで、 予期した型を表す述語とその型に一致しなかったオブジェクトである。 エラーシンボルの説明は、see Error Symbols

error-symboldataの両者は、 任意のエラーハンドラで利用できる。 condition-caseは、ローカル変数に フォーム(error-symbol . data)のリストを束縛する (see Handling Errors)。 エラーが処理されないと、これらの2つの値はエラーメッセージの表示に使われる。

関数signalはけっして戻らない (しかし、Emacsの古い版では戻る場合もある)。

(signal 'wrong-number-of-arguments '(x y))
     error--> Wrong number of arguments: x, y

(signal 'no-such-error '("My unknown error condition"))
     error--> peculiar error: "My unknown error condition"

Common Lispに関した注意: Emacsには、Common lispの継続可能なエラーの概念に相当するものはない。


Node:Processing of Errors, Next:, Previous:Signaling Errors, Up:Errors

Emacsのエラー処理方法

エラーが通知されると、signalは、 エラーに対する有効なハンドラ(handler)を探します。 ハンドラは、Lispプログラムの一部でエラーが発生した場合に 実行されるように指定されたLisp式の列です。 エラーに対して適用可能なハンドラがあると、 そのハンドラが実行され、ハンドラに続いて制御は復旧します。 ハンドラは、そのハンドラを設定したcondition-caseの環境で実行されます。 condition-caseの内側で呼び出された関数はすべて終了しているので、 ハンドラからそれらへ戻ることはできません。

エラーに適用可能なハンドラがなければ、 現在のコマンドは終了し、制御はエディタコマンドループへ戻ります。 というのは、コマンドループには、 すべての種類のエラーに対する暗黙のハンドラがあるからです。 コマンドループのハンドラは、エラーシンボルと関連するデータを使って エラーメッセージを表示します。

明示的なハンドラがないエラーは、Lispデバッガを呼び出すこともあります。 変数debug-on-error(see Error Debugging)が nil以外であると、デバッガが有効になります。 エラーハンドラと違って、デバッガはエラーの環境で実行されるので、 エラー時の変数の正確な値を調べることができます。


Node:Handling Errors, Next:, Previous:Processing of Errors, Up:Errors

エラーハンドラの書き方

エラーを通知することの普通の効果は、 実行中のコマンドを終了し、Emacsのエディタコマンドループにただちに戻ります。 読者のプログラムの一部で発生したエラーを捕捉するようにするには、 スペシャルフォームcondition-caseを使ってエラーハンドラを設定します。 単純な例はつぎのようになります。

(condition-case nil
    (delete-file filename)
  (error nil))

これはfilenameという名前のファイルを削除しますが、 エラーが発生するとどんなエラーでも捕捉してnilを返します。

condition-caseの第2引数を 保護されたフォーム(protected form)と呼びます。 (上の例では、保護されたフォームはdelete-fileの呼び出し。) このフォームの実行を開始するとエラーハンドラが有効になり、 このフォームから戻るとエラーハンドラは取り除かれます。 そのあいだは、つねにエラーハンドラは有効です。 特に、このフォームから呼び出される関数の実行中、 それらのサブルーティンの実行中などには、エラーハンドラは有効です。 これは大切なことで、厳密にいえば、 エラーが通知されるのは、保護されたフォームから呼び出された (signalerrorを含む)Lisp基本関数の実行中であって、 保護されたフォームそのものからではないからです。

保護されたフォームのうしろにある引数は、ハンドラです。 各ハンドラは1つ以上の(シンボルである)条件名 (condition names)を列挙し、処理するエラーを指定します。 エラーが通知されたときのエラーシンボルも条件名のリストを定義します。 それらに共通の条件名があるとき、 エラーハンドラがエラーに適用されます。 上の例では、1つのハンドラがあり、条件名は1つ、errorを指定しています。 この条件名はすべてのエラーを意味します。

適用可能なハンドラの探索では、 もっとも最近に確立されたハンドラから始めて、 確立されたすべてのハンドラを調べます。 したがって、フォームcondition-caseが2つ入れ子になっていて 同じ名前のハンドラを確立していると、内側のものが実際に処理を受け持ちます。

フォームcondition-caseでエラーが処理されるときには、 debug-on-errorでエラーによりデバッガを起動するように指定してあっても デバッガは実行されません。 See Error Debuggingcondition-caseで捕捉されるエラーをデバッグしたいときには、 変数debug-on-signalnil以外の値を設定します。

エラーを処理できる場合には、制御はハンドラに移ります。 こうするまえに、Emacsは、抜け出し対象となる束縛作成構造が設定した すべての変数束縛を解き、抜け出し対象となるフォームunwind-protect すべての後始末を実行します。 ハンドラに制御が移ると、ハンドラの本体を実行します。

ハンドラ本体の実行を完了すると、 フォームcondition-caseから戻ります。 ハンドラを実行するまえに保護されたフォームから完全に抜けているので、 ハンドラでは、エラー発生時点から再開したり、 保護されたフォームの内側で作られた変数束縛を調べたりすることはできません。 ハンドラでできることは、後始末をして先へ進むことだけです。

condition-case構造は、insert-file-contentsの呼び出しで ファイルのオープンに失敗するなどの予測可能なエラーを捕捉するために しばしば使われます。 プログラムがユーザーから読み取った式を評価する場合のように、 まったく予測不可能なエラーを捕捉するためにも使われます。

エラー通知とエラー処理は、throwcatchに多少似ていますが、 それらはまったく別の機能です。 catchではエラーを捕捉できませんし、 エラーハンドラではthrowを処理できません (しかしながら、適切なcatchがないthrowを使うと、 処理できるエラーを通知する)。

condition-case var protected-form handlers... Special Form
このスペシャルフォームは、protected-formの実行中は エラーハンドラhandlersを確立する。 protected-formがエラーなしに完了すると、 その戻り値がフォームcondition-caseの値になる。 この場合、condition-caseはなんの効果もない。 フォームcondition-caseで違いがでるのは、 protected-formの実行中にエラーが起こった場合である。

handlersは、(conditions body...)の形式の リストである。 ここでconditionsは、処理すべきエラーの条件名か条件名のリストである。 bodyは1つ以上のLisp式であり、 このハンドラがエラーを処理するときに実行される。 ハンドラの例を示す。

(error nil)

(arith-error (message "Division by zero"))

((arith-error file-error)
 (message
  "Either division by zero or failure to open a file"))

生起する各エラーには、 そのエラーの種類を表すエラーシンボル(error symbol)がある。 そのシンボルの属性error-conditionsは、 条件名のリストである(see Error Symbols)。 Emacsは、有効なフォームcondition-caseすべてを探索し、 これらの条件名を1つ以上指定したハンドラを探す。 もっとも内側の一致するcondition-caseがエラーを処理する。 このcondition-caseの内側では、 適用可能な最初のハンドラがエラーを処理する。

ハンドラの本体の実行を完了すると、 condition-caseは通常のように戻り、 ハンドラの本体の最後のフォームの値を全体としての値に使う。

引数varは変数である。 condition-caseは、protected-formを実行するときには この変数を束縛せず、エラーを処理するときだけ束縛する。 そのとき、varはローカルにエラー記述 (error description)に束縛される。 これは、エラーの詳細を与えるリストである。 エラー記述は、(error-symbol . data)の形式である。 ハンドラは、動作を決定するためにこのリストを参照できる。 たとえば、ファイルのオープンに失敗したエラーであれば、 dataの第2要素、エラー記述の第3要素がファイル名である。

varnilであると、変数を束縛しなことを意味する。 そうすると、ハンドラではエラーシンボルと関連するデータを使えない。

error-message-string error-description Function
この関数は、指定したエラー記述に対するエラーメッセージ文字列を返す。 エラーに対する普通のエラーメッセージを表示して、 エラーを処理したい場合に便利である。

ゼロ除算の結果であるエラーを処理するcondition-caseの使用例を示します。 ハンドラはエラーメッセージを(ベルを鳴らさずに)表示して、 大きな数を返します。

(defun safe-divide (dividend divisor)
  (condition-case err
      ;; 保護されたフォーム
      (/ dividend divisor)
    ;; ハンドラ
    (arith-error                        ; 条件
     ;; このエラーに対する普通のメッセージを表示する
     (message "%s" (error-message-string err))
     1000000)))
=> safe-divide

(safe-divide 5 0)
     -| Arithmetic error: (arith-error)
=> 1000000

ハンドラは条件名arith-errorを指定しているので、 ゼロ除算エラーだけを処理します。 少なくともこのcondition-caseでは他の種類のエラーは処理しません。 したがって、つぎのようになります

(safe-divide nil 3)
     error--> Wrong type argument: number-or-marker-p, nil

以下は、errorで通知されるエラーも含めて、 すべての種類のエラーを捕捉するcondition-caseです。

(setq baz 34)
     => 34

(condition-case err
    (if (eq baz 35)
        t
      ;; これは関数errorの呼び出し
      (error "Rats!  The variable %s was %s, not 35" 'baz baz))
  ;; これはハンドラ。フォームではない
  (error (princ (format "The error was: %s" err))
         2))
-| The error was: (error "Rats!  The variable baz was 34, not 35")
=> 2


Node:Error Symbols, Previous:Handling Errors, Up:Errors

エラーシンボルと条件名

エラーを通知するときには、読者が意図するエラーの種類を指定する エラーシンボル(error symbol)を指定します。 各エラーには、それを分類する一意な名前があります。 これは、Emacs Lisp言語で定義されたエラーを細分類したものです。

これらの細分類は、エラー条件(error conditions)と呼ばれる より大きなクラスの階層にまとめられています。 エラー条件は、条件名(condition names)で識別します。 もっとも細かい分類は、エラーシンボルそのものです。 各エラーシンボルは条件名でもあります。 より大きなクラスを表す条件名errorもあります。 これはすべての種類のエラーを表します。 したがって、各エラーには、1つ以上の条件名があります。 つまり、errorerrorとは別のエラーシンボル、あるいは、 その中間の分類に属するものです。

あるシンボルがエラーシンボルであるためには、そのシンボルには、 条件名のリストを与える属性error-conditionsがあることが必要です。 このリストは、そのエラーが属するエラー条件を定義します。 (エラーシンボルそのものと、シンボルerrorは、 つねにこのリストの要素であること。) したがって、条件名の階層は、 エラーシンボルの属性error-conditionsで定義されます。

error-conditionsリストに加えて、 エラーシンボルには、属性error-messageも必要です。 この属性の値は、そのエラーが処理されないときに表示される文字列です。 属性error-messageがあるのに、それが文字列でなければ、 エラーメッセージpeculiar errorを使います。

以下に、新たなエラーシンボルnew-errorの定義方法を示します。

(put 'new-error
     'error-conditions
     '(error my-own-errors new-error))
=> (error my-own-errors new-error)
(put 'new-error 'error-message "A new error")
=> "A new error"

このエラーには、3つの条件名があります。 もっとも細かい分類であるnew-error、 それより大きな分類とであると考えているmy-own-error、 もっとも大きな分類であるerrorです。

エラー文字列は大文字で始めるべきですが、ピリオドで終えません。 これは、Emacsの他の慣習と整合をとるためです。

普通、Emacs自身がnew-errorを通知することはありえません。 つぎのように、読者のコードで明示的に signal(see Signaling Errors)を呼んだときだけです。

(signal 'new-error '(x y))
     error--> A new error: x, y

このエラーは、3つの条件名のどれでも処理できます。 つぎの例は、new-errorと クラスmy-own-errorsの任意の他のエラーを処理します。

(condition-case foo
    (bar nil t)
  (my-own-errors nil))

エラーを分類する重要な方法は、それらの条件名によることです。 つまり、エラーに一致するハンドラを探すために条件名を使います。 エラーシンボルは、意図したエラーメッセージと条件名のリストを指定する 簡便な方法を提供するだけです。 signalに、1つのエラーシンボルではなく、 条件名のリストを指定するのではわずらわしいでしょう。

一方、条件名なしにエラーシンボルだけを使うのでは、 condition-caseの能力をいちじるしく損ないます。 条件名があることで、エラーハンドラを書くときにさまざまなレベルに 一般化してエラーを分類できるのです。 エラーシンボルだけを使ったのでは、 最細分類以外のレベルを削除してしまうことになります。

すべての標準エラー名とそれらの条件名については、 See Standard Errors


Node:Cleanups, Previous:Errors, Up:Nonlocal Exits

非ローカル脱出時の後始末

unwind-protect構造は、データ構造を一時的に整合性のない状態に するときには本質的です。 この構造により、エラーや非ローカル脱出が起こったときに、 データの整合性を回復できます。

unwind-protect body cleanup-forms... Special Form
unwind-protectは、bodyからどのように制御が離れた場合にも cleanup-formsの実行を保証して、bodyを実行する。 bodyは通常どおり完了するか、 throwを実行してunwind-protectから脱出するか、 エラーを引き起こす。 いずれの場合でも、cleanup-formsは評価される。

フォームbodyが正常に終了すると、 unwind-protectは、cleanup-formsを評価したあとに、 フォームbodyの最後の値を返す。 フォームbodyが完了しなかった場合、 unwind-protectは普通の意味での値は返さない。

unwind-protectが保護するのはbodyだけである。 cleanup-formsそのもののどれかが(throwやエラーで) 非ローカル脱出を行うと、unwind-protectは、 cleanup-formsの残りを評価することを保証しないcleanup-formsのどれかが失敗するとトラブルになる危険性がある場合には、 cleanup-formsを別のunwind-protectで保護する。

フォームunwind-protectの現在の入れ子の個数は、 ローカル変数束縛の個数とともに数えられ、 max-specpdl-sizeに制限されている(see Local Variables)。

たとえば、表示しないバッファを一時的に作成し、 終了前に確実にそれを消去したいとしましょう。

(save-excursion
  (let ((buffer (get-buffer-create " *temp*")))
    (set-buffer buffer)
    (unwind-protect
        body
      (kill-buffer buffer))))

変数bufferを使わずに(kill-buffer (current-buffer))と 書くだけで十分だと考えるかもしれません。 しかし、別のバッファに切り替えたあとでbodyでエラーが発生した場合には、 上の方法はより安全です。 (あるいは、bodyの周りに別のsave-excursionを書いて、 一時バッファを消去するときに、それがカレントバッファになることを 保証する。)

Emacsには、上のようなコードに展開されるwith-temp-bufferという 標準マクロがあります(see Current Buffer)。 本書で定義しているマクロのいくつかでは、 このようにunwind-protectを使っています。

ファイルftp.elから持ってきた実際の例を示しましょう。 リモートの計算機への接続を確立するプロセス(see Processes)を作ります。 関数ftp-loginは、その関数の作成者が予想できないほどの 数多くの問題に対してとても敏感ですから、 失敗したときにプロセスを消去することを保証するフォームで保護します。 さもないと、Emacsは、無用なサブプロセスで満たされてしまいます。

(let ((win nil))
  (unwind-protect
      (progn
        (setq process (ftp-setup-buffer host file))
        (if (setq win (ftp-login process host user password))
            (message "Logged in")
          (error "Ftp login failed")))
    (or win (and process (delete-process process)))))

この例には、小さなバグが1つあります。 ユーザーがC-gを打って中断しようとして、かつ、 関数ftp-setup-bufferの終了後に 変数processを設定するまえに実際に中断が行われると、 プロセスは消去されません。 このバグを直す簡単な方法はありませんが、 少なくとも、ほとんど起こりえません。


Node:Variables, Next:, Previous:Control Structures, Up:Top

変数

変数(variable)は、プログラムにおいて値を表すために使う名前です。 ほとんどすべてのプログラム言語には、ある種の変数があります。 Lispプログラムのテキストでは、シンボルの構文を使って変数を書きます。

ほとんどのプログラム言語と違って、Lispでは、 プログラムはLispオブジェクトで表現し、テキスト表現は副次的なものです。 変数として使うLispオブジェクトはシンボルです。 シンボル名が変数名であり、変数の値はシンボルの値セルに格納されています。 変数としてのシンボルの使い方は、関数名としての使い方とは独立しています。 See Symbol Components

Lispプログラムを構成するLispオブジェクト群は、 プログラムのテキスト表現を決定します。 つまり、Lispオブジェクト群に対する単なる入力構文です。 これは、たとえば、Lispプログラムのテキスト表現では、 変数を表現するシンボルの入力構文で変数を書く理由です。


Node:Global Variables, Next:, Up:Variables

グローバル変数

変数を使うもっとも簡単な方法は、 グローバルに(globally、大局的に)使うことです。 つまり、どんなときにも変数にはたった1つの値だけがあり、 (少なくともここでは)Lispシステム全体にその値が有効になります。 新たな値を設定するまで、その値が有効であり続けます。 新たな値で古い値を置き換えると、変数には古い値の痕跡はなにも残りません。

シンボルの値はsetqで指定します。 たとえば、

(setq x '(a b))

は、変数xに値(a b)を与えます。 setqは、最初の引数、つまり、変数の名前を評価せず、 新しい値である第2引数を評価することに注意してください。

変数にいったん値を与えれば、 式としてシンボルそのものを使うことによりその値を参照できます。 つまり、つぎのとおりです。

x => (a b)

ただし、上に示したフォームsetqを実行してあると仮定します。

同じ変数に値を設定し直すと、 新しい値で古い値を置き換えます。

x
     => (a b)
(setq x 4)
     => 4
x
     => 4


Node:Constant Variables, Next:, Previous:Global Variables, Up:Variables

変更不可能な変数

Emacs Lispには、通常それ自身に評価されるある種のシンボルがあります。 :で始まる名前の任意の変数、および、niltです。 これらのシンボルを再束縛することはできず、 それらの値を変更することもできません。 niltを設定しようとしたり束縛しようとすると、 エラーsetting-constantを通知します。 :で始まる名前のシンボルに関してもそうですが、 そのようなシンボルにそれ自身を設定することはできます。

nil == 'nil
     => nil
(setq nil 500)
error--> Attempt to set constant symbol: nil

keyword-symbols-constant-flag Variable
この変数がnilであると、 :で始まる名前の変数を望みの値に設定したり束縛したりできる。 これは、そのようなことを行う古いLispプログラムの実行を可能にするためである。


Node:Local Variables, Next:, Previous:Constant Variables, Up:Variables

ローカル変数

グローバル変数は、 明示的に新しい値で置き換えない限り存続する値を持ちます。 一時的にしか存在しない変数値、 つまり、プログラムのある部分を完了するまでのみ存在する変数値を 作れると便利なことがあります。 このような値をローカル(local、局所的)と呼び、 そのように使われる変数をローカル変数(local variables)と呼びます。

たとえば、関数を呼び出したとき、その引数変数は、 関数を抜けるまで存続する新たなローカルな値を受け取ります。 スペシャルフォームletは、指定した変数の新たなローカル値を 明示的に確立します。 これらはフォームletを抜けるまで存続します。

ローカル値を確立すると、 変数の以前の値(あるいは値がないこと)を保存します。 ローカル値の存続期間が終了すると、以前の値を復元します。 この期間は、以前の値を隠して(shadowed)いて 以前の値は見えません。 グローバル値でもローカル値でも隠せます(see Scope)。

変数がローカルなときに(setqなどで)その変数を設定すると、 ローカル値を置き換えます。 隠されているグローバル値や以前のローカル値を変更しません。 このふるまいをモデル化するために、 変数のローカル値に加えて変数のローカル束縛(local binding)を 考えます。

ローカル束縛とは、ローカル値を保持する概念的な場所です。 関数やletなどのスペシャルフォームに入るたびに ローカル束縛を作成します。 関数やフォームletから抜けるとローカル束縛を削除します。 ローカル束縛が存続する限り、変数の値はそこに保持されています。 ローカル束縛が存在するときにsetqsetを使うと、 ローカル束縛の中に別の値を格納します。 新たな束縛を作るのではありません。

グローバル値を保持する概念的な場所を グローバル束縛(global binding)ともいいます。

変数には一度に複数のローカル束縛がありえます (たとえば、同じ変数を束縛する入れ子になったフォームletがあるとき)。 そのような場合、既存のもっとも最近に作成されたローカル束縛が、 変数の現在の束縛(current binding)です。 (この規則を動的スコープ(dynamic scoping)と呼びます。 see Variable Scoping) ローカル束縛がまったくなければ、変数のグローバル束縛が現在の束縛です。 現在の束縛のことを強調して既存の最ローカル束縛と呼ぶこともあります。 シンボルの通常の評価では、その現在の束縛の値を返します。

スペシャルフォームletlet*は、 ローカル束縛を作るためにあります。

let (bindings...) forms... Special Form
このスペシャルフォームは、bindingsに従って変数を束縛し、 formsのすべてをテキスト上の順に評価する。 letフォームは、formsの最後のフォームの値を返す。

bindingsのおのおのは、(i)シンボルであるか、 (ii)フォーム(symbol value-form)のリストである。 前者は、シンボルにnilを束縛する。 後者は、symbolvalue-formの評価結果を束縛する。 value-formを省略するとnilを使う。

bindingsvalue-form群すべてを現れる順に評価してから、 シンボルにそれらの値を束縛する。 例をつぎに示す。 Zは、Yの古い値2に束縛され、Yの新しい値1ではない。

(setq Y 2)
     => 2
(let ((Y 1)
      (Z Y))
  (list Y Z))
     => (1 2)

let* (bindings...) forms... Special Form
このスペシャルフォームはletに似ているが、 変数のローカル値を計算し終えた直後にその変数を束縛し、 つぎの変数のローカル値の計算に進む。 したがって、bindings内の式では、このlet*フォーム内で まえにあるシンボルを参照できる。 つぎの例を上のletの例と比較してほしい。
(setq Y 2)
     => 2
(let* ((Y 1)
       (Z Y))    ; 設定し終えたばかりのYの値を使う
  (list Y Z))
     => (1 1)

以下にローカル束縛を作成するその他の機能の完全な一覧をあげておきます。

変数は、バッファローカルな束縛(see Buffer-Local Variablesや フレームローカルな束縛(see Frame-Local Variables)を持つことができます。 少数の変数は、端末にローカルな束縛(see Multiple Displays) を持つこともできます。 この種の束縛は普通のローカル束縛と同じように働きますが、 これらはEmacsの『どの部分』にいるかに依存したローカル化であり、 時間的なローカル化ではありません。

max-specpdl-size Variable
この変数は、("Variable binding depth exceeds max-specpdl-size"を 伴った)エラーを通知するまでに許される、 ローカル変数束縛と unwind-protectによる後始末(see Nonlocal Exits)の 全体の個数の制限を定義する。

この制限、および、これを超えたときのエラーは、 不正に定義された関数によってLispが無限に再帰することを防止する 1つの方法である。

デフォルト値は600である。 Lispデバッガに入ったとき、 制限に近い場合にはデバッガ自身が実行できることを保証するために値を増やす。


Node:Void Variables, Next:, Previous:Local Variables, Up:Variables

変数が『空』であるとき

シンボルにグローバル変数としての値を一度も与えていないとき、 そのシンボルのグローバル値は(void)であるといいます。 いいかえれば、シンボルの値セルにはどんなLispオブジェクトも入っていません。 シンボルを評価しようとすると、値ではなくエラーvoid-variableを得ます。

nilという値は空とは異なることに注意してください。 シンボルnilはLispオブジェクトであり、他のオブジェクトと同様に 変数の値になりえます。 それはなのです。 空な変数はいかなる値も持たないのです。

変数に値を与えたあとでは、makunboundを使って 再度その変数を空にできます。

makunbound symbol Function
この関数は、symbolの現在の変数束縛を空にする。 これ以降に変数としてこのシンボルの値を使おうとすると、 再度設定していない限り、エラーvoid-variableを通知する。

makunboundsymbolを返す。

(makunbound 'x)      ; 変数xのグローバル値を空にする
     => x
x
error--> Symbol's value as variable is void: x

symbolがローカルに束縛されていると、 makunboundは既存の最ローカル束縛に作用する。 ローカル束縛を作成するすべての構文は変数に値を与えるため、 これはシンボルのローカル束縛を空にする唯一の方法である。 この場面では、空の状態は、束縛が存在する限り存続する。 束縛を作成した構造から抜け出して束縛が削除されると、 通常どおりそれ以前のローカル束縛かグローバル束縛が有効になり、 その束縛が空でなければ変数は空ではない。

(setq x 1)               ; グローバル束縛に値を入れる
     => 1
(let ((x 2))             ; ローカルに束縛する
  (makunbound 'x)        ; ローカル束縛を空にする
  x)
error--> Symbol's value as variable is void: x
x                        ; グローバル束縛は変更されていない
     => 1

(let ((x 2))             ; ローカルに束縛する
  (let ((x 3))           ; もう一度
    (makunbound 'x)      ; もっとも内側のローカル束縛を空にする
    x))                  ; 参照するが、それは空
error--> Symbol's value as variable is void: x

(let ((x 2))
  (let ((x 3))
    (makunbound 'x))     ; 内側の束縛を空にし、それを削除する
  x)                     ; 外側のletの束縛が見える
     => 2

makunboundで空にした変数は、 一度も値を受け取ったことがなく、そのために空である変数と区別できません。

変数が現在、空であるかどうかは関数boundpを使って調べられます。

boundp variable Function
boundpは、(シンボル)variableが空でなければ、 より正確にいえば、現在の束縛が空でなければtを返す。 さもなければnilを返す。
(boundp 'abracadabra)          ; 空で始める
     => nil
(let ((abracadabra 5))         ; ローカルに束縛する
  (boundp 'abracadabra))
     => t
(boundp 'abracadabra)          ; グローバルにはまだ空である
     => nil
(setq abracadabra 5)           ; グローバルに空でなくする
     => 5
(boundp 'abracadabra)
     => t


Node:Defining Variables, Next:, Previous:Void Variables, Up:Variables

グローバル変数を定義する

スペシャルフォームdefconstdefvar変数定義を使って、 シンボルをグローバル変数として使う意図を表明できます。

Emacs Lispでは、定義には3つの目的があります。 まず、コードを読む人向けに、特定のシンボルを(変数として)特定目的に 使う意図があることを知らせます。 第2に、Lispシステムに対しては、値と説明文字列を提供して これらのことを伝えます。 第3に、プログラム内の関数や変数のデータベースを作成する etagsmake-docfileなどのユーティリティに情報を提供します。

defconstdefvarの違いは、主に好みの問題であり、 値が変更されるかどうかを人に伝えます。 Emacs Lispは、defconstdefvarの宣言に基づいて 変数の使い方を制限することはしません。 しかしながら、初期化に関しては違いがあります。 defconstは無条件に変数を初期化しますが、 defvarは変数が空である場合にのみ初期化します。

defvar symbol [value [doc-string]] Special Form
このスペシャルフォームは、symbolを変数として定義し、 初期値や説明文字列を設定する。 この定義は、コードを読む人向けに、 値を設定したり変更する変数としてsymbolを使うことを伝える。 symbolは評価されないことに注意。 定義するシンボルは、defvarに明示的に現れる必要がある。

symbolの値が空でありvalueを指定してあると、 defvarvalueを評価し、その結果をsymbolに設定する。 しかし、symbolにすでに値があれば(つまり、空でなければ)、 valueをまったく評価せず、symbolの値も変更しない。 valueを省略した場合、symbolの値をいっさい変更しない。

symbolにカレントバッファでバッファローカルな束縛がある場合には、 defvarはデフォルト値に作用する。 それは、バッファには独立であり、現在の(バッファローカルな)束縛ではない。 defvarは、デフォルト値が空の場合にデフォルト値を設定する。 see Buffer-Local Variables

emacs-lispモードにおいてC-M-xeval-defun)でトップレベルの フォームdefvarを評価すると、 eval-defunの特別な機能により、 変数の値が空かどうかを調べずに無条件に変数に設定する。

doc-stringがあれば、それは変数の説明文を指定する。 (説明文を指定できるのは、変数定義の主な利点の1つである。) 説明文はシンボルの属性variable-documentationに格納する。 Emacsのヘルプ関数(see Documentation)は、この属性を調べる。

doc-stringの最初の文字が*であると、 この変数をユーザーオプションと考えることを意味する。 これにより、ユーザーはコマンドset-variableedit-optionsを 使って簡単に変数を設定できる。 しかしながら、ユーザーオプションの変数には、 defvarではなくdefcustomを使ったほうがよく、 そうすればカスタマイズ情報を指定できる。 see Customization

いくつか例をあげる。 つぎのフォームはfooを定義するが初期化はしない。

(defvar foo)
     => foo

つぎの例は、barの値を23に初期化し、説明文字列を与える。

(defvar bar 23
  "The normal weight of a bar.")
     => bar

つぎの例は、barの説明文字列を変更し、 この変数をユーザーオプションにする。 しかし、barにはすでに値が設定してあるので、 その値は変更しない。 (さらに(1+ nil)は評価するとエラーになるが、 評価されないのでエラーはない。)

(defvar bar (1+ nil)
  "*The normal weight of a bar.")
     => bar
bar
     => 23

つぎの例は、スペシャルフォームdefvarに等価な式である。

(defvar symbol value doc-string)
==
(progn
  (if (not (boundp 'symbol))
      (setq symbol value))
  (if 'doc-string
    (put 'symbol 'variable-documentation 'doc-string))
  'symbol)

フォームdefvarsymbolを返すが、 通常このフォームはファイルのトップレベルで使われ、そこでは値は関係ない。

defconst symbol [value [doc-string]] Special Form
このスペシャルフォームは、symbolを変数として定義し初期化する。 この定義は、コードを読む人向けに、 symbolはこれ以降標準のグローバル値を持ち、 ユーザーや他のプログラムが変更すべきでないことを伝える。 symbolは評価されないことに注意。 定義するシンボルは、defconstに明示的に現れる必要がある。

defconstは、valueがあればつねにvalueを評価し、 その結果をsymbolに設定する。 symbolにカレントバッファのバッファローカルな束縛がある場合には、 defconstはデフォルト値を設定し、 バッファローカルな値にではない。 (しかし、defconstで定義するシンボルには、 バッファローカルな束縛を作るべきではない。)

つぎの例では、piは、(インディアナ州立法府はいうにおよばず) だれも変更すべきではないと考えられる定数である。 しかし、2番目のフォームからわかるように、これは単に助言でしかない。

(defconst pi 3.1415 "Pi to five places.")
     => pi
(setq pi 3)
     => pi
pi
     => 3

user-variable-p variable Function
この関数は、variableがユーザーオプション、つまり、 カスタマイズのためにユーザーが設定することを意図した変数であると、 tを返し、さもなければnilを返す。 (ユーザーオプション向け以外の変数は、Lispプログラムの内部目的用にあり、 それらについてユーザーが知る必要はない。)

ユーザーオプション変数は、 属性variable-documentationの最初の文字で他の変数と区別される。 その属性が存在して文字列であり、最初の文字が*であれば、 その変数はユーザーオプションである。

ユーザーオプション変数に属性variable-interactiveがあると、 コマンドset-variableはその属性値を使って、 変数の新しい値の読み取りを制御します。 この属性値は、interactiveの引数(see Using Interactive) のように使われます。 しかしながら、この機能はdefcustom(see Customization)により ほとんど廃れています。

警告: 変数にローカル束縛があるときに スペシャルフォームdefconstdefvarを使うと、 ローカル束縛の値を変更し、グローバル束縛は変更しない。 これは望む効果ではない。 これを防ぐには、これらのスペシャルフォームはファイルのトップレベルで使う。 そうすれば、普通は有効なローカル束縛はない。 さらに、変数のローカル束縛を作るまえに、 確実にファイルをロードしておく。


Node:Tips for Defining, Next:, Previous:Defining Variables, Up:Variables

変数を堅牢に定義するためのヒント

(内部に束縛を含むようなキーマップなどの)複雑な値を保持する変数を 定義し初期化するときには、つぎのように、 値の計算全体をdefvarの内部に入れておくのが最良です。

(defvar my-mode-map
  (let ((map (make-sparse-keymap)))
    (define-key map "\C-c\C-a" 'my-command)
    ...
    map)
  docstring)

この方法には、いくつかの利点があります。 まず、ファイルのロード中にユーザーが中断した場合、 変数は初期化されないか正しく初期化されるかのいずれかであり、 その中間状態ということはありません。 第2に、変数をすでに初期化したあとにファイルをロードし直しても、 変数を変更しません。 (キーをバインドし直すなどの)内容の一部を変更するために ユーザーがフックを実行した場合などには、これは重要です。 第3に、C-M-xでフォームdefvarを評価すると、 マップを完全に初期化し直せます

フォームdefvarの内側に多くのコードを置くことには、欠点が1つあります。 変数の名前を指定した行から説明文字列が離れすぎてしまうことです。 つぎのようにしてこれを安全に防げます。

(defvar my-mode-map nil
  docstring)
(if my-mode-map
    nil
  (let ((map (make-sparse-keymap)))
    (define-key my-mode-map "\C-c\C-a" 'my-command)
    ...
    (setq my-mode-map map)))

これには、defvarの内側に初期化を入れたときと同じ利点がありますが、 変数を再初期化するには、各フォームそれぞれについて C-M-xを打つ必要があります。

しかし、つぎのようなコードは書かないでください。

(defvar my-mode-map nil
  docstring)
(if my-mode-map
    nil
  (setq my-mode-map (make-sparse-keymap))
  (define-key my-mode-map "\C-c\C-a" 'my-command)
  ...)

このコードでは、変数を設定してから変更しますが、 それを複数の手順で行います。 setqの直後にユーザーが中断すると、 変数は正しく初期化されておらず、空でもnilでもありません。 こうなったときにファイルを再ロードしても変数を初期化できません。 変数は不完全な状態のままです。


Node:Accessing Variables, Next:, Previous:Tips for Defining, Up:Variables

変数値の参照

変数を参照する普通の方法は、 変数を指名するシンボルを書くことです(see Symbol Forms)。 これには、プログラムを書くときに変数名を指定する必要があります。 読者は、普通このようにするでしょう。 場合によっては、実行時にどの変数を参照するか選ぶ必要があり、 そのときにはsymbol-valueを使います。

symbol-value symbol Function
この関数はsymbolの値を返す。 これは、シンボルのもっとも内側のローカル束縛の値、あるいは、 ローカル束縛がなければグローバル値である。
(setq abracadabra 5)
     => 5
(setq foo 9)
     => 9

;; ここで、abracadabraは、
;;   その値を調べるシンボル
(let ((abracadabra 'foo))
  (symbol-value 'abracadabra))
     => foo

;; ここで、abracadabraの値、
;;   つまりfooが、
;;   その値を調べるシンボル
(let ((abracadabra 'foo))
  (symbol-value abracadabra))
     => 9

(symbol-value 'abracadabra)
     => 5

symbolの現在の束縛が空であると、 エラーvoid-variableを通知する。


Node:Setting Variables, Next:, Previous:Accessing Variables, Up:Variables

変数値の変更

変数の値を変更する普通の方法は、スペシャルフォームsetqを使うことです。 実行時に選択する変数を計算する必要があるときには、 関数setを使います。

setq [symbol form]... Special Form
このスペシャルフォームは、変数の値を変更するもっとも一般的な方法である。 各symbolに、対応するformの評価結果である新たな値を与える。 シンボルの既存の際、ローカルの束縛を変更する。

setqsymbolを評価しない。 読者が書いたシンボルに設定する。 この変数は自動的にクォートされるのである。 setqqは、『quoted(クォートする)』を表す。

フォームsetqの値は、最後のformの値である。

(setq x (1+ 2))
     => 3
x                   ; xはグローバル値を持つ
     => 3
(let ((x 5))
  (setq x 6)        ; xのローカル束縛を設定する
  x)
     => 6
x                   ; グローバル値は変更されない
     => 3

最初のformを評価して最初のsymbolに設定し、 つぎに、2番目のformを評価して2番目のsymbolに設定し、 といった具合になることに注意。

(setq x 10          ; xは、yの値を計算するまえに
      y (1+ x))     ;   設定されることに注意
     => 11

set symbol value Function
この関数は、symbolの値としてvalueを設定し、valueを返す。 setは関数なので、symbolとして書いた式は、 設定するシンボルを得るために評価される。

変数の既存の最ローカルの束縛に設定する。 隠されている束縛には影響しない。

(set one 1)
error--> Symbol's value as variable is void: one
(set 'one 1)
     => 1
(set 'two 'one)
     => one
(set two 2)         ; twoはシンボルoneに評価される
     => 2
one                 ; そのため、oneに設定される
     => 2
(let ((one 1))      ; oneのこの束縛が設定され、
  (set 'one 3)      ;   グローバル値は設定されない
  one)
     => 3
one
     => 2

symbol(の評価結果)が実際にはシンボルでないと、 エラーwrong-type-argumentを通知する。

(set '(x y) 'z)
error--> Wrong type argument: symbolp, (x y)

論理的には、setsetqよりもさらに基本的な操作である。 どんなsetqの使い方でも、setで素直に書き直せる。 setqは、setを使ってマクロとして定義することも可能である。 しかし、setそのものを使うことは稀であり、 初心者はsetを知る必要がほとんどない。 設定する変数を実行時に選ぶときにのみ有用である。 たとえば、コマンドset-variableは、 ユーザーから変数名を読み取りその変数に設定するので、 setを使う必要がある。

Common Lispに関した注意: Common Lispでは、setはつねにシンボルの『スペシャル』な、つまり、 動的な値を変更し、文脈上の束縛を無視する。 Emacs Lispでは、すべての変数とすべての束縛は動的であり、 setはつねに既存の最ローカルの束縛に作用する。

変数に設定する別の関数は、リストに既存でない要素を追加するように 設計されたものです。

add-to-list symbol element Function
この関数は、elementが変数symbolの値のリストのメンバでなければ、 elementと変数symbolの値をコンスした値を 変数symbolに設定する。 リストを変更してもしなくても結果のリストを返す。 呼び出すまえに、symbolの値はリストであるほうがよい。

引数symbolは暗黙にクォートされない。 add-to-listは、setのように普通の関数であり、 setqとは違う。 必要ならば、読者自身でクォートする。

add-to-listの使い方を以下に示します。

(setq foo '(a b))
     => (a b)

(add-to-list 'foo 'c)     ;; cを追加する
     => (c a b)

(add-to-list 'foo 'b)     ;; なんの効果もない
     => (c a b)

foo                       ;; fooは変更されている
     => (c a b)

(add-to-list 'var value)に等価な式はつぎのとおりです。

(or (member value var)
    (setq var (cons value var)))


Node:Variable Scoping, Next:, Previous:Setting Variables, Up:Variables

変数束縛のスコープルール

あるシンボルfooは、さまざまなローカルな変数束縛を持つことができます。 Lispプログラムの異なる場所で確立されたものや グローバル束縛です。 もっとも最近に確立した束縛が他のものに優先します。

Emacs Lispのローカル束縛は、無限のスコープ(indefinite scope)と 動的存続期間(dynamic extent)を持ちます。 スコープ(scope)とは、ソースコードのテキスト上の どこから束縛を参照できるかを表します。 無限のスコープとは、プログラムのどこからでも変数束縛を参照できることを 意味します。 存続期間(extent)とは、プログラムの実行にしたがって、 いつ束縛が存在するかを表します。 動的存続期間とは、束縛を作成した構造が有効である限り、 束縛が存続することを意味します。

動的存続期間と無限のスコープの組み合せを 動的スコープ(dynamic scoping)と呼びます。 対照的に、ほとんどのプログラム言語は、 レキシカルスコープ(lexical scoping)を用います。 つまり、ローカル変数の参照は、 その変数を束縛する関数やブロックのテキスト上で内側にある必要があります。

Common Lispに関した注意: Common Lispでは、『スペシャル』と宣言した変数は、 Emacs Lispのすべての変数と同様に、動的スコープである。


Node:Scope, Next:, Up:Variable Scoping

スコープ

Emacs Lispでは、 ローカル変数束縛は無限のスコープ(indefinite scope)です。 つまり、プログラムテキスト上のどの関数からでも、 ある変数束縛を参照できるのです。 つぎの関数定義を考えてみましょう。

(defun binder (x)   ; xは、binderで束縛
   (foo 5))         ; fooは別の関数

(defun user ()      ; xは、userにおいて『自由』
  (list x))

テキスト上のスコープを用いる言語では、 binder内のxの束縛を、userで参照することはできません。 なぜなら、userは、テキスト上で関数binderの内側にはないからです。 しかしながら、動的スコープのEmacs Lispでは、 状況に応じて、binder内で確立したxの束縛を userから参照してもしなくてもよいのです。

Emacs Lispで動的スコープを使うのは、 テキスト上のスコープの単純な実装は遅いからです。 さらに、すべてのLispシステムは、少なくともオプションとして、 動的スコープを使えるようにする必要があります。 テキスト上のスコープが標準であると、 特定の変数に対して動的スコープを指定する方法が必要になります。 Emacsで両方のスコープを使えるようにしてもよいのですが、 動的スコープだけだと実装がより簡単になります。


Node:Extent, Next:, Previous:Scope, Up:Variable Scoping

存続期間

存続期間(Extent)とは、プログラムの実行中において、 変数名が有効である期間を指します。 Emacs Lispでは、束縛を作ったフォームを実行している期間中だけ、 変数は有効です。 これを動的存続期間(dynamic extent)と呼びます。 CやPascalなどのほとんどの言語の『ローカル』変数や『自動』変数も 動的存続期間です。

動的存続期間とは別のものに無限の存続期間(indefinite extent)があります。 つまり、変数束縛は、その束縛を作ったフォームから抜けても存続するのです。 たとえば、Common LispやSchemeにはこれがありますが、Emacs Lispにはありません。

これを説明するために、つぎの関数make-addを考えます。 この関数は、nに自身の引数mを加算する関数を返します。 この関数はCommon Lispでは動作しますが、Emacs Lispではだめです。 というのは、make-addの呼び出しを抜けると、 変数nは実引数2に束縛されなくなるからです。

(defun make-add (n)
    (function (lambda (m) (+ n m))))  ; 関数を返す
     => make-add
(fset 'add2 (make-add 2))  ; 関数add2を
                           ;   (make-add 2)を使って定義する
     => (lambda (m) (+ n m))
(add2 4)                   ; 4に2を加算してみる
error--> Symbol's value as variable is void: n

Lispの方言のいくつかには『クロージャ』(closure)があります。 それは関数のようなオブジェクトですが、追加の変数束縛を記録します。 Emacs Lispにはクロージャはありません。


Node:Impl of Scope, Next:, Previous:Extent, Up:Variable Scoping

動的スコープの実装

(Emacs Lispの実際の動作とは異なるが)単純な実装例が、 動的束縛を理解する助けになるでしょう。 この技法を深い束縛(ディープバインディング、deep binding)と呼び、 初期のLispシステムで使われていました。

変数・値の対である束縛のスタックがあるとしましょう。 関数やフォームletに入ると、 引数やローカル変数の束縛をスタックに積みます。 束縛を作った構造から抜けるとそれらの束縛を取りさります。

変数の値は、スタックの先頭から底へ向けてその変数の束縛を探索します。 その束縛から得る値が変数の値になります。 変数に設定するには、現在の束縛を探して、その束縛に新たな値を格納します。

これからわかるように、関数の束縛は、その関数の実行中には、 たとえ別の関数を呼び出していても、存続しています。 これが束縛の存続が動的であるという理由です。 また、その束縛が有効である期間中ならば、同じ変数を使えば他の関数からも 束縛を参照できるのです。 これがスコープが無限であるという理由です。

GNU Emacs Lispにおいて、変数のスコープの実際の実装には、 浅い束縛(シャローバインディング、shallow binding)と呼ばれる 技法を用いています。 各変数には現在値を保存しておく標準の場所、シンボルの値セルがあります。

浅い束縛では、変数の設定は値セルに値を格納することで動作します。 新たな束縛を作成すると(以前の束縛に属する)古い値をスタックに積み、 新たなローカル値を値セルに格納します。 束縛を解くときには、古い値をスタックから取り出して値セルに格納します。

浅い束縛を用いる理由は、束縛を探索する必要がないため、 深い束縛と同じ結果を持ちながら高速に動作するからです。


Node:Using Scoping, Previous:Impl of Scope, Up:Variable Scoping

動的スコープの正しい使い方

ある関数で変数を束縛し別の関数でそれを使うことは、強力な技法ですが、 なんの制限もせずに使うとプログラムを理解し難いものにしてしまいます。 この技法を見通しよく使うための2つの方法があります。

いずれの場合でも、変数はdefvarで定義するべきです。 これは、関数間での変数の使い方を見るように伝えることで、 他人が読者のプログラムを理解するのを助けます。 また、バイトコンパイラからの警告も防ぎます。 変数名が衝突しないようにも注意しましょう。 xのような短い名前を使わないでください。


Node:Buffer-Local Variables, Next:, Previous:Variable Scoping, Up:Variables

バッファローカルな変数

グローバルとローカルの変数束縛は、 ほとんどのプログラム言語にいろいろな形であります。 Emacsには、あまり普通でない追加の種類の変数束縛があります。 1つのバッファだけに適用されるバッファローカルな束縛、 1つのフレームだけに適用されるフレームローカルな束縛です。 異なるバッファやフレームごとに変数に異なる値があるということは、 重要なカスタマイズ技法です。

本節では、バッファローカルな束縛を説明します。 フレームローカルな束縛については、つぎの節と See Frame-Local Variables。 (各端末にローカルな束縛を持つ変数も少数ある。 see Multiple Displays。)


Node:Intro to Buffer-Local, Next:, Up:Buffer-Local Variables

バッファローカルな変数の紹介

バッファローカルな変数には、特定のバッファに関連したバッファローカルな 束縛があります。 この束縛は、そのバッファがカレントバッファであるときに有効になります。 さもなければなんの効果もありません。 バッファローカルな束縛が有効なときに変数に設定すると、 新しい値はその束縛に入り、他の束縛は変更されません。 つまり、その変更は、変更を行ったバッファだけで見ることができるのです。

変数の通常の束縛、つまり、特定のバッファに関連していない束縛を デフォルトの束縛(default binding)と呼びます。 多くの場合、これはグローバル束縛です。

変数は、あるバッファ群ではバッファローカルな束縛を持ち、 他のバッファではそのような束縛を持たないようにできます。 変数に対する独自の束縛を持たないバッファすべてでは、 デフォルトの束縛を共有します。 (これには、新たに作成されるバッファも含む。) バッファローカルな束縛を持たないバッファで変数に設定すると、 (状況を複雑にするフレームローカルな束縛はないと仮定して) デフォルトの束縛を使います。 したがって、新たな値はデフォルトの束縛を見るバッファすべてで見えます。

バッファローカルな束縛のもっとも一般的な使い方は、 メジャーモードでコマンドのふるまいを制御する変数に変更することです。 たとえば、CモードやLispモードでは、変数paragraph-startを設定して、 空行だけが段落を区切るように指定します。 これには、CモードやLispモードになったバッファでは、 変数をバッファローカルにしてから、 そのモード用の新たな値を変数に設定するのです。 See Major Modes

バッファローカルな束縛を作る普通の方法は、 make-local-variableです。 メジャーモードのコマンドは典型的にこれを使います。 これはカレントバッファだけに影響します。 (これから作成するものも含めて)他のすべてのバッファは、 それ専用のバッファローカルな束縛を明示的に与えない限り、 デフォルト値を共有し続けます。

より強力な操作は、make-variable-buffer-localを呼び出して 変数を自動的にバッファローカルにするように印を付けることです。 これは、これから作成するものも含めたバッファすべてで、 変数をバッファローカルにすると考えることができます。 より正確には、変数がカレントバッファにローカルでなければ、 自動的に変数をカレントバッファにローカルにするように設定する効果があります。 すべてのバッファは通常どおり変数のデフォルト値を共有して始まりますが、 変数に設定するとカレントバッファにバッファローカルな束縛を作ります。 新たな値はバッファローカルな束縛に格納され、デフォルトの束縛は変更しません。 つまり、どのバッファでもデフォルト値をsetqでは変更できません。 デフォルト値を変更する唯一の方法は、setq-defaultを使うことです。

警告: 複数のバッファにおいて変数にバッファローカルな値があるときに、 変数をletで束縛してから、 別の束縛が有効である別のバッファに切り替えてletを抜けると、 Emacsをとても混乱させることになる。 こうすると、バッファローカルな束縛とデフォルトの束縛を混ぜ合わせてしまう。

混乱を避けるために、このような変数の使い方は避けてください。 別のバッファに切り替える各コード部分をsave-excursionで囲めば、 このような問題はありません。

(setq foo 'b)
(set-buffer "a")
(make-local-variable 'foo)
(setq foo 'a)
(let ((foo 'temp))
  (set-buffer "b")
  body...)
foo => 'a      ; バッファaの古いバッファローカルな値が
               ;   現在のデフォルト値
(set-buffer "a")
foo => 'temp   ; 消えているべきローカルなletの値が
               ;   バッファaの現在のバッファローカルな値

しかし、つぎに示すようにsave-excursionを使えば、この問題を回避できます。

(let ((foo 'temp))
  (save-excursion
    (set-buffer "b")
    body...))

body内でのfooへの参照は、 バッファbのバッファローカルな束縛を使います。

ファイルでローカル変数の値を指定していると、 そのファイルを訪問したときに、それらはバッファローカルな値になります。 See File Variables


Node:Creating Buffer-Local, Next:, Previous:Intro to Buffer-Local, Up:Buffer-Local Variables

バッファローカルな束縛の作成と削除

make-local-variable variable コマンド
この関数は、カレントバッファにおいて、 variable(シンボル)のバッファローカルな束縛を作る。 他のバッファは影響されない。 返す値はvariable

variableのバッファローカルな値は、 variableの以前と同じ値で始まる。 variableが空であれば、空のままである。

;; バッファb1では、
(setq foo 5)                ; すべてのバッファに影響する
     => 5
(make-local-variable 'foo)  ; b1にローカル
     => foo
foo                         ; これは値を
     => 5                   ;   変えない
(setq foo 6)                ; b1での値を
     => 6                   ;   変更する
foo
     => 6

;; バッファb2では、値は変わっていない
(save-excursion
  (set-buffer "b2")
  foo)
     => 5

変数のlet束縛の内側でその変数をバッファローカルにしても、 そのバッファがletに入るときや抜けるときに カレントバッファになっていないと、正しく動作しない。 これは、letが、異なる種類の束縛を区別しないからであり、 どの変数の束縛を作るかだけを知っているからである。

変数が端末にローカルなときには、この関数はエラーを通知する。 そのような変数は、同時にバッファローカルな束縛を持てない。 See Multiple Displays

注意: フック変数に対してmake-local-variableを使わないこと。 そのかわりにmake-local-hookを使う。 see Hooks

make-variable-buffer-local variable コマンド
この関数は、variable(シンボル)を 自動的にバッファローカルにするように印を付け、 これ以降にその変数に設定しようとすると、 その時点のカレントバッファにローカルにする。

この機能の重要な点は、 (letや他の束縛を作る構文で)変数を束縛しても、 その変数のバッファローカルな束縛を作らないことである。 (setsetqで)変数を設定して初めてそのようにする。

返す値はvariableである。

警告: ユーザーが異なるバッファでは異なったカスタマイズをするかもしれないと いうだけで、ユーザーオプション変数にmake-variable-buffer-localを 使うべきだと仮定しないこと。 ユーザーは、必要ならば、どんな変数でもローカルにできる。 選択はユーザーに任せるのがよい。

2つのバッファが同じ束縛を共有しないことが重要な場面では、 make-variable-buffer-localを使う。 たとえば、異なるバッファでは異なる値を持つことに依存するような Lispプログラムで内部目的に変数を使うときには、 make-variable-buffer-localを使うのが最良である。

local-variable-p variable &optional buffer Function
これは、variableがバッファbuffer (デフォルトはカレントバッファ)において バッファローカルであればtを返し、 さもなければnilを返す。

buffer-local-variables &optional buffer Function
この関数は、バッファbufferのバッファローカルな変数を 記述したリストを返す。 (bufferを省略するとカレントバッファを使う。) バッファローカルな変数とその値を入れた要素から成る連想リスト (see Association Lists)を返す。 しかし、bufferにおける変数のバッファローカルな束縛が空であると、 変数は結果のリストに直接現れる。
(make-local-variable 'foobar)
(makunbound 'foobar)
(make-local-variable 'bind-me)
(setq bind-me 69)
(setq lcl (buffer-local-variables))
    ;; まず、すべてのバッファでローカルな組み込み変数
=> ((mark-active . nil)
    (buffer-undo-list . nil)
    (mode-name . "Fundamental")
    ...
    ;; 続いて、組み込みでないバッファローカルな変数
    ;; これはバッファローカルで、かつ、空
    foobar
    ;; これはバッファローカルで、かつ、空ではない
    (bind-me . 69))

このリストのコンスセルのCDRに新たな値を格納しても、 変数のバッファローカルな値を変更しないことに注意してほしい。

kill-local-variable variable コマンド
この関数は、カレントバッファにおけるvariable(シンボル)の バッファローカルな束縛を(あれば)削除する。 その結果、このバッファでは、variableのデフォルトの束縛が 見えるようになる。 典型的には、variableの値が変わる。 なぜなら、デフォルト値は、削除したバッファローカルな値とは 普通は異なるからである。

自動的にバッファローカルにする印が付いた変数のバッファローカルな束縛を 削除すると、カレントバッファではデフォルト値が見えるようになる。 しかし、変数に再度設定すると、それに対するバッファローカルな束縛が 再度作成される。

kill-local-variablevariableを返す。

この関数がコマンドであるのは、 対話的にバッファローカルな変数を作るのが有用なように、 対話的にバッファローカルな変数を削除するのが有用な場合があるからである。

kill-all-local-variables Function
この関数は、カレントバッファにおいて、 『恒久的』と印付けしてある変数を除いて、 すべてのバッファローカルな変数束縛を削除する。 その結果、バッファでは、ほとんどの変数のデフォルト値が見えるようになる。

この関数は、バッファに属する他のある種の情報もリセットする。 つまり、ローカルキーマップにnil、 構文テーブルに(standard-syntax-table)の値、 大文字小文字テーブルに(standard-case-table)、 略語テーブルにfundamental-mode-abbrev-tableの値を設定する。

この関数が最初に行うことは、 ノーマルフックchange-major-mode-hook(下記参照)を 実行することである。

各メジャーモードコマンドはこの関数を呼び出すことから始める。 つまり、基本(fundamental)モードに切り替え、 それ以前のメジャーモードのほとんどの効果を消しさる。 この処理を保証するために、メジャーモードで設定する変数には、 恒久的の印を付けないこと。

kill-all-local-variablesnilを返す。

change-major-mode-hook Variable
関数kill-all-local-variablesは、最初にこのノーマルフックを実行する。 このフックはメジャーモードに対して、 ユーザーが別のメジャーモードに切り替えていた場合には、 なにか特別なことを行う情報を提供する。 最良の結果を得るためには、この変数をバッファローカルにしておくと その役目を終えると変数は消えてしまい、それ以降のメジャーモードに干渉しない。 see Hooks

バッファローカル変数は、 変数名(シンボル)の属性permanent-localnil以外であると、 恒久的(permanent)です。 恒久的なローカル変数は、編集作業の文脈ではなく、 どのファイルを訪問中であるとかどのように保存するとかに関連する情報に 適しています。


Node:Default Value, Previous:Creating Buffer-Local, Up:Buffer-Local Variables

バッファローカル変数のデフォルト値

バッファローカルな束縛がある変数のグローバル値を、 デフォルト値とも呼びます。 カレントバッファや選択したフレームに変数の独自の束縛がない場合に、 グローバル値を使うからです。

関数default-valueと関数setq-defaultは、 カレントバッファにバッファローカルな束縛があるかどうかに関わらず、 変数のデフォルト値を参照したり変更したりします。 たとえば、setq-defaultを使って、 ほとんどのバッファのparagraph-startのデフォルト値を変更できます。 この変数のバッファローカルな値があるCモードやLispモードのバッファで 行ってもこれは動作します。

スペシャルフォームdefvardefconstも、 バッファローカルやフレームローカルな値ではなく、 (変数に設定する場合には)デフォルト値を設定します。

default-value symbol Function
この関数は、symbolのデフォルト値を返す。 この値は、この変数に対して独自の値を持たないバッファやフレームで見える 値である。 symbolがバッファローカルでなければ、 これは、symbol-value(see Accessing Variables)と等価。

default-boundp symbol Function
関数default-boundpは、 symbolのデフォルト値が空でないことを調べる。 (default-boundp 'foo)nilを返せば、 (default-value 'foo)はエラーになる。

default-boundpは、boundpsymbol-valueに対応するように、 default-valueに対応する。

setq-default [symbol form]... Special Form
このスペシャルフォームは、各symbolに、 対応するformの評価結果である新たなデフォルト値を与える。 symbolは評価しないが、formは評価する。 フォームsetq-defaultの値は、最後のformの値である。

symbolがカレントバッファでバッファローカルではなく、かつ、 自動的にバッファローカルにする印が付いていなければ、 setq-defaultsetqと同じ効果がある。 symbolがカレントバッファでバッファローカルならば、 (バッファローカルな値を持たない)別のバッファが見る値を変更し、 カレントバッファが見る値は変更しない。

;; バッファfooにおいて、
(make-local-variable 'buffer-local)
     => buffer-local
(setq buffer-local 'value-in-foo)
     => value-in-foo
(setq-default buffer-local 'new-default)
     => new-default
buffer-local
     => value-in-foo
(default-value 'buffer-local)
     => new-default

;; (新たな)バッファbarでは、
buffer-local
     => new-default
(default-value 'buffer-local)
     => new-default
(setq buffer-local 'another-default)
     => another-default
(default-value 'buffer-local)
     => another-default

;; バッファfooに戻ってみると
buffer-local
     => value-in-foo
(default-value 'buffer-local)
     => another-default

set-default symbol value Function
この関数はsetq-defaultに似ているが、 symbolは普通どおりに評価される引数である。
(set-default (car '(a b c)) 23)
     => 23
(default-value 'a)
     => 23


Node:Frame-Local Variables, Next:, Previous:Buffer-Local Variables, Up:Variables

フレームローカルな変数

変数にバッファローカルな束縛があるように、 変数にはフレームローカルな束縛もあります。 これらの束縛は1つのフレームに属し、 そのフレームを選択しているときに有効になります。 フレームローカルな束縛は、実際にはフレームパラメータです。 特定のフレームでフレームローカルな束縛を作るには modify-frame-parametersを呼び出し、 パラメータ名として変数名を指定します。

特定の変数に対するフレームローカルな束縛を有効にするには、 関数make-variable-frame-localを呼び出します。

make-variable-frame-local variable コマンド
variableに対してフレームローカルな束縛を使うようにする。 この関数そのものはvariableに対してフレームローカルな束縛を作成しない。 しかし、フレームパラメータとしてvariableの値を持つフレームが すでに存在すれば、その値は自動的にフレームローカルな束縛になる。

変数が端末にローカルであると、この関数はエラーを通知する。 そのような変数はフレームローカルな束縛を同時には持てないからである。 see Multiple Displays。 Emacsで特別に実装されている少数の変数は(普通) バッファローカルになることができるが、フレームローカルにはならない。

バッファローカルな束縛はフレームローカルな束縛に優先します。 変数fooを考えてみましょう。 カレントバッファにfooのバッファローカルな束縛があると、 その束縛が有効になります。 選択したフレームにfooのフレームローカルな束縛があると、 その束縛が有効になります。 さもなければ、fooのデフォルトの束縛が有効になります。

つぎに例を示します。 まず、fooの束縛を準備しておきます。

(setq f1 (selected-frame))
(make-variable-frame-local 'foo)

;; b1において、fooのバッファローカルな束縛を作る
(set-buffer (get-buffer-create "b1"))
(make-local-variable 'foo)
(setq foo '(b 1))

;; 新しいフレームでfooのフレームローカルな束縛を作る
;; そのフレームをf2に格納する
(setq f2 (make-frame))
(modify-frame-parameters f2 '((foo . (f 2))))

では、さまざまな文脈でfooを調べてみましょう。 バッファb1がカレントバッファであれば、 選択したフレームに関係なく、 b1のバッファローカルな束縛が有効になっています。

(select-frame f1)
(set-buffer (get-buffer-create "b1"))
foo
     => (b 1)

(select-frame f2)
(set-buffer (get-buffer-create "b1"))
foo
     => (b 1)

さもなければ、フレームの束縛を使う可能性があります。 フレームf2を選択していると、 そのフレームローカルな束縛が有効になります。

(select-frame f2)
(set-buffer (get-buffer "*scratch*"))
foo
     => (f 2)

カレントバッファにもフレームにも束縛がなければ、 デフォルトの束縛を使います。

(select-frame f1)
(set-buffer (get-buffer "*scratch*"))
foo
     => nil

変数の有効な束縛がフレームローカルな束縛であるとき、 変数に設定するとその束縛を変更します。 frame-parametersでその結果を見ることができます。

(select-frame f2)
(set-buffer (get-buffer "*scratch*"))
(setq foo 'nobody)
(assq 'foo (frame-parameters f2))
     => (foo . nobody)


Node:Future Local Variables, Previous:Frame-Local Variables, Up:Variables

将来のローカル変数

フレームに分類されるものでローカルな束縛というアイデアを考察しています。 たとえば、すべてのカラーフレーム、暗い背景色のすべてのフレームなどです。 この機能が本当に有用なのか明らかでないので、それらをまだ実装してはいません。 after-make-frame-hookに関数を追加して、 各フレームの適切な状態に応じたフレームパラメータを設定すれば、 同じような結果を得られます。

ウィンドウローカルな束縛を実装することも可能です。 これが有用である多くの状況を知りませんが、 バッファローカルな束縛を持つ間接バッファ(see Indirect Buffers)で、 そのような状況をより堅牢に扱えると思います。

これら2種類のローカル束縛のいずれかを必要とする十分な数のアプリケーションが みつかれば、Emacsの将来の版でそのような束縛を提供するでしょう。


Node:Functions, Next:, Previous:Variables, Up:Top

関数

Lispプログラムは、主にLisp関数から構成されます。 本章では、関数とはなにか、引数をどのように受け取るのか、 どのように関数を定義するのかを説明します。


Node:What Is a Function, Next:, Up:Functions

関数とはなにか

一般的には、関数とは、引数(arguments)と呼ばれる値を与えられ、 計算を行うための規則です。 この計算結果を関数の値と呼びます。 計算では副作用、つまり、変数の値やデータ構造の内容に継続する変更 を伴うこともできます。

Emacs Lispの関数や関数のようなオブジェクトに関する重要な用語をあげておきます。

関数
Emacs Lispでは、Lispプログラムにおいて引数に適用可能ものは なんであれ関数(function)である。 Lispで書いた関数を意味する場合もある。 スペシャルフォームやマクロは関数ではない。
基本関数
基本関数(primitive)は、carappendなどのCで書いた Lispから呼び出し可能な関数である。 これらの関数は、組み込み関数とかsubrsとも呼ぶ。 (スペシャルフォームは基本関数とも考えられる。)

関数を基本関数として実装する理由は、 それが基本的なものである、 それがオペレーティングシステムの機能に対する 低レベルのインターフェイスを提供する、 あるいは、高速に動作する必要があるからである。 基本関数を変更したり追加する唯一の方法は、 Cソースを変更してエディタを再コンパイルすることである。 see Writing Emacs Primitives

ラムダ式
ラムダ式(lambda expression)は、Lispで書いた関数である。 これらについては以下の節で説明する。
スペシャルフォーム
スペシャルフォーム(special form)は関数に似た基本関数であるが、 その引数すべてを普通のようには評価しない。 引数の一部を評価したり、普通とは異なる順序で評価したり、 複数回評価したりする。 多くのスペシャルフォームについては、 Control Structuresで説明してある。
マクロ
マクロ(macro)は、プログラマがLispで定義した構文である。 マクロと関数との違いは、マクロは、 読者が書いたLisp式をもとの式のかわりに評価される等価な式に変換する。 マクロは、スペシャルフォームでできる種類のことを Lispプログラマに提供する。 マクロの定義方法と使い方については、see Macros
コマンド
コマンド(command)とは、 command-executeが起動できるオブジェクトであり、 キー列に対して定義できる。 いくつかの関数はコマンドである。 Lispで書いた関数に対話宣言(see Defining Commands)が含まれているとき、 その関数はコマンドである。 そのような関数は、他の関数と同様にLisp式から呼び出すことができる。 その場合、関数がコマンドであるという事実は関係ない。

キーボードマクロ(文字列かベクトル)もコマンドであるが、 それらは関数ではない。 シンボルの関数定義がコマンドであれば、シンボルはコマンドである。 そのようなシンボルは、M-xで起動できる。 シンボルの定義が関数であれば、シンボルは関数でもある。

打鍵コマンド
打鍵コマンド(keystroke command)とは、 キー列(典型的には1から3打鍵)にバインドされたコマンドである。 ここでの区別は、Emacs以外のエディタの『コマンド』の意味との 混乱を防ぐためであるが、 Lispプログラムにとっては、この区別は普通は重要ではない。
バイトコード関数
バイトコード関数(byte-code function)とは、 バイトコンパイラでコンパイルした関数である。 see Byte-Code Type

functionp object Function
この関数は、objectが、なんらかの関数、スペシャルフォーム、 マクロであれば、tを返す。

subrp object Function
この関数は、objectが組み込み関数(つまり、Lisp基本関数)であれば tを返す。
(subrp 'message)            ; messageはシンボルであり、
     => nil                 ;   subrオブジェクトではない
(subrp (symbol-function 'message))
     => t

byte-code-function-p object Function
この関数は、objectがバイトコード関数であればtを返す。 たとえば、つぎのとおり。
(byte-code-function-p (symbol-function 'next-line))
     => t


Node:Lambda Expressions, Next:, Previous:What Is a Function, Up:Functions

ラムダ式

Lispで書いた関数はつぎのようなリストです。

(lambda (arg-variables...)
  [documentation-string]
  [interactive-declaration]
  body-forms...)

このようなリストをラムダ式(lambda expression)と呼びます。 Emacs Lispでは、これは式として正しいもので、 それ自身に評価されます。 Lispの他の方言では、ラムダ式は正しい式ではありません。 いずれの場合でも、その主な用途は式として評価することではなく、 関数として呼び出すことです。


Node:Lambda Components, Next:, Up:Lambda Expressions

ラムダ式の構成要素

ラムダ式の先頭要素は、つねにシンボルlambdaです。 このシンボルは、リストが関数を表すことを示します。 関数はlambdaで始まると定義してあるのは、 他の目的向けの他のリストが誤って正しい関数とならないようにするためです。

第2要素は、シンボルのリスト、つまり、引数変数名です。 これをラムダリスト(lambda list)と呼びます。 Lisp関数が呼ばれると、引数値をラムダリストの変数に対応させ、 指定した値を持つローカル束縛になります。 See Local Variables

説明文字列は、関数定義の内側にあるLisp文字列オブジェクトであり、 Emacsのヘルプ機能に対して関数を記述します。 See Function Documentation

対話宣言は、(interactive code-string)の形式のリストです。 この宣言は、関数が対話的に使われたときに、 どのように引数を与えるかを指定します。 この宣言を有する関数をコマンド(commands)と呼びます。 コマンドは、M-xで呼び出したり、キーにバインドできます。 このように呼ばれることを意図していない関数には、 対話宣言を付けてはいけません。 対話宣言の書き方については、See Defining Commands

残りの要素は、関数の本体(body)です。 関数の動作を行うLispコードです (Lispプログラマとしては、『評価するべきLispフォームのリスト』という)。 関数が返す値は、本体の最後の要素が返す値です。


Node:Simple Lambda, Next:, Previous:Lambda Components, Up:Lambda Expressions

簡単なラムダ式の例

つぎの関数を考えてみましょう。

(lambda (a b c) (+ a b c))

この関数を呼び出すには、つぎのように式のCARにこの関数を書きます。

((lambda (a b c) (+ a b c))
 1 2 3)

この呼び出しは、変数aには1、変数bには2、 変数cには3を束縛し、ラムダ式の本体を評価します。 本体の評価ではこれらを加算し、結果6を生じます。 したがって、この関数呼び出しは6を返します。

つぎの例のように、他の関数呼び出しの結果が引数になることもあります。

((lambda (a b c) (+ a b c))
 1 (* 2 3) (- 5 4))

これは、引数、1(* 2 3)(- 5 4)を 左から右へ順に評価します。 そして、引数値、1、6、1にラムダ式を適用し、値8を生じます。

このようにフォームのCARとしてラムダ式を書くのは、 あまり便利ではありません。 スペシャルフォームlet(see Local Variables)を使って、 ローカル変数を作ってそれらに値を与えても、同じ結果を得られます。 さらに、letは見通しがよく使いやすいです。 実用上、ラムダ式は、シンボルの関数定義として格納して名前付き関数を作るか、 他の関数に引数として渡します(see Anonymous Functions)。

しかしながら、スペシャルフォームletがなかった初期のLispでは、 ラムダ式を明示的に呼び出すことはとても便利でした。 その頃では、ラムダ式はローカル変数を束縛し初期化する唯一の方法でした。


Node:Argument List, Next:, Previous:Simple Lambda, Up:Lambda Expressions

引数リストのその他の機能

単純な関数の例(lambda (a b c) (+ a b c))では、 3つの引数変数を指定しているので、これは3引数で呼び出す必要があります。 2引数や4引数で呼び出そうとすると、 エラーwrong-number-of-argumentsになります。

特定の引数を省略できる関数を書けると便利なことがしばしばあります。 たとえば、関数substringは3つの引数、つまり、 文字列、開始と終了の添字を取りますが、 第3引数を省略するとデフォルトは文字列のlengthになります。 list+のように、 特定の関数では任意個数の引数を受け付けると便利なこともあります。

関数呼び出し時に省略してもよい引数を指定するには、 省略可能な引数のまえにキーワード&optionalを含めるだけです。 0個以上の引数のリストを指定するには、 最後の引数のまえにキーワード&restを含めます。

したがって、引数リストの完全な構文はつぎのようになります。

(required-vars...
               ; 必須の引数
 [&optional optional-vars...]
               ; 省略可能な引数
 [&rest rest-var])
               ; 残りの引数

角括弧は、&optional&restの節や それに続く変数は省略できることを示します。

関数呼び出し時には、各required-varsに1つの実引数が必要です。 0個以上のoptional-varsにも実引数が必要ですが、 ラムダリストに&restがない限り、 optional-varsの個数を超える実引数は指定できません。 &restがあれば、任意個の余分な実引数を指定できます。

&optional&restに対応する実引数を省略すると、 それらのデフォルトはnilです。 関数では、nilを明示した引数と省略した引数とを区別する方法はありません。 しかしながら、関数本体でnilを適切な意味ある値の省略と みなすことは自由です。 substringはそのようにしています。 substringの第3引数がnilであると、 指定した文字列の長さを使うことを意味します。

Common Lispに関した注意: Common Lispでは、省略可能引数を省略したときのデフォルト値を関数で指定できる。 Emacs Lispではつねにnilを使う。 Emacs Lispには、明示的に引数を指定したかどうか調べる 『supplied-p』変数はない。

たとえば、引数リストはつぎのようになります。

(a b &optional c d &rest e)

これは、abに最初の2つの実引数を束縛し、これらは必須です。 さらに1個か2個の引数を指定すると、 それらは、それぞれcdに束縛します。 最初の4個よりあとの引数はリストにまとめ、 eにそのリストを束縛します。 引数が2個だけであると、cnilです。 引数が2個か3個だけであると、dnilです。 引数が4個以下であると、enilです。

省略可能な引数のあとに必須引数を指定する方法はありませんし、 それには意味がありません。 なぜそうなのかを理解するために、上の例で、 cは省略可能であり、dは必須であるとしましょう。 3つの実引数を指定したとき、どの引数を3番目と考えるのでしょう? 同様に、&restのうしろに余分に(必須、もしくは省略可能な)引数が あっても意味がありません。

引数リストと正しい呼び出しの例をあげます。

((lambda (n) (1+ n))                ; 1個が必須
 1)                                 ; 引数は1個だけ
     => 2
((lambda (n &optional n1)           ; 1個は必須、1個は省略可
         (if n1 (+ n n1) (1+ n)))   ; 引数は1個か2個
 1 2)
     => 3
((lambda (n &rest ns)               ; 1個は必須、あとは残り全部
         (+ n (apply '+ ns)))       ; 引数は1個以上いくつでもよい
 1 2 3 4 5)
     => 15


Node:Function Documentation, Previous:Argument List, Up:Lambda Expressions

関数の説明文字列

ラムダ式には、ラムダリストの直後に 説明文字列(documentation string)があってもかまいません。 この文字列は関数の実行には影響しません。 コメントのようなものですが、Lisp内部に現れる系統的なコメントであり、 Emacsのヘルプ機能が使用します。 documentation-stringの参照方法については、See Documentation

読者のプログラムの関数すべてに、 たとえ内部的に使用されるものであっても説明文字列を与えることはよいことです。 説明文字列はコメントに似ていますが、参照するのはもっと簡単です。

説明文字列の先頭行は、その1行で完結しているべきです。 というのは、aproposは先頭行だけを表示するからです。 関数の機能をまとめた1つか2つの文にしましょう。

説明文字列の先頭は、ソースファイル上では普通字下げしてあるでしょうが、 それらの空白は文字列を始めるダブルクォートのまえにありますから、 それらは文字列の一部ではありません。 説明文字列の残りの行を字下げして、 プログラムソース上でテキスト行が揃うようにする人もいます。 しかし、それはまちがいです。 後続の行の字下げは文字列の内側にあります。 ソースファイルで綺麗に見えても、 ヘルプコマンドの表示では不恰好になります。

関数の必須の構成要素(本体)があとに続くのに、 説明文字列を省略できるのを不思議に思うかもしれません。 文字列を評価すると、副作用なしに、その文字列を返すので、 それが本体の最後のフォームでなければ、なんの効果もありません。 したがって、実用上、本体の最初のフォームと 説明文字列を混同することはありません。 本体のフォームが文字列だけであると、 それは戻り値でもあり説明文字列でもあります。


Node:Function Names, Next:, Previous:Lambda Expressions, Up:Functions

関数を命名する

ほとんどの計算機言語では、各関数には名前があります。 名前のない関数という考えは本質的ではありません。 Lispでは、もっとも厳密にいえば、関数には名前はありません。 関数は、先頭要素が単にlambdaであるリスト、 バイトコード関数オブジェクト、あるいは、基本関数のsubrオブジェクトです。

しかしながら、シンボルは関数の名前として働きます。 シンボルの関数セル(function cell、see Symbol Components)に 関数を入れると、このようになります。 そうすると、シンボルそのものは正当な呼び出し可能な関数となり、 関数セルが参照するリストやsubrオブジェクトと等価になります。 関数セルの内容をシンボルの関数定義(function definition)とも呼びます。 シンボルのかわりにシンボルの関数定義を使う処理を シンボルの関数間接(symbol function indirection)と呼びます。 See Function Indirection

実用上、ほとんどすべての関数には、このようにして名前が付いていて、 その名前で参照します。 たとえば、シンボルcarは、 その関数セルに基本関数のsubrオブジェクト#<subr car>が格納してあるので、 その動作を行う関数として動作します。

関数に名前を与えるのは、Lisp式からその名前で参照できると便利だからです。 #<subr car>のような基本関数のsubrオブジェクトでは、 名前はそれらを参照する唯一の方法です。 そのようなオブジェクトには入力構文はありません。 Lispで書いた関数では、明示的なラムダ式より名前を使うほうがより便利です。 また、関数に名前があればそれを参照できます。 つまり、再帰呼び出しができます。 関数の名前をその定義そのものに書くことは、 関数定義がそれ自身を指すようにする (これは不可能ではないにしても、実用上はさまざまな欠点がある)よりは、 とても便利です。

関数を指名するシンボルで関数をしばしば識別します。 たとえば、しばしば『関数car』といって、 シンボルcarと関数定義である基本関数のsubrオブジェクトとを区別しません。 ほとんどの目的には、区別する必要はありません。

たとえそうであっても、関数に一意な名前は必要ないことを 心に留めておいてください。 関数オブジェクトは普通1つのシンボルの関数セルだけに現れますが、 これは単なる便法です。 fsetを使って、複数のシンボルに格納するのは簡単です。 そうすると、各シンボルは同じ関数を同等に指名します。

関数名として使うシンボルは、変数としても使えます。 シンボルのこれら2つの使い方は独立していて衝突しません。 (SchemeなどのLispの方言のなかには、 シンボルの値とその関数定義を区別しないものもある。 変数としてのシンボルの値は、その関数定義でもある。) シンボルに関数定義を与えていないと、そのシンボルを関数としては使えません。 これは、シンボルに変数としての値があるかどうかには関係しません。


Node:Defining Functions, Next:, Previous:Function Names, Up:Functions

関数を定義する

関数を作成するときには、普通、関数に名前を与えます。 これを関数を定義すると呼び、 スペシャルフォームdefunで行います。

defun name argument-list body-forms Special Form
defunは、新たにLisp関数を定義する普通の方法である。 これは、シンボルnameをつぎのような関数として定義する。
(lambda argument-list . body-forms)

defunは、このラムダ式をnameの関数セルに格納する。 値nameを返すが、普通、これは無視する。

前述(see Lambda Expressions)のように、 argument-listは引数名のリストであり、 キーワード&optional&restが入っていてもよい。 また、body-formsの最初の2つは、説明文字列と対話宣言でもよい。

同一のシンボルnameを変数として使っていても衝突はない。 というのは、シンボルの値セルは関数セルとは独立だからである。 see Symbol Components

例を示そう。

(defun foo () 5)
     => foo
(foo)
     => 5

(defun bar (a &optional b &rest c)
    (list a b c))
     => bar
(bar 1 2 3 4 5)
     => (1 2 (3 4 5))
(bar 1)
     => (1 nil nil)
(bar)
error--> Wrong number of arguments.

(defun capitalize-backwards ()
  "Upcase the last letter of a word."
  (interactive)
  (backward-word 1)
  (forward-word 1)
  (backward-char 1)
  (capitalize-word 1))
     => capitalize-backwards

既存の関数を意図せずに再定義しないように注意すること。 defunは、たとえcarなどの基本関数であっても、 なんの躊躇も注意もせずに再定義してしまう。 既存関数の再定義は注意深く行うが、 不本意な再定義と熟考した再定義を区別する方法はない。

defalias name definition Function
このスペシャルフォームは、 シンボルnameを定義definition(任意の正しいLisp関数)とする 関数として定義する。

defaliasを使う正しい場所は、 特定の関数名が定義されている場所である。 特に、ロード中のソースファイルで明示的に名前が現れている場所である。 というのは、defaliasは、defunと同様に、 関数が定義されたファイルを記録するからである(see Unloading)。

一方、他の目的で関数定義を操作するプログラムでは、 そのような記録を保持しないfsetを使うのがよい。

defunのように関数を定義し、かつ、 Lispコンパイラに関数定義を展開するように指示する defsubstも参照してください。 See Inline Functions


Node:Calling Functions, Next:, Previous:Defining Functions, Up:Functions

関数呼び出し

関数を定義することは、全体の半分でしかありません。 関数を呼ぶまでは、つまり、実行を命じなければ、関数はなにもしません。 関数呼び出しは起動(invocation)ともいいます。

関数を起動するもっとも一般的な方法は、リストを評価することです。 たとえば、リスト(concat "a" "b")を評価すると、 関数concatを引数"a""b"で呼び出します。 評価についてはSee Evaluation

読者のプログラムで式としてリストを書くときには、 呼び出す関数名を読者のプログラムに書きます。 つまり、プログラムを書くときに、 どの関数をどれだけの引数で呼び出すかを指定できることを意味します。 これが、普通にしたいことでしょう。 呼び出す関数を実行時に計算する必要がある場合もあるでしょう。 それには、関数funcallを使います。 渡す引数の個数を実行時に決定する必要があるときには、 applyを使います。

funcall function &rest arguments Function
funcallは、functionargumentsで呼び出し、 functionがなにを返そうともそれを返す。

funcallは関数なので、functionの呼び出しを評価するまえに functionを含めた引数すべてを評価する。 つまり、呼び出す関数を得るためのどんな式でも使えることを意味する。 また、funcallは、読者がargumentsに書いた式を見ることはなく、 それらの値だけを見ることになる。 これらの値は、functionを呼び出す操作において、 2回目の評価を行うことはないfuncallは、通常の関数呼び出し処理において、 引数を評価し終えたところから始める。

引数functionは、Lisp関数か基本関数である必要がある。 スペシャルフォームやマクロは許されない。 それらには、『未評価』の引数式を与えたときだけ意味があるからである。 funcallではそのようにできない。 なぜなら、上の説明でわかるように、 未評価の引数をまったく知らないからである。

(setq f 'list)
     => list
(funcall f 'x 'y 'z)
     => (x y z)
(funcall f 'x 'y '(z))
     => (x y (z))
(funcall 'and t nil)
error--> Invalid function: #<subr and>

これらの例をapplyの例と比較してほしい。

apply function &rest arguments Function
applyは、funcallのように、 functionargumentsで呼び出すが、1点だけ異なる。 argumentsの最後はオブジェクトのリストであり、 functionにはこれを、単一のリストではなく、個々の引数として渡す。 これを、applyは、 このリストの個々の要素が引数となるように分配するという。

applyは、functionの呼び出し結果を返す。 funcallと同様に、functionはLisp関数か基本関数である必要がある。 スペシャルフォームやマクロは、applyでは意味がない。

(setq f 'list)
     => list
(apply f 'x 'y 'z)
error--> Wrong type argument: listp, z
(apply '+ 1 2 '(3 4))
     => 10
(apply '+ '(1 2 3 4))
     => 10

(apply 'append '((a b c) nil (x y z) nil))
     => (a b c x y z)

applyを使った興味深い例として、 Mapping Functionsmapcarの説明を見てほしい。

Lisp関数にとっては、引数として関数を受け取ったり、 データ構造(特に、フック変数や属性リスト)内の関数を探して funcallapplyを使ってそれを呼び出すことは一般的です。 関数引数を受け付ける関数を しばしばファンクショナル(functionals)と呼びます。

場合によっては、ファンクショナルを呼び出すときには、 引数としてなにもしない関数(no-op)を指定できると有用です。 つぎのものは、2種類のなにもしない関数です。

identity arg Function
この関数はargを返し、副作用を持たない。

ignore &rest args Function
この関数は引数を無視し、nilを返す。


Node:Mapping Functions, Next:, Previous:Calling Functions, Up:Functions

マップ関数

マップ関数(mapping function)は、 リストや他の集まりの各要素に指定した関数を適用します。 Emacs Lispにはそのような関数がいくつかあります。 mapcarmapconcatはリストを走査するもので、ここで説明します。 オブジェクト配列obarray内のシンボルについて マップする関数mapatomsについては、 See Creating Symbols

これらのマップ関数では、文字テーブルは扱えません。 というのは、文字テーブルは疎な配列であり、その添字範囲も非常に大きいからです。 文字テーブルの疎な性質を考慮して文字テーブルについてマップするには、 関数map-char-table(see Char-Tables)を使います。

mapcar function sequence Function
mapcarは、sequenceの各要素に順にfunctionを適用し、 結果のリストを返す。

引数sequenceは文字テーブル以外の任意の種類のシーケンスでよい。 つまり、リスト、ベクトル、ブールベクトル、あるいは、文字列である。 結果はつねにリストである。 結果の長さはsequenceの長さと同じである。


たとえば、つぎのとおり。
(mapcar 'car '((a b) (c d) (e f))) => (a c e) (mapcar '1+ [1 2 3]) => (2 3 4) (mapcar 'char-to-string "abc") => ("a" "b" "c") ;; my-hooksの各関数を呼び出す (mapcar 'funcall my-hooks) (defun mapcar* (function &rest args) "Apply FUNCTION to successive cars of all ARGS. Return the list of results." ;; リストをつくしていなければ (if (not (memq 'nil args)) ;; CARに関数を適用する (cons (apply function (mapcar 'car args)) (apply 'mapcar* function ;; Recurse for rest of elements. (mapcar 'cdr args))))) (mapcar* 'cons '(a b c) '(1 2 3 4)) => ((a . 1) (b . 2) (c . 3))

mapconcat function sequence separator Function
mapconcatは、sequenceの各要素にfunctionを適用する。 それらの結果は、文字列である必要があり、連結される。 mapconcatは、結果の文字列のあいだに文字列separatorを挿入する。 普通、separatorは、空白やコンマ、その他の句読点を含む。

引数functionは、引数を1つ取る関数であり、 文字列を返す必要がある。 引数sequenceは、文字テーブル以外の任意の種類のシーケンスでよい。 つまり、リスト、ベクトル、ブールベクトル、あるいは、文字列である。

(mapconcat 'symbol-name
           '(The cat in the hat)
           " ")
     => "The cat in the hat"

(mapconcat (function (lambda (x) (format "%c" (1+ x))))
           "HAL-8000"
           "")
     => "IBM.9111"


Node:Anonymous Functions, Next:, Previous:Mapping Functions, Up:Functions

無名関数

Lispでは、関数とは、lambdaで始まるリスト、 そのようなリストをコンパイルしたバイトコード関数、 あるいは、基本関数のsubrオブジェクトです。 名前は『余分』なのです。 普通の関数はdefunで定義し、そのとき名前を与えますが、 明示的なラムダ式、つまり、無名関数を使ったほうがより簡素な場合もあります。 そのようなリストは、関数名を使える場面ならば、どこでも使えます。

そのようなリストをどんな方法で作っても、正しい関数となります。 つぎのようにしてもかまわないのです。

(setq silly (append '(lambda (x)) (list (list '+ (* 3 4) 'x))))
=> (lambda (x) (+ 12 x))

これは、(lambda (x) (+ 12 x))のようなリストを計算し、 その値をsillyの値(関数定義ではない!)とします。

この関数はつぎのように呼び出せます。

(funcall silly 1)
=> 13

(silly 1)と書いても動作しない。 なぜなら、この関数は、silly関数定義ではないからである。 sillyには関数定義を与えてなく、 変数としての値を与えただけである。)

ほとんどの場合、無名関数は読者のプログラムに現れる定数です。 たとえば、関数mapcarの引数の1つに渡したいときなどです。 mapcarは、リストの各要素に指定した関数を適用します。

第3引数に関数を取る関数change-propertyを定義します。

(defun change-property (symbol prop function)
  (let ((value (get symbol prop)))
    (put symbol prop (funcall function value))))

ここで、数を2倍する関数を渡してchange-propertyを使う 関数を定義します。

(defun double-property (symbol prop)
  (change-property symbol prop '(lambda (x) (* 2 x))))

このような場合、つぎのように、無名関数をクォートするには、 単純なクォートのかわりにスペシャルフォームfunctionを使います。

(defun double-property (symbol prop)
  (change-property symbol prop
                   (function (lambda (x) (* 2 x)))))

quoteのかわりにfunctionを使った場合に違いがでるのは、 関数double-propertyをコンパイルしたときです。 たとえば、double-propertyの2番目の定義をコンパイルすると、 無名関数もコンパイルされます。 一方、普通のquoteを使った最初の定義をコンパイルすると、 change-propertyへ渡す引数は、書いたとおりのリストです。

(lambda (x) (* x 2))

Lispコンパイラは、このリストが関数に見えたとしても、 このリストを関数とはみなしません。 というのは、コンパイラにはchange-propertyがリストになにを行うか わからないからです。 たぶん、第3要素のCARがシンボル*か どうか調べればよいのでしょう! functionを使うと、コンパイラに対して先へ進んで 定数の関数をコンパイルしても安全であることを伝えます。

関数名をクォートするときにquoteのかわりにfunctionを 書くこともありますが、この用法はコメントのようなものです。

(function symbol) == (quote symbol) == 'symbol

入力構文#'は、functionの省略形です。 たとえば、

#'(lambda (x) (* x x))

は、つぎと等価です。

(function (lambda (x) (* x x)))

function function-object Special Form
このスペシャルフォームは、function-objectを評価せずに function-objectを返す。 この意味ではquoteに等価である。 しかし、これは、Emacs Lispコンパイラに対しては注意書きとして働き、 function-objectを関数としてのみ使う意図があり、 したがって、コンパイルしても安全であることを意味する。 Quotingquoteと比較してほしい。

functionと無名関数を用いた実際的な例は、 Accessing Documentationdocumentationを参照してください。


Node:Function Cells, Next:, Previous:Anonymous Functions, Up:Functions

関数セルの内容の参照

シンボルの関数定義(function definition)とは、 シンボルの関数セルに格納されたオブジェクトです。 ここで説明する関数は、シンボルの関数セルを参照したり、調べたり、 設定したりします。 Function Indirectionの関数indirect-functionも参照してください。

symbol-function symbol Function
これは、symbolの関数セルのオブジェクトを返す。 シンボルの関数セルが空であると、エラーvoid-functionを通知する。

この関数は、返すオブジェクトが正しい関数であるかどうか検査しない。

(defun bar (n) (+ n 2))
     => bar
(symbol-function 'bar)
     => (lambda (n) (+ n 2))
(fset 'baz 'bar)
     => bar
(symbol-function 'baz)
     => bar

シンボルに一度も関数定義を与えていないと、 そのシンボルの関数セルは(void)であるといいます。 いいかえれば、関数セルにはどんなLispオブジェクトも入っていません。 そのようなシンボルを関数として呼び出そうとすると、 エラーvoid-functionを通知します。

空(void)は、nilやシンボルvoidと違うことに注意してください。 シンボルnilvoidもLispオブジェクトであり、 それらは他のオブジェクトと同様に関数セルに格納できます (そして、それらをdefunで定義しておけば、正しい関数である)。 空の関数セルには、どんなオブジェクトも含まれていません。

シンボルの関数定義が空かどうかはfboundpで調べることができます。 シンボルに関数定義を与えたあとでも、 fmakunboundを使ってふたたび空にできます。

fboundp symbol Function
この関数は、シンボルの関数セルにオブジェクトが入っていればtを返し、 さもなければnilを返す。 オブジェクトが正しい関数であるかどうか検査しない。

fmakunbound symbol Function
この関数はsymbolの関数セルを空にする。 これ以降にこのセルを参照しようとすると、 エラーvoid-functionを引き起こす。 (Void Variablesmakunboundも参照)。
(defun foo (x) x)
     => foo
(foo 1)
     =>1
(fmakunbound 'foo)
     => foo
(foo 1)
error--> Symbol's function definition is void: foo

fset symbol definition Function
この関数は、symbolの関数セルにdefinitionを格納する。 結果はdefinitionである。 通常、definitionは関数か関数名であるべきだが、 そうであるかどうか検査しない。 引数symbolは通常どおり評価される引数である。

この関数の普通の3つの使い方はつぎのとおり。

  • あるシンボルの関数定義を別のものにコピーする。 いいかえれば、関数の別名を作る。 (これを新たな名前の定義と考えるならば、 fsetのかわりにdefaliasを使うべきである。 see Defining Functions。)
  • リストではない関数定義をシンボルに与える。 これは、defunではできない。 たとえば、fsetを使って、s1に関数定義として 別のシンボルs2を与えることができる。 すると、s1は、s2の現在の定義の別名として働く。 (これをs1の定義と考えるのであれば、 やはり、fsetのかわりにdefaliasを使う。)
  • 関数を定義したり変更したりする構文で使う。 defunが基本関数でなかったならば、 fsetを使って(マクロとして)Lispでdefunを書くことができる。

これらの使用例を示す。

;; fooの定義をold-fooに保存する
(fset 'old-foo (symbol-function 'foo))

;; シンボルcarxfirstの関数定義にする
;; (これには、fsetよりdefaliasのほうがよい)
(fset 'xfirst 'car)
     => car
(xfirst '(1 2 3))
     => 1
(symbol-function 'xfirst)
     => car
(symbol-function (symbol-function 'xfirst))
     => #<subr car>

;; 名前付きのキーボードマクロを定義する
(fset 'kill-two-lines "\^u2\^k")
     => "\^u2\^k"

;; 他の関数を変更する関数
(defun copy-function-definition (new old)
  "Define NEW with the same function definition as OLD."
  (fset new (symbol-function old)))

既存の関数定義を拡張する関数を書くときには、 つぎのような常套句を使うこともあります。

(fset 'old-foo (symbol-function 'foo))
(defun foo ()
  "Just like old-foo, except more so."
  (old-foo)
  (more-so))

fooが自動ロードと定義されていると、これは正しく動作しません。 そのような場合には、fooold-fooを呼び出すと、 Lispはファイルをロードしてold-fooを定義しようとします。 しかし、これはold-fooではなくfooを定義するので、 正しい結果を得られません。 この問題を回避する唯一の方法は、 fooの古い定義を移すまえに、確実にファイルをロードしておくことです。

しかし、別の箇所で定義された関数を再定義するLispファイルに対しては、 いずれにしても、これではモジュール化も見通しもよくありません。 アドバイズ機能(see Advising Functions)を使えば、見通しがよくなります。


Node:Inline Functions, Next:, Previous:Function Cells, Up:Functions

インライン関数

defunのかわりにdefsubstを使うことで、 インライン関数(inline function)を定義できます。 インライン関数は、1つの点を除いて、普通の関数と同様に動作します。 そのような関数の呼び出しをコンパイルすると、 関数定義は呼び出し側で展開されます。

関数を展開すると明示的な呼び出しが高速になります。 しかし、それには欠点もあります。 その1つは、柔軟性を減らすことです。 関数の定義を変更しても、コンパイルし直すまでは、 すでに展開された呼び出しは古い定義を使い続けます。 関数を再定義できる柔軟性はEmacsでは重要な機能ですから、 速度が本当に重要でなければ、関数を展開すべきではありません。

別の欠点は、大きな関数を展開すると、コンパイルした関数のサイズが ファイル内でもメモリ上でも増加します。 インライン関数のスピードの利点は、小さな関数でもっとも大きいので、 一般には大きな関数を展開すべきではありません。

インライン関数が実行するのと同じコードに展開するようにマクロを定義する ことも可能です。 (see Macros。) しかし、マクロは式で直接使った場合に制限されます。 マクロは、applymapcarなどで呼び出せません。 さらに、普通の関数をマクロに変換するには、多少の作業が必要です。 普通の関数をインライン関数に変換するのはとても簡単です。 単に、defundefsubstで置き換えるだけです。 インライン関数の各引数は、ちょうど1回だけ評価されるので、 マクロのように本体で引数を何回使うかを考慮する必要はありません。 (see Argument Evaluation。)

インライン関数は、マクロと同様に、 同じファイル内の定義位置よりうしろで使われ展開されます。


Node:Related Topics, Previous:Inline Functions, Up:Functions

関数に関連したその他の話題

関数呼び出しと関数定義に関連したいくつかの関数の一覧をあげておきます。 これらは別の場所で説明してありますが、相互参照をあげておきます。

apply
see Calling Functions
autoload
see Autoload
call-interactively
see Interactive Call
commandp
see Interactive Call
documentation
see Accessing Documentation
eval
see Eval
funcall
see Calling Functions
function
see Anonymous Functions
ignore
see Calling Functions
indirect-function
see Function Indirection
interactive
see Using Interactive
interactive-p
see Interactive Call
mapatoms
see Creating Symbols
mapcar
see Mapping Functions
map-char-table
see Char-Tables
mapconcat
see Mapping Functions
undefined
see Key Lookup


Node:Macros, Next:, Previous:Functions, Up:Top

マクロ

マクロ(macros)により、 新たな制御構造の構文を定義したり、他の言語の機能を定義したりできます。 マクロは関数のように定義しますが、値の計算方法を指示するかわりに、 値を計算するための別のLisp式の計算方法を指示します。 この式をマクロの展開形(expansion)と呼びます。

マクロでこのようなことができるのは、 関数が評価済みの引数を操作するのに対して、 マクロは引数の未評価の式を操作するからです。 そのため、これらの引数の式やその一部を含む展開形を構築できるのです。

実行速度のために普通の関数でできることにマクロを使うのであれば、 そのかわりにインライン関数を使うことを考えてください。


Node:Simple Macro, Next:, Up:Macros

マクロの簡単な例

C言語の演算子++のように、 変数の値を増加させるLispの構文を定義したいとしましょう。 (inc x)のように書いて、 (setq x (1+ x))のような効果を得たいのです。 これを行うマクロ定義はつぎのようになります。

(defmacro inc (var)
   (list 'setq var (list '1+ var)))

これを(inc x)のように呼び出すと、 引数varはシンボルxになります。 関数のようにxではありません。 マクロの本体では、これを使って展開形(setq x (1+ x))を構築します。 マクロ定義がこの展開形を返すと、 Lispはそれを評価することに進み、xを増やします。


Node:Expansion, Next:, Previous:Simple Macro, Up:Macros

マクロ呼び出しの展開

マクロ呼び出しはマクロ名で始まるリストであり、 関数呼び出しとほとんど同じに見えます。 リストの残りの要素はマクロの引数です。

マクロ呼び出しの評価は、関数呼び出しの評価のように始められますが、 1つだけ重要な違いがあります。 マクロの引数は、マクロ呼び出しに現れた実際の引数です。 マクロ定義に渡すまえに、それらを評価しません。 一方、関数の引数は、関数呼び出しのリストの要素を評価した結果です。

引数を得ると、Lispは関数定義を起動するのと同様にマクロ定義を起動します。 マクロの引数変数は、マクロ呼び出しの引数値や &rest引数の場合にはそれらのリストに束縛されます。 そうして、マクロ本体を実行し、関数本体と同様に値を返します。

マクロと関数の重要な違いの2つめは、 マクロ本体が返した値はマクロ呼び出しの値ではないことです。 戻り値は値を計算するためのかわりの式であり、 これをマクロの展開形(expansion)といいます。 Lispインタープリタは、マクロから戻ってくると、 ただちに展開形を評価することへ進みます。

展開形は、通常どおりに評価されるので、 展開形から他のマクロを呼び出してもかまいません。 同一のマクロを呼び出してもかまいませんが、 それは一般的ではありません。

macroexpandを呼ぶと、指定したマクロの展開形を調べることができます。

macroexpand form &optional environment Function
この関数は、formがマクロ呼び出しならば、それを展開する。 その結果がまた別のマクロ呼び出しであれば、さらに展開する。 マクロ呼び出しでない結果を得るまでこれを繰り返す。 それが、macroexpandが返す値である。 formが始めからマクロ呼び出しでなければ、 与えられたとおりのものを返す。

macroexpandformの部分式を調べないことに注意してほしい (ただし、マクロ定義によっては調べるかもしれない)。 部分式がマクロ呼び出しであったとしても、 macroexpandはそれらを展開しない。

関数macroexpandは、インライン関数の呼び出しは展開しない。 インライン関数の呼び出しを理解することは普通の関数呼び出しを理解するのと かわりないので、通常、そのような展開を行う必要はない。

environmentを指定すると、 それは、現在定義済みのマクロを隠すマクロ定義の連想リストを表す。 バイトコンパイルではこの機能を使う。

(defmacro inc (var)
    (list 'setq var (list '1+ var)))
     => inc

(macroexpand '(inc r))
     => (setq r (1+ r))

(defmacro inc2 (var1 var2)
    (list 'progn (list 'inc var1) (list 'inc var2)))
     => inc2

(macroexpand '(inc2 r s))
     => (progn (inc r) (inc s))  ; ここではincを展開しない


Node:Compiling Macros, Next:, Previous:Expansion, Up:Macros

マクロとバイトコンパイル

なぜ、マクロの展開形をわざわざ計算してから展開形を評価するのか、 疑問に思うかもしれません。 なぜ、マクロ本体で望みの結果を直接出さないのでしょう? その理由には、コンパイルが関係しています。

コンパイルするLispプログラムにマクロ呼び出しが現れると、 Lispコンパイラは、インタープリタがするのと同様にマクロ定義を呼び出し、 その展開形を受け取ります。 この展開形を評価するかわりに、コンパイラは、 展開形がプログラムに直接現れたかのようにそれをコンパイルします。 その結果、コンパイル済みのコードは、マクロが意図した値と副作用を生じ、 かつ、実行速度はコンパイルした速度になるのです。 マクロ本体そのもので値と副作用を計算したのでは、 このように動作しません。 コンパイル時に計算してしまい、それでは意味がありません。

マクロ呼び出しが正しくコンパイルされるためには、 それらの呼び出しをコンパイルするときに、 Lisp内でマクロが定義済みである必要があります。 コンパイラには、読者がこのようにすることを補佐する機能があります。 コンパイル対象のファイルにフォームdefmacroが含まれていると、 そのファイルの残りをコンパイルするあいだは、 一時的にマクロを定義します。 この機能が動作するためには、 defmacroを同じファイルの最初に利用する箇所よりまえに 入れておく必要があります。

ファイルをバイトコンパイルすると、 そのファイルのトップレベルにあるrequireの呼び出しを実行します。 これは、ファイルを正しくコンパイルするために必要なパッケージを表します。 コンパイル中に必要なマクロ定義が使えることを保証する1つの方法は、 それらのマクロを定義するファイルを requireに指定しておくことです(see Named Features)。 コンパイル済みのプログラムを実行するときに、 マクロを定義したファイルをロードしてしまうことを避けるには、 requireの呼び出しの周りにeval-when-compileを書いておきます (see Eval During Compile)。


Node:Defining Macros, Next:, Previous:Compiling Macros, Up:Macros

マクロ定義

Lispのマクロは、そのCARmacroであるリストです。 そのCDRは関数であるべきです。 マクロの展開は、マクロ呼び出しの未評価の引数式に (applyで)関数を適用して動作します。

無名関数のように無名Lispマクロを使うことも可能ですが、 けっしてしないでしょう。 mapcarのようなファンクショナルに無名マクロを渡す意味がないからです。 実用上は、すべてのLispマクロには名前があり、 普通、スペシャルフォームdefmacroで定義します。

defmacro name argument-list body-forms... Special Form
defmacroは、シンボルnameをつぎのようなマクロとして定義する。
(macro lambda argument-list . body-forms)

(このリストのCDRは関数、つまり、ラムダ式であることに注意。) このマクロオブジェクトは、nameの関数セルに格納される。 フォームdefmacroを評価した結果、返される値はnameであるが、 通常この値は無視する。

argument-listの形式と意味は、関数のそれと同じであり、 キーワード&rest&optionalを使ってもよい (see Argument List)。 マクロにも説明文字列を指定できるが、 マクロを対話的に呼び出すことはできないので、 interactive宣言は無視する。


Node:Backquote, Next:, Previous:Defining Macros, Up:Macros

バッククォート

マクロでは、定数部分と非定数部分を組み合わせた大きなリスト構造を 構築する必要がしばしばあります。 これを簡単に行うためには、 (通常、バッククォート(backquote)と呼ばれる)`構文を 使います。

バッククォートにより、リストの要素を選択に評価しつつ、 リストをクォートできます。 もっとも単純な場合、これはスペシャルフォームquote(see Quoting)と 等価です。 たとえば、つぎの2つのフォームは等価な結果になります。

`(a list of (+ 2 3) elements)
     => (a list of (+ 2 3) elements)
'(a list of (+ 2 3) elements)
     => (a list of (+ 2 3) elements)

バッククォートの引数の内側にある特別な印,は、 値が定数ではないことを表します。 バッククォートは、リスト構造の中の,の引数を評価し、 値で置き換えます。

(list 'a 'list 'of (+ 2 3) 'elements)
     => (a list of 5 elements)
`(a list of ,(+ 2 3) elements)
     => (a list of 5 elements)

,による置き換えは、リスト構造の深いレベルでも許されます。 たとえば、つぎのとおりです。

(defmacro t-becomes-nil (variable)
  `(if (eq ,variable t)
       (setq ,variable nil)))

(t-becomes-nil foo)
     == (if (eq foo t) (setq foo nil))

特別な印,@を使って、 評価結果を結果となるリストに繋ぎ合わせる(splice)こともできます。 繋ぎ合わせたリストの要素は、結果となるリストの他の要素と同じレベルになります。 `を使わない等価なコードはしばしば読み難くなります。 例をあげましょう。

(setq some-list '(2 3))
     => (2 3)
(cons 1 (append some-list '(4) some-list))
     => (1 2 3 4 2 3)
`(1 ,@some-list 4 ,@some-list)
     => (1 2 3 4 2 3)

(setq list '(hack foo bar))
     => (hack foo bar)
(cons 'use
  (cons 'the
    (cons 'words (append (cdr list) '(as elements)))))
     => (use the words foo bar as elements)
`(use the words ,@(cdr list) as elements)
     => (use the words foo bar as elements)

19.29版よりまえのEmacsの旧版では、 `の構文は異なっていて、 バッククォート構文全体を囲む括弧の余分なレベルが必要でした。 同様に、,,@の置換でも、 ,,@、および後続の式を囲む括弧の余分なレベルが1つ必要でした。 古い構文では、`,,@と後続の式とのあいだには 空白が必要でした。

この構文も受け付けますが、これはEmacsの旧版との互換性のためであり、 新しいプログラムでは使わないことを勧めます。


Node:Problems with Macros, Previous:Backquote, Up:Macros

マクロ使用時の一般的な問題

マクロ展開に関する基本的事実には、直観的でない結果があります。 本節では、問題を引き起こしかねない重要な結果を説明し、 問題を回避するための規則を説明します。


Node:Argument Evaluation, Next:, Up:Problems with Macros

マクロ引数の複数回評価

マクロを定義するときには、展開形を実行するときに、 引数が何回評価かされるかに注意を払う必要があります。 つぎの(繰り返しを行う)マクロで、この問題を示しましょう。 このマクロで、Pascalにあるような単純な『for』ループを書けます。

(defmacro for (var from init to final do &rest body)
  "Execute a simple \"for\" loop.
For example, (for i from 1 to 10 do (print i))."
  (list 'let (list (list var init))
        (cons 'while (cons (list '<= var final)
                           (append body (list (list 'inc var)))))))
=> for

(for i from 1 to 3 do
   (setq square (* i i))
   (princ (format "\n%d %d" i square)))
==>
(let ((i 1))
  (while (<= i 3)
    (setq square (* i i))
    (princ (format "%d      %d" i square))
    (inc i)))

     -|1       1
     -|2       4
     -|3       9
=> nil

このマクロの引数、fromtodoは、 『シンタックスシュガー』であり、完全に無視します。 (fromtodoなどの)余分な単語を マクロ呼び出しのこの引数位置に書けるようにするのです。

バッククォートを使って単純化した等価な定義をつぎに示します。

(defmacro for (var from init to final do &rest body)
  "Execute a simple \"for\" loop.
For example, (for i from 1 to 10 do (print i))."
  `(let ((,var ,init))
     (while (<= ,var ,final)
       ,@body
       (inc ,var))))

この定義の(バッククォートありとなしの)どちらの形式でも、 各繰り返しごとにfinalが評価されるという欠陥があります。 finalが定数ならば、これは問題になりません。 たとえば(long-complex-calculation x)のような、 より複雑なフォームであると、実行速度をかなり遅くしてしまいます。 finalに副作用があると、複数回評価するのは正しくありません。

繰り返し評価することがマクロの意図している目的の一部でなければ、 よく設計されたマクロ定義では、 引数をちょうど1回だけ評価するような展開形を生成して、 上のような問題を回避するように手立てします。

(let ((i 1)
      (max 3))
  (while (<= i max)
    (setq square (* i i))
    (princ (format "%d      %d" i square))
    (inc i)))

このような展開形を作るマクロ定義はつぎのようになります。

(defmacro for (var from init to final do &rest body)
  "Execute a simple for loop: (for i from 1 to 10 do (print i))."
  `(let ((,var ,init)
         (max ,final))
     (while (<= ,var max)
       ,@body
       (inc ,var))))

残念なことに、この修正は、 次節に説明する別の問題を引き起こします。


Node:Surprising Local Vars, Next:, Previous:Argument Evaluation, Up:Problems with Macros

マクロ展開形内のローカル変数

forの新しい定義には、新たな問題があります。 ユーザーが予期していないローカル変数maxを導入しているのです。 これは、つぎのような場合、問題を引き起こします。

(let ((max 0))
  (for x from 0 to 10 do
    (let ((this (frob x)))
      (if (< max this)
          (setq max this)))))

forの本体内でのmaxの参照は、 ユーザーが束縛したmaxを参照するものと期待されていますが、 実際にはforが作った束縛を使います。

これを修正するには、maxのかわりに、 インターンしてないシンボル(see Creating Symbols)を使います。 インターンしてないシンボルは、他のシンボルと同様に、 束縛したり参照したりできますが、forで作ったので、 ユーザープログラムには現れていないことがわかっています。 インターンしてないので、ユーザーがプログラムのあとの部分で 参照する方法もありません。 forで使った箇所以外には現れえないのです。 このように動作するforの定義をつぎに示します。

(defmacro for (var from init to final do &rest body)
  "Execute a simple for loop: (for i from 1 to 10 do (print i))."
  (let ((tempvar (make-symbol "max")))
    `(let ((,var ,init)
           (,tempvar ,final))
       (while (<= ,var ,tempvar)
         ,@body
         (inc ,var)))))

これは、maxという名前のインターンしてないシンボルを作成し、 もとの式に現れていたインターンしたシンボルmaxのかわりに 展開形内部で使います。


Node:Eval During Expansion, Next:, Previous:Surprising Local Vars, Up:Problems with Macros

展開形におけるマクロ引数の評価

eval(see Eval)を呼び出すなどして、 マクロ定義そのものの中でマクロ引数の式を評価すると、 別の問題を生じます。 引数でユーザーの変数を参照する場合、 ユーザーがマクロ引数の1つと同じ名前を使っていると、 問題になります。 マクロ本体の内側では、マクロ引数の束縛が最ローカルな束縛ですから、 そのフォームの内側からの参照は、この束縛を使います。 例を示しましょう。

(defmacro foo (a)
  (list 'setq (eval a) t))
     => foo
(setq x 'b)
(foo x) ==> (setq b t)
     => t                  ; bを設定する
;; しかし
(setq a 'c)
(foo a) ==> (setq a t)
     => t                  ; cではなくaを設定する

ユーザーの引数の名前がaxかで違いがでます。 というのは、マクロ引数の変数aaが衝突するからです。

マクロ定義内でevalを呼び出したときの別の問題点は、 コンパイルしたプログラムでは、意図した動作をしないだろうということです。 バイトコンパイラは、プログラムをコンパイル中にマクロ定義を実行しますから、 (evalで参照したい)プログラムそのものの計算は行われず、 そのローカル変数の束縛も存在しません。

これらの問題を回避するには、 マクロ展開の計算過程では、引数の式を評価しないことです。 そのかわりに、マクロ展開では式の置換を使って、 展開時にその値が計算されるようにします。 このようにすれば、本章の他の例題は動作します。


Node:Repeated Expansion, Previous:Eval During Expansion, Up:Problems with Macros

マクロは何回展開されるか

関数を解釈実行しているときには、マクロ呼び出しを評価するたびに展開しますが、 コンパイルした関数では、(コンパイル時に)1回だけ展開します。 この違いが問題になることもあります。 マクロ定義に副作用があると、 マクロを何回展開したかに依存して動作が異なります。

したがって、マクロ展開の計算では、 本当になにをしているのか理解していない限り、副作用は避けてください。

特別な種類の副作用の1つ、つまり、 Lispオブジェクトを構築することは回避できません。 ほとんどすべてのマクロ展開では、リストを構築し、 それがマクロの重要な点でもあります。 これは、通常、安全ですが、 1つだけ注意する必要があります。 読者が構築したオブジェクトが、 マクロ展開形の中のクォートした定数の一部であるときです。

コンパイル時にマクロを1回だけ展開すると、 コンパイル中にはオブジェクトは一度だけ作られます。 しかし、解釈実行中には、マクロ呼び出しを行うたびにマクロを展開するので、 そのたびに新たなオブジェクトが作成されたことを意味します。

見通しのよいほとんどのLispコードでは、この違いは関係ありません。 マクロ定義で構築したオブジェクトに副作用のある操作を行うと 違いが出てきます。 したがって、問題を回避するには、 マクロ定義で構築したオブジェクトに副作用のある操作は行わない ということです。 そのような副作用がどのように問題を引き起こすのか、例をあげましょう。

(defmacro empty-object ()
  (list 'quote (cons nil nil)))

(defun initialize (condition)
  (let ((object (empty-object)))
    (if condition
        (setcar object condition))
    object))

initializeを解釈実行しているときには、 initializeを呼び出すたびに新たなリスト(nil)が作られます。 したがって、2つの呼び出しのあいだで副作用が残ることはありません。 initializeをコンパイルしてあると、 マクロempty-objectはコンパイル時に展開され、 1つの『定数』(nil)を作りますが、 これは、initializeを呼び出すたびに、 再利用され変更されてしまいます。

このような病的な場面を回避する1つの方法は、 empty-objectを、メモリ割り付けではなく、 ある種の定数と考えることです。 '(nil)のような定数にsetcarは使わないでしょうから、 (empty-object)も自然にそのように使わないでしょう。


Node:Customization, Next:, Previous:Macros, Up:Top

カスタマイズ定義の書き方

本章では、カスタマイズのためのユーザーオプションの宣言方法、 および、それらを分類するカスタマイズグループの宣言方法を説明します。 フェイスの定義(see Defining Faces)に加えて、 カスタマイズの両方の種類を含めて、 カスタマイズ項目(customization item)という用語を使います。


Node:Common Keywords, Next:, Up:Customization

すべての種類の項目に共通のキーワード

(変数やグループ、フェイスの)すべての種類のカスタマイズ宣言では、 さまざまな情報を指定するためのキーワード引数を受け付けます。 本節では、全種類に適用できるキーワードを説明します。

:tagを除くこれらのキーワードすべては、各項目で複数回使えます。 キーワードのそれぞれの使用には、独立の効果があります。 キーワード:tagは例外です。 任意の項目には名前を1つしか表示できないからです。

:tag name
カスタマイズメニューやカスタマイズバッファ内で 項目に付けるラベルとして、項目の名前のかわりに文字列nameを使う。
:group group
このカスタマイズ項目をグループgroupに入れる。 defgroupの中で:groupを使うと、 新たなグループをgroupの下位グループにする。

このキーワードを複数回使うと、 1つの項目を複数のグループに入れることができる。 それらのグループのどれを表示しても、この項目が表示される。 これを多用しすぎないように注意すること!

:link link-data
この項目に対する説明文字列のうしろに外部リンクを含める。 これは、他の説明文字列を参照するアクティブフィールドを含む文である。

link-dataとして使えるものは3種類ある。

(custom-manual info-node)
infoのノードへリンクする。 info-nodeは、"(emacs)Top"のようなノード名を指定する文字列。 リンクは、カスタマイズバッファでは[manual]のように表示される。
(info-link info-node)
custom-manualと同様であるが、 カスタマイズバッファに現れるリンクはinfoのノード名になる。
(url-link url)
webページへリンクする。 urlは、URLを指定する文字列。 カスタマイズバッファに現れるリンクはurlになる。

link-dataの先頭要素のうしろに:tag nameを使うことで、 カスタマイズバッファに使うテキストを指定できる。 たとえば、(info-link :tag "foo" "(emacs)Top")とすると、 バッファではfooと表示されるEmacsマニュアルへのリンクを作れる。

1つの項目に複数個の外部リンクがあってもよいが、 ほとんどの項目には外部リンクはない。

:load file
このカスタマイズ項目を表示するまえにファイルfile(文字列)をロードする。 ファイルをすでにロードしていない場合に限り、 load-libraryでロードする。
:require feature
カスタマイズ機能を用いて保存するこの項目に対する値をインストールするときに 必要となる機能feature(シンボル)を指定する。 requireを呼び出す。

:requireを使うもっとも一般的な理由は、 変数がマイナモードなどの機能をオンにするとき、 そのモードを実装するコードをロードしてないと、 変数にはなんの効果もないからである。


Node:Group Definitions, Next:, Previous:Common Keywords, Up:Customization

カスタマイズグループを定義する

Emacs Lispの各パッケージには、 そのパッケージのすべてのオプション、フェイス、他のグループを含んだ 1つの主要なカスタマイズグループがあるべきです。 パッケージに少数のオプションやフェイスしかなければ、 それらを1つのグループにまとめます。 12個を超えるオプションやフェイスがある場合には、 それらを下位グループに構造化して、 下位グループすべてをパッケージの主カスタマイズグループに入れておきます。 パッケージの主グループに下位グループとともにいくつかのオプションやフェイスを 入れておくのもよいでしょう。

パッケージの主グループや単一のグループは、 標準カスタマイズグループの1つかそれ以上のメンバであるべきです。 (それらの完全な一覧を表示するにはM-x customizeを使う。) それらの中から1個か数個を選び(多すぎないこと)、 キーワード:groupを使って、それぞれに読者のグループを追加します。

新たなカスタマイズグループは、defgroupで宣言します。

defgroup group members doc [keyword value]... Macro
membersを含むカスタマイズグループとしてgroupを宣言する。 シンボルgroupをクォートしないこと。 引数docは、グループの説明文字列を指定する。

引数membersは、グループのメンバとなる カスタマイズ項目の初期集合を指定するリストである。 しかし、ほとんどの場合、membersnilであり、 それらのメンバを定義するときに、キーワード:groupを使って、 グループのメンバであることを指定する。

membersでグループのメンバを指定する場合には、 各要素は(name widget)という形式であること。 ここで、nameはシンボル、 widgetはそのシンボルを編集するためのウィジェット型である。 有用なウィジェットは、変数に対してはcustom-variable、 フェイスに対してはcustom-face、 グループに対してはcustom-groupである。

共通のキーワード(see Common Keywords)に加えて、 defgroupではつぎのキーワードも使える。

:prefix prefix
グループ内の項目の名前がprefixで始まるときには、 その項目に対するタグを(デフォルトでは)prefixを省略して作る。

1つのグループにprefixがいくつあってもよい。

接頭辞を取りさる機能は、現在、オフにしてあります。 つまり、:prefixは、現在、なんの効果もありません。 このようにしたのは、指定した接頭辞を取りさると、 オプション名がしばしば混乱するからです。 さまざまなグループのdefgroup定義を書く人は、 論理的と考えられるとき、つまり、ライブラリに共通の接頭辞があるときには キーワード:prefixを追加するので、このようになるのです。

:prefixを使ってよい結果を得るには、 グループ内の特定の項目とそれらの名前と説明文字列に関して、 特定の接頭辞を取りさった場合の効果を調べる必要があります。 その結果、テキストがわかり難ければ、 その場面では、:prefixを使うべきではないのでしょう。

カスタマイズグループすべてを調べ直して、 わかり難くなる結果をもたらす:prefix指定を削除し、 この機能をオンにすることは、誰かが頑張れば、可能です。


Node:Variable Definitions, Next:, Previous:Group Definitions, Up:Customization

カスタマイズ変数を定義する

defcustomを使って、ユーザーが編集可能な変数を宣言します。

defcustom option default doc [keyword value]... Macro
カスタマイズ可能なユーザーオプション変数としてoptionを宣言する。 optionをクォートしないこと。 引数docは変数の説明文字列を指定する。

optionが空であると、defcustomdefaultで初期化する。 defaultは値を計算する式であること。 これは複数回評価される可能性があるので、書き方には注意すること。

defcustomでは、つぎの追加キーワードも使えます。

:type type
このオプションのデータ型としてtypeを使う。 これは、正しい値とその表示方法を指定する。 詳しくは、see Customization Types
:options list
このオプションに使える合理的な値のリストとしてlistを指定する。

これは、現時点では、型がhookのときだけ意味を持つ。 その場合、listの要素は、フックの値の要素として使える関数であること。 ユーザーはこれらの関数以外も使えるが、便利な選択肢として提示する。

:version version
このオプションは、変数を最初に導入したり、デフォルト値を変更したりした Emacsの版versionを指定する。 値versionは、文字列であること。 たとえば、つぎのとおり。
(defcustom foo-max 34
  "*Maximum number of foo's allowed."
  :type 'integer
  :group 'foo
  :version "20.3")

:set setfunction
このオプションの値を変更する方法としてsetfunctionを指定する。 関数setfunctionは、2つの引数、つまり、シンボルと新しい値を取り、 このオプションの値を(Lisp変数としてオプションを設定するだけでなく) 適切に更新するために必要なことを行うこと。 setfunctionのデフォルトはset-default
:get getfunction
このオプションの値を取り出す方法としてgetfunctionを指定する。 関数getfunctionは、1つの引数、つまり、シンボルを取り、 そのシンボル(のLisp値とは必ずしも限らない)の『現在値』を返すこと。 デフォルトはdefault-value
:initialize function
functionは、defcustomを評価したときに変数の初期化に使う関数。 この関数は、2つの引数、つまり、シンボルと値を取ること。 このように使うことを意図した定義済みの関数がいくつかある。
custom-initialize-set
変数の:set関数を使って変数を初期化するが、 変数の値が空でないときには再初期化しない。 これは:initializeのデフォルト。
custom-initialize-default
custom-initialize-setに似ているが、 変数の:set関数のかわりに関数set-defaultを使って変数を設定する。 変数の:set関数がマイナモードをオン/オフする場合には、 普通はこれを選ぶ。 これを選ぶと、変数を定義してもマイナモード関数を呼び出さないが、 変数をカスタマイズするとマイナモード関数を呼び出す。
custom-initialize-reset
変数を初期化するにはつねに:set関数を使う。 変数の値が空でない場合には、(:getで得られる)現在値で :set関数を呼び出して、変数をリセットする。
custom-initialize-changed
変数がすでに設定されていたりカスタマイズしてあるときに、 変数を初期化するために:set関数を使う。 さもなければ、set-defaultを使う。

:requireオプションは、 特定の機能をオンにするようなオプションには便利です。 パッケージがオプション変数の値を検査するように書かれていたとしても、 パッケージをロードするようにする必要があります。 これを:requireで行えるのです。 See Common Keywords。 ライブラリparen.elからとった例をつぎに示します。

(defcustom show-paren-mode nil
  "Toggle Show Paren mode...."
  :set (lambda (symbol value)
         (show-paren-mode (or value 0)))
  :initialize 'custom-initialize-default
  :type 'boolean
  :group 'paren-showing
  :require 'paren)

内部的には、defcustomは、 デフォルト値を与える式は属性standard-valueを使って記録し、 ユーザーがカスタマイズバッファで保存した値は 属性saved-valueを使って記録しています。 属性saved-valueは実際にはリストであり、 そのCARが値に評価される式です。


Node:Customization Types, Previous:Variable Definitions, Up:Customization

カスタマイズ型

defcustomでユーザーオプションを定義するときには、 そのカスタマイズ型(customization type)を定義する必要があります。 これはLispオブジェクトであり、 (1)どのような値が正しいものであり、 (2)編集用にカスタマイズバッファに表示する方法、 を示します。

カスタマイズ型は、defcustom内の:typeキーワードで指定します。 :typeの引数は評価されます。 実行時に型が変わるものはほとんど使い途がないので、 普通、クォートした型を指定します。 たとえば、つぎのとおりです。

(defcustom diff-command "diff"
  "*The command to use to run diff."
  :type '(string)
  :group 'diff)

一般に、カスタマイズ型はリストであり、 その先頭要素はシンボルで、次節以降で定義するカスタマイズ型名の1つです。 このシンボルのあとには、シンボルに依存した数個の引数が続きます。 型シンボルとその引数のあいだには、 キーワード・値の対を書くこともできます (see Type Keywords)。

型シンボルには、引数を取らないものもあります。 これらを単純型(simple types)と呼びます。 単純型では、キーワード・値の対を指定しなければ、 型シンボルを囲む括弧を省略できます。 たとえば、カスタマイズ型としてのstringは、 (string)と等価です。


Node:Simple Types, Next:, Up:Customization Types

単純型

本節では、すべての単純型を説明します。

sexp
値は、表示したり読み取れるならば、任意のLispオブジェクトでよい。 使用する型をより限定する手間を省きたければ、 任意のオプションに対するデフォルトとして、 sexpを使うことができる。
integer
値は整数である必要があり、カスタマイズバッファではテキストで表示する。
number
値は数である必要があり、カスタマイズバッファではテキストで表示する。
string
値は文字列である必要があり、 カスタマイズバッファでは、その内容だけを表示し、 文字"で区切ったり、\でクォートしない。
regexp
stringと同様であるが、 文字列は正規表現である必要がある。
character
値は文字コードである必要がある。 文字コードは実際には整数であるが、 この型では、数として表示するのではなく、 文字としてバッファに挿入してその値を表示する。
file
値はファイル名である必要があり、M-<TAB>で補完できる。
(file :must-match t)
値は既存のファイル名である必要があり、M-<TAB>で補完できる。
directory
値はディレクトリ名である必要があり、M-<TAB>で補完できる。
hook
値は関数のリスト(あるいは、単一の関数。ただし、この使い方は廃れている) である必要がある。 このカスタマイズ型は、フック変数に使用する。 フックに使う推奨される関数のリストを指定するために、 フック変数のdefcustom:optionsキーワードを使用できる。 see Variable Definitions
symbol
値はシンボルである必要がある。 カスタマイズバッファでは、シンボルの名前を表示する。
function
値はラムダ式か関数名である必要がある。 関数名の場合、M-<TAB>で補完できる。
variable
値は変数名である必要があり、M-<TAB>で補完できる。
face
値はフェイス名を表すシンボルである必要があり、M-<TAB>で補完できる。
boolean
値は真理値、つまり、niltである必要がある。 choiceconstを同時に使うと(次節参照)、 値はniltである必要があることを指定し、 さらに、どちらの値がどの選択肢に合うかを記述するテキストを 指定できることに注意。


Node:Composite Types, Next:, Previous:Simple Types, Up:Customization Types

複合型

単純型が適切でない場合には、 他の型から新たな型を作り上げる複合型を使えます。 これには、いくつかの方法があります。

(restricted-sexp :match-alternatives criteria)
値は、criteriaの1つを満たす任意のLispオブジェクトでよい。 criteriaはリストであり、その各要素は以下の1つであること。

たとえば、

(restricted-sexp :match-alternatives
                 (integerp 't 'nil))

は、整数、tnilが正しい値である。

カスタマイズバッファでは、すべての正しい値はその入力構文で表示し、 ユーザーはそれらをテキストとして編集する。

(cons car-type cdr-type)
値はコンスセルである必要があり、 そのCARcar-typeに合い、かつ、 そのCDRcdr-typeに合う必要がある。 たとえば、(cons string symbol)は、 ("foo" . foo)などの値に一致するカスタマイズ型である。

カスタマイズバッファでは、 CARCDRは、 それらに指定した型に応じて別々に表示され、個別に編集できる。

(list element-types...)
値はelement-typesに指定したとおりの個数のリストである必要があり、 各要素はelement-typeに合うこと。

たとえば、(list integer string function)は、 3要素のリストを意味し、 第1要素は整数、第2要素は文字列、第3要素は関数であることを指定する。

カスタマイズバッファでは、 各要素は、それらに指定した型に応じて別々に表示され、個別に編集できる。

(vector element-types...)
listと同様だが、値はリストではなくベクトルである必要がある。 その要素はlistの場合と同じ。
(choice alternative-types...)
値は、alternative-typesの少なくとも1つに合う必要がある。 たとえば、(choice integer string)は、整数か文字列を許す。

カスタマイズバッファでは、ユーザーはメニューを使って選択肢を選び、 その選択肢において普通の方法で値を編集する。

通常、このメニューの選択肢名は、選択肢から自動的に決定されるが、 選択肢に:tagキーワードを含めることで、 メニューに異なる名前を指定できる。 たとえば、整数が空白の個数を表し、文字列がそのまま使うテキストを表す場合には、 つぎのようにカスタマイズ型を書く。

(choice (integer :tag "Number of spaces")
        (string :tag "Literal text"))

そうすると、メニューには、 Number of spacesLiteral Textが表示される。

const以外のnilが正当な値ではない選択肢では、 そのような選択肢には:valueキーワードを使って 正当なデフォルト値を指定すること。 See Type Keywords

(const value)
値はvalueであること。 それ以外は許さない。

constの主な用途はchoiceの内側である。 たとえば、(choice integer (const nil))は、整数かnilを許す。

choiceの内側では、constにしばしば:tagを使う。 たとえば、

(choice (const :tag "Yes" t)
        (const :tag "No" nil)
        (const :tag "Ask" foo))

は、tは『yes』(はい)、nilは『no』(いいえ)、 fooは『ask』(問い合わせる)を意味する変数を記述する。

(other value)
この選択肢は任意のLisp値に一致するが、 ユーザーがこの選択肢を選ぶと、値valueを選ぶことになる。

otherは、主に、choiceの最後の要素として使うことである。 たとえば、

(choice (const :tag "Yes" t)
        (const :tag "No" nil)
        (other :tag "Ask" foo))

は、tは『yes』(はい)、nilは『no』(いいえ)、 それ以外は『ask』(問い合わせる)を意味することを示す。 ユーザーが選択肢のメニューからAskを選ぶと、値fooを指定する。 しかし、(tでもnilでもfooでもない)それ以外の値は、 fooと同様にAskと表示される。

(function-item function)
constと同様だが、関数であるような値に使う。 これは、関数名に加えて説明文字列を表示する。 説明文字列は、:docに指定したものか、 functionそのものの説明文字列である。
(variable-item variable)
constと同様だが、変数名であるような値に使う。 これは、変数名に加えて説明文字列を表示する。 説明文字列は、:docに指定したものか、 variableそのものの説明文字列である。
(set elements...)
値はリストである必要があり、 その各要素はelementsに指定したものの1つである必要がある。 これは、カスタマイズバッファにはチェックリストとして表示される。
(repeat element-type)
値はリストである必要があり、 その各要素はelement-typeに指定した型に合う必要がある。 これは、カスタマイズバッファには、 要素を追加したり削除したりする[INS][DEL]ボタンを伴って、 要素のリストとして表示される。


Node:Splicing into Lists, Next:, Previous:Composite Types, Up:Customization Types

リストに繋ぎ合わせる

:inline機能により、可変個数の要素をリストやベクトルの 途中に繋ぎ合わせることができます。 listvectorの要素型に現れる set型、choice型、repeat型の中に使います。

通常、listvectorのおのおのの要素型は、 リストやベクトルのたった1つの要素を記述します。 したがって、要素型がrepeatであると、 1要素として表示される長さを指定しないリストを指定します。

しかし、要素型に:inlineを使うと、 これに一致する値は、:inlineを含むシーケンスに直接に併合されます。 たとえば、3要素のリストに一致すると、 それがシーケンス全体の3つの要素になります。 これはバッククォート構文の,@の使い方に似ています。

たとえば、先頭要素がtであり、 残りがfoobarの0個以上の繰り返しであるリストを指定するには、 つぎのカスタマイズ型を使います。

(list (const t) (set :inline t foo bar))

これは、(t)(t foo)(t bar)(t foo bar)などの 値に一致します。

要素型がchoiceであるときには、 choiceそのものには:inlineを使いませんが、 choiceの選択肢(のどれか)に:inlineを使います。 たとえば、ファイル名で始まりシンボルtか2つの文字列が続くような リストに一致するようにするには、 つぎのカスタマイズ型を使います。

(list file
      (choice (const t)
              (list :inline t string string)))

ユーザーが最初の選択肢を選ぶと、全体としてのリストは2要素になり、 第2要素はtです。 ユーザーが2番目の選択肢を選ぶと、 全体としてのリストは3要素になり、 第2要素と第3要素は文字列である必要があります。


Node:Type Keywords, Previous:Splicing into Lists, Up:Customization Types

型キーワード

型名のシンボルのあとに、カスタマイズ型内にキーワード・引数の対を指定できます。 使えるキーワードとその意味を以下に示します。

:value default
choiceの内側の選択肢として現れる型に使う。 これは、カスタマイズバッファのメニューでユーザーがこの選択肢を選ぶと、 使用するデフォルト値をまず指定する。

もちろん、オプションの実際の値がこの選択肢に合えば、 defaultではなく実際の値が表示される。

選択肢の値としてnilが不正であるときには、 :valueで正当なデフォルトを指定することが本質的である。

:format format-string
この文字列は、型に対応する値を表現するためにバッファに挿入される。 format-stringには、以下に示す%を使える。
%[button%]
ボタンとして印を付けたテキストbuttonを表示する。 :action属性は、ユーザーがボタンを起動したらなにを行うかを指定する。 その値は2つの引数、つまり、ボタンが現れるウィジェットとイベント を取る関数であること。

異なるアクションを有する異なるボタンを指定する方法はない。

%{sample%}
:sample-faceで指定した特別なフェイスでsampleを表示する。
%v
項目の値で置き換える。 値の表示方法は項目の種類と、 (変数の)カスタマイズ型に依存する。
%d
項目の説明文字列で置き換える。
%h
%dと同様だが、説明文字列が1行を超えるときには、 説明文字列全体を表示するか先頭行だけを表示するかを 制御するアクティブフィールドを追加する。
%t
タグで置き換える。 タグは:tagキーワードで指定する。
%%
%をそのまま表示する。

:action action
ユーザーがボタンをクリックしたらactionを行う。
:button-face face
%[...%]で表示するボタンテキストに フェイスface(フェイス名かフェイス名のリスト)を使う。
:button-prefix prefix
:button-suffix suffix
これらは、以下のようにボタンの前後に表示するテキストを指定する。
nil
テキストを挿入しない。
文字列
文字列をそのまま挿入する。
シンボル
シンボルの値を使う。

:tag tag
この型に対応する値(やその一部)に対するタグとして tag(文字列)を使う
:doc doc
この型に対応する値(やその一部)に対する説明文字列として docを使う。 これが動作するためには、 :formatの値を指定し、かつ、 その値の中で%d%hを使う必要がある。

型に対して説明文字列を指定するのは、 :choiceの選択肢や他の複合型の一部の意味について より多くの情報をユーザーに与えるためである。

:help-echo motion-doc
widget-forwardwidget-backwardでこの項目に移動すると、 エコー領域に文字列motion-docを表示する。
:match function
値がこの型に一致することを調べる方法を指定する。 対応する値functionは、2つの引数、つまり、 ウィジェットと値を取る関数であること。 受理できる値の場合にはnil以外を返すこと。


Node:Loading, Next:, Previous:Customization, Up:Top

ロード

Lispコードのファイルをロードするとは、 その内容をLispオブジェクトの形でLisp環境に取り込むことです。 Emacsは、ファイルを探してオープンし、テキストを読み取り、 各フォームを評価し、そしてファイルをクローズします。

ロード関数は、関数eval-current-bufferがバッファ内の すべての式を評価するように、ファイル内のすべての式を評価します。 異なる点は、ロード関数は、Emacsバッファ内のテキストではなく ディスク上のファイル内のテキストを読み取って評価することです。

ロードするファイルには、Lisp式のソースコードかバイトコンパイル済みコードが 入っている必要があります。 ファイルの各フォームをトップレベルのフォーム(top-level form)と 呼びます。 ロード可能なファイル内のフォーム向けの特別な書式はありません。 ファイル内のどんなフォームでも、バッファに直接打ち込んで評価できます。 (もちろん、ほとんどのコードはこのようにして試したはず。) ほとんどの場合、フォームは関数定義や変数定義です。

Lispコードを収めたファイルをしばしばライブラリ(library)と呼びます。 したがって、『rmailライブラリ』は、rmailモード用のコードを収めたファイルです。 同様に、『Lispライブラリディレクトリ』は、 Lispコードを収めたファイルのディレクトリです。


Node:How Programs Do Loading, Next:, Up:Loading

プログラムからのロード方法

Emacs Lispには、ロードのためのインターフェイスがいくつかあります。 たとえば、autoloadは、 ファイルで定義された関数向けに場所を確保するオブジェクトを作成します。 自動ロードする関数を呼び出すと、 ファイルの実際の定義を得るためにファイルをロードします(see Autoload)。 requireは、ファイルをすでにロードしていなければロードします (see Named Features)。 これらの機構はすべて、最終的には、関数loadを呼び出して動作します。

load filename &optional missing-ok nomessage nosuffix must-suffix Function
この関数は、Lispコードのファイルを探してオープンし、 その中のフォームすべてを評価してから、ファイルをクローズする。

ファイルを探すために、 loadはまずfilename.elcという名前のファイル、 つまり、filename.elcを付加した名前のファイルを探す。 そのようなファイルが存在すれば、それをロードする。 そのような名前のファイルがなければ、 loadfilename.elという名前のファイルを探す。 そのファイルが存在すれば、それをロードする。 いずれの名前のファイルもみつからなければ、 最終的に、loadは、なにも付加しないfilenameという名前のファイルを 探し、存在すればそれをロードする。 (関数loadfilenameを探す手順は賢くない。 (load "foo.el")を評価すると、 foo.el.elという名前のファイルを探してしまう。)

省略可能な引数nosuffixnil以外であれば、 .elc.elの接尾辞を試さない。 この場合、目的のファイルの正確な名前を指定する必要がある。 正確なファイル名を指定し、かつ、nosuffixtを使えば、 foo.el.elのようなファイル名を探してしまうことを防げる。

省略可能な引数must-suffixnil以外であれば、 loadは、ディレクトリ名を明示していない限り、 ファイル名は.el.elcで終るものと仮定する。 filenameにディレクトリ名が明示してなく、かつ、 接尾辞も指定してなければ、loadは接尾辞を必ず付加する。

filenamefoobaz/foo.barのように 相対ファイル名であると、loadは変数load-pathを使って ファイルを探す。 filenameload-pathに指定した各ディレクトリを付加し、 最初にみつかったファイルをロードする。 デフォルトディレクトリを表すnilload-pathに 指定されている場合に限り、カレントディレクトリを試す。 loadは、まず最初のディレクトリで3つの可能な接尾辞を試し、 続いて2番目のディレクトリで3つの可能な接尾辞を試し、 というように行う。 see Library Search

foo.elcfoo.elより古いという旨の警告を受け取った場合には、 foo.elの再コンパイルを考えるべきである。 see Byte Compilation

(コンパイルしていない)ソースファイルをロードするときには、 Emacsがファイルを訪問する場合と同様に、 loadは文字集合を変換する。 see Coding Systems

nomessagenilであると、 ロード中にはエコー領域に Loading foo...Loading foo...doneのメッセージを表示する。

ファイルをロード中に処理できないエラーに出会うと、ロードを終了する。 autoloadによるロードの場合には、 ロード中に行われた関数定義はすべてもとに戻す。

loadがロードすべきファイルをみつけられないと、 普通、(Cannot open load file filenameを伴った) エラーfile-errorを通知する。 missing-oknil以外であれば、 loadnilを返すだけである。

変数load-read-functionを使って、 式を読み取るためにreadのかわりにloadが使う関数を指定できる。 下記参照。

ファイルを正しくロードできるとloadtを返す。

load-file filename コマンド
このコマンドはファイルfilenameをロードする。 filenameが相対ファイル名であると、 現在のデフォルトディレクトリを仮定する。 load-pathを使わず、接尾辞も付加しない。 ロードするファイル名を正確に指定したい場合にこのコマンドを使う。

load-library library コマンド
このコマンドは、libraryという名前のライブラリをロードする。 loadと等価であるが、引数を対話的に読み取る点が異なる。

load-in-progress Variable
Emacsがファイルをロード処理中であると、 この変数はnil以外であり、さもなければnilである。

load-read-function Variable
この変数は、loadeval-regionが、 readのかわりに使う、式を読み取る関数を指定する。 その関数はreadと同様に引数を1つとること。

通常、この変数の値はnilであり、 これらの関数がreadを使うことを意味する。

注意: この変数を使うかわりに、eval-regionの引数read-functionとして 関数を渡す新しい別の機能を使ったほうが見通しがよい。 see Eval

Emacs構築時のloadの使い方についての情報は、 See Building Emacs


Node:Library Search, Next:, Previous:How Programs Do Loading, Up:Loading

ライブラリの探索

EmacsがLispライブラリをロードするときには、 変数load-pathで指定したディレクトリ群でライブラリを探します。

load-path User Option
この変数の値は、loadでファイルをロードするときに探索する ディレクトリのリストである。 各要素は、(ディレクトリ名である)文字列か (カレント作業ディレクトリを表す)nilである。

load-pathの値は、環境変数EMACSLOADPATHがあれば、 それで初期化します。 さもなければ、デフォルト値は、 Emacsを構築したときにemacs/src/paths.hで指定したものです。 そして、リスト内のディレクトリのサブディレクトリをリストに追加して 拡張します。

EMACSLOADPATHの構文はPATHと同じです。 :(オペレーティングシステムによっては;)で ディレクトリ名を区切ります。 デフォルトのカレントディレクトリには.を使います。 csh.loginファイルで環境変数EMACSLOADPATHを 指定する例はつぎのとおりです。

setenv EMACSLOADPATH .:/user/bil/emacs:/usr/local/share/emacs/20.3/lisp

shを使っている場合はつぎのようにします。

export EMACSLOADPATH
EMACSLOADPATH=.:/user/bil/emacs:/usr/local/share/emacs/20.3/lisp

.emacsファイルで、 デフォルトのload-pathの先頭に複数のディレクトリを追加するには、 つぎのようなコードを書きます。

(setq load-path
      (append (list nil "/user/bil/emacs"
                    "/usr/local/lisplib"
                    "~/emacs")
              load-path))

この例では、Lispコードを、まずカレント作業ディレクトリで探索し、 続いて、/user/bil/emacsディレクトリ、 /usr/local/lisplibディレクトリ、~/emacsディレクトリ、 さらに、標準のディレクトリで探索します。

Emacsのダンプには、load-pathの特別な値を使います。 ダンプ終了時にload-pathの値が未変更(つまり、同じ特別な値)であれば、 ダンプ版Emacsは起動時に、上に述べたように、普通のload-pathの値を 使います。 しかし、ダンプ終了時にload-pathの値が別の値であれば、 ダンプ版Emacsの実行でもその(別の)値を使います。

したがって、site-init.elsite-load.elで 少数のライブラリをロードするために 一時的にload-pathを変更したい場合には、 loadの呼び出しをletで囲んで load-pathをローカルに束縛するべきです。

システムにインストールしたEmacsを実行中は、 load-pathのデフォルト値には、2つの特別なディレクトリ (とそれらのサブディレクトリ)が含まれます。

"/usr/local/share/emacs/version/site-lisp"

"/usr/local/share/emacs/site-lisp"

です。 前者は、Emacsの特定の版向けにローカルにインストールしたパッケージ用です。 後者は、Emacsの任意の版向けにローカルにインストールしたパッケージ用です。

Emacsのある版向けのパッケージが別の版ではトラブルを引き起こす理由は いくつかあります。 Emacsの互換性のない変更のために更新を必要とするパッケージもあります。 予告なしに変更される可能性のある明文化していない Emacsの内部データに依存するものもあります。 Emacsの新しい版では、パッケージの特定の版と一体になっているものもあり、 その版だけで使うべきです。

Emacsは、起動すると、ディレクトリのサブディレクトリを捜し出して、 それらをload-pathに追加します。 直下のサブディレクトリも複数レベル下のサブディレクトリも load-pathに追加します。

しかし、サブディレクトリすべてを含むわけではありません。 英数字で始まらない名前のサブディレクトリは除外します。 RCSという名前のサブディレクトリも除外します。 また、.nosearchという名前のファイルを置いた サブディレクトリも除外します。 これらの方法を用いれば、site-lispディレクトリ下の 特定のサブディレクトリの探索を防げます。

Emacsを構築したディレクトリでEmacsを起動すると、 つまり、正式にインストールしてない実行形式を起動すると、 load-pathには、普通、2つのディレクトリを追加します。 主構築ディレクトリのサブディレクトリ、lispsite-lispです。 (どちらも、絶対ファイル名で表される。)

locate-library library &optional nosuffix path interactive-call コマンド
このコマンドは、ライブラリlibraryの正確なファイル名を探す。 loadと同様にライブラリを探索する。 引数nosuffixの意味はloadと同じであり、 指定した名前libraryに接尾辞.elc.elを付加しない。

pathnil以外であると、 それはload-pathのかわりに使うディレクトリのリストである。

locate-libraryをプログラムから呼び出した場合、 文字列でファイル名を返す。 ユーザーがlocate-libraryを対話的に実行した場合、 引数interactive-calltであり、これは locate-libraryに対してファイル名をエコー領域に表示するように指示する。


Node:Loading Non-ASCII, Next:, Previous:Library Search, Up:Loading

非ASCII文字のロード

Emacs Lispプログラムが非ASCII文字の文字列定数を含む場合、 Emacs内部では、それらはユニバイト文字列かマルチバイト文字列で表現できます (see Text Representations)。 どちらの表現形式を用いるかは、 どのようにファイルをEmacsに読み込んだかに依存します。 マルチバイト表現へ復号化して読んだ場合には、 Lispプログラムのテキストはマルチバイトテキストになり、 その文字列定数はマルチバイト文字列になります。 (たとえば)Lantin-1文字を含むファイルを復号化せずに読むと、 プログラムテキストはユニバイトテキストになり、 その文字列定数はユニバイト文字列になります。 See Coding Systems

結果をより予測可能にするために、 オプション--unibyteを指定して起動した場合であっても、 Lispファイルをロードするときには、 Emacsはつねにマルチバイト表現に復号化します。 つまり、非ASCII文字の文字列定数はマルチバイト文字列に変換します。 唯一の例外は、特定のファイルで無変換を指定した場合だけです。

Emacsをこのように設計したのは、 Emacsの起動方法によらずに、 Lispプログラムが予測可能な結果をもたらすようにするためです。 さらに、こうすることで、ユニバイト動作のEmacsであっても、 マルチバイトテキストを使うことに依存したプログラムが動作します。 もちろん、そのようなプログラムは、 default-enable-multibyte-charactersを検査して適切に表現を変換して、 ユーザーがユニバイトテキストとマルチバイトテキストのどちらを 好んでいるか調べるように設計すべきです。

Emacs Lispのほとんどのプログラムでは、 非ASCII文字列はマルチバイト文字列であるということに 気づかないでしょう。 というのは、それらをユニバイトバッファに挿入すると 自動的にユニバイトに変換するからです。 しかしながら、これで違いがでるならば、 Lispファイルの先頭行のコメントに-*-unibyte: t;-*-と書くことで、 特定のLispファイルをユニバイトと解釈するように強制できます。 このように指定すると、マルチバイト動作のEmacsであっても、 そのファイルを無条件にユニバイトと解釈します。


Node:Autoload, Next:, Previous:Loading Non-ASCII, Up:Loading

自動ロード

自動ロード(autoload)機能により、 関数やマクロを定義しているファイルをロードしていなくても、 関数やマクロをLispに登録できます。 関数を初めて呼び出すと、 適切なファイルを読み込んで実際の定義と関連する他のコードを インストールしてから、すでにロードしてあったかのように実際の定義を実行します。

関数を自動的にロードするように設定する方法は2つあります。 autoloadを呼び出すか、あるいは、 ソース内の実際の定義のまえに特別な『マジック』コメントを書きます。 autoloadは自動ロードを行う低レベルの基本関数です。 任意のLispプログラムでいつでもautoloadを呼び出せます。 マジックコメントは、Emacsで使うパッケージ向けに 関数を自動的にロードするように設定するとても便利な方法です。 これらのコメントそのものはなにもしませんが、 コマンドupdate-file-autoloadsに対する指針として働きます。 このコマンドは、autoloadの呼び出しを作成し、 Emacs構築時にそれらを実行するように設定します。

autoload function filename &optional docstring interactive type Function
この関数は、functionという名前の関数(やマクロ)を filenameから自動的にロードするように定義する。 文字列filenameは、functionの実際の定義を取得するために ロードするファイルを指定する。

filenameにディレクトリ名や接尾辞.el.elcがなければ、 autoloadはこれらの接尾辞の1つを必ず付加し、 接尾辞を付けないfilenameという名前のファイルはロードしない。

引数docstringは、関数に対する説明文字列である。 通常、これは関数定義そのものの説明文字列と同一であること。 autoloadの呼び出しにおいて説明文字列を指定しておくことで、 関数の実際の定義をロードしなくても説明文を見ることが可能になる。

interactivenil以外ならば、 functionを対話的に呼び出せることを意味する。 つまり、関数の実際の定義をロードしなくても M-xの補完が動作するのである。 完全な対話指定を指定しない。 ユーザーがfunctionを実際に呼び出すまでは必要なく、 呼び出し時点で実際の定義をロードするからである。

普通の関数と同様に、マクロやキーマップも自動的にロードできる。 functionが実際にはマクロならば、typeにはmacroを指定する。 functionが実際にはキーマップならば、 typeにはkeymapを指定する。 Emacsのさまざまな部分では、 実際の定義をロードせずにこの情報を知る必要がある。

自動ロードと指定したキーマップは、 プレフィックスキーのバインディングがシンボルfunctionであるときに、 キーを探す過程で自動的にロードする。 キーマップのこれ以外の参照方法では、自動的にロードしない。 特に、変数名がシンボルfunctionと同じであっても、 Lispプログラムで変数の値からキーマップを取得して define-keyを呼び出す場合には、自動的にロードしない。

functionが自動ロードオブジェクトではない 空でない関数定義を有する場合には、 autoloadはなにもせずにnilを返す。 functionの関数セルが空であったり、 すでに自動ロードオブジェクトである場合には、 つぎのような自動ロードオブジェクトとして関数セルを定義する。

(autoload filename docstring interactive type)

たとえばつぎのとおり。

(symbol-function 'run-prolog)
     => (autoload "prolog" 169681 t nil)

この場合、"prolog"はロードすべきファイルの名前であり、 169681はファイルemacs/etc/DOC-version (see Documentation Basics)内の説明文字列を指す。 tは関数が対話的であることを示し、 nilはマクロでもキーマップでもないことを示す。

自動ロード対象のファイルでは、通常、他の定義や 複数の機能を提供したり必要としたりします。 (その内容の評価中のエラーなどで)ファイルを完全にロードできないと、 ロード中に行った関数定義やprovideの呼び出しをもとに戻します。 そのファイルから自動ロードする任意の関数をつぎに呼び出そうとしたときに、 そのファイルを再度ロードすることを保証するためです。 こうしておかないと、 自動ロードをアボートしたファイルで関数が定義されても、 そのファイルのうしろの部分で定義される その関数に必要なサブルーティンが必ずしもロードされないために その関数が動作しない可能性があるからです。

自動ロード対象のファイルで必要なLisp関数やマクロの定義に失敗すると、 "Autoloading failed to define function function-name"を 伴ったエラーを通知します。

自動ロードを指定するマジックコメントは、 ;;;###autoloadだけを書いた行であり、 自動ロード対象のソースファイル上で実際の関数定義の直前に必要です。 コマンドM-x update-file-autoloadsは、 対応するautoload呼び出しをloaddefs.elに書き込みます。 Emacs構築時にはloaddefs.elをロードするので、 autoloadを呼び出します。 M-x update-directory-autoloadsはもっと強力で、 カレントディレクトリのすべてのファイルに対する自動ロード情報を更新します。

同じマジックコメントは、任意の種類のフォームをloaddefs.elに コピーできます。 マジックコメントに続くフォームが関数定義でない場合、 そのフォームをそのままコピーします。 構築時にはフォームを実行しても、 ファイルのロード時にはそのフォームを実行しないように マジックコメントを使うこともできます。 そうするには、マジックコメントと同じ行にそのフォームを書きます。 するとそれはコメントなので、ソースファイルをロードするときにはなにもしません。 一方、M-x update-file-autoloadsはそのフォームをloaddefs.elに コピーするので、Emacs構築時には実行されるのです。

つぎの例は、マジックコメントを使ってdoctorを自動ロードする方法です。

;;;###autoload
(defun doctor ()
  "Switch to *doctor* buffer and start giving psychotherapy."
  (interactive)
  (switch-to-buffer "*doctor*")
  (doctor-mode))

こうすると、loaddefs.elではつぎのようになります。

(autoload 'doctor "doctor"
  "\
Switch to *doctor* buffer and start giving psychotherapy."
  t)

ダブルクォートの直後にバックスラッシュや改行を書く慣習は、 loaddefs.elなどの あらかじめロードするLispファイルの中だけで使うものです。 これは、make-docfileに対して、 説明文字列をetc/DOCファイルに書くように指示します。 See Building Emacs


Node:Repeated Loading, Next:, Previous:Autoload, Up:Loading

ロードの繰り返し

1つのEmacsセッションにおいて、あるファイルを複数回ロードできます。 たとえば、バッファ内の関数定義を編集して、 関数定義を書き直してインストールし直したあとで、 もとの版に戻したいこともあるでしょう。 これには、もとのファイルを再ロードすればよいのです。

ファイルをロードしたり再ロードするとき、 関数loadload-libraryは、 コンパイルしていないファイルではなく、 バイトコンパイル済みのファイルを自動的にロードすることに注意してください。 ファイルを書き直して保存してから再インストールする場合、 新しい版をバイトコンパイルする必要があります。 さもないと、Emacsは、新しいコンパイルしていないファイルではなく、 バイトコンパイル済みの古いファイルをロードしてしまいます。 そのような場合、ファイルをロードすると、 (compiled; note, source is newer)とメッセージを表示して、 再コンパイルするように忠告してきます。

Lispライブラリファイルにフォームを書くときには、 ファイルを複数回ロードする可能性があることを忘れないでください。 たとえば、ライブラリを再ロードするたびに 各変数を再初期化すべきかどうか考えましょう。 defvarは、初期化済みの変数の値を変更しません。 (see Defining Variables。)

連想リストに要素を追加するもっとも簡単な方法はつぎのとおりです。

(setq minor-mode-alist
      (cons '(leif-mode " Leif") minor-mode-alist))

しかし、これでは、ライブラリを再ロードすると、 複数の要素を追加してしまいます。 これを避けるにはつぎのようにします。

(or (assq 'leif-mode minor-mode-alist)
    (setq minor-mode-alist
          (cons '(leif-mode " Leif") minor-mode-alist)))

リストに要素を1回だけ追加するには、 add-to-list(see Setting Variables)も使えます。

ライブラリをすでにロードしたかどうか明示的に調べたいこともあるでしょう。 ライブラリ内で以前ロードされたかどうか検査する方法の1つは、 つぎのとおりです。

(defvar foo-was-loaded nil)

(unless foo-was-loaded
  execute-first-time-only
  (setq foo-was-loaded t))

ライブラリで名前付き機能を提供するためにprovideを使っていれば、 ファイルの始めのほうでfeaturepを使って、 provideを以前呼び出したかどうか検査できます。


Node:Named Features, Next:, Previous:Repeated Loading, Up:Loading

機能

providerequireは、 ファイルを自動的にロードするためのautoloadの代替手段です。 それらは指定した機能(features)という考え方で動作します。 自動ロードは特定の関数を呼び出すことで起動しますが、 機能はその名前でプログラムが最初に要求したときにロードします。

機能名は、関数や変数などの集合を表すシンボルです。 それらを定義するファイルでは、その機能を提供(provide)します。 それらを使う別のプログラムでは、 その機能を要求(require)することで、 それらが定義されることを確実にします。 こうすると、未ロードであれば定義しているファイルをロードします。

機能を要求するには、機能名を引数にしてrequireを呼び出します。 requireは、グローバル変数featuresを調べて、 目的の機能がすでに提供されているかどうか調べます。 提供されていなければ、適当なファイルから機能をロードします。 このファイルでは、トップレベルでprovideを呼び出して、 featuresに機能を追加するべきです。 そうしないと、requireはエラーを通知します。

たとえば、emacs/lisp/prolog.el には、 つぎのコードのようなrun-prologの定義が入っています。

(defun run-prolog ()
  "Run an inferior Prolog process, with I/O via buffer *prolog*."
  (interactive)
  (require 'comint)
  (switch-to-buffer (make-comint "prolog" prolog-program-name))
  (inferior-prolog-mode))

(require 'comint)は、ファイルcomint.elが未ロードであると、 そのファイルをロードします。 これにより、make-comintが定義済みであることを保証します。 普通、機能には、その機能を提供するファイル名からとった名前を付けますから、 requireにファイル名を指定する必要はありません。

comint.elファイルには、つぎのトップレベルの式が入っています。

(provide 'comint)

これにより、グローバル変数featuresのリストに comintが追加されるので、 これ以降に(require 'comint)を実行しても、 なにもしないでよいことになります。

ファイルのトップレベルでrequireを使うと、 そのファイルをロードする場合と同様に、 そのファイルをバイトコンパイルするとき(see Byte Compilation)にも requireには効果があります。 要求したパッケージに、 バイトコンパイラが知っている必要があるマクロが入っている場合です。

トップレベルのrequireの呼び出しは、 バイトコンパイル中に評価されますが、 provideの呼び出しは評価しません。 したがって、つぎの例のように、 同じ機能に対するprovideに続けてrequireを書くことで、 バイトコンパイルするまえに定義のファイルをロードすることを確実にできます。

(provide 'my-feature)  ; バイトコンパイラは無視し、
                       ;   loadは評価する
(require 'my-feature)  ; バイトコンパイラは評価する

コンパイラはprovideを無視し、 続くrequireの処理では当該ファイルをロードします。 ファイルのロード時にはprovideの呼び出しを実行するので、 そのあとのrequireの呼び出しは、 ファイルをロードするときにはなにもしません。

provide feature Function
この関数は、機能featureをロードし終えたこと、あるいは、 ロード中であることを現在のEmacsセッション内で宣言する。 つまり、featureに関連した機能が他のLispプログラムから利用できることを 意味する。

provideの呼び出しの直接の効果は、 featureがリストfeaturesに入っていなければ、 featureをリストfeaturesの先頭に入れることである。 引数featureはシンボルであること。 providefeatureを返す。

features
     => (bar bish)

(provide 'foo)
     => foo
features
     => (foo bar bish)

自動ロードによってファイルをロードしているとき、 その内容を評価することでエラーになってロードを中止すると、 ロード中に行われた関数定義やprovideの呼び出しはもとに戻す。 see Autoload

require feature &optional filename Function
この関数は((featurep feature)を使って) 現在のEmacsセッション内にfeatureが存在するかどうか調べる。 引数featureはシンボルであること。

機能が存在していなければ、requireは、 loadを使ってfilenameをロードする。 filenameを指定しないと、シンボルfeatureの名前を ロードすべきファイル名の基にする。 しかしながら、この場合には、requireは、 接尾辞を必ず付加してfeatureを探す。 featureだけの名前のファイルは探さない。

featureを提供するファイルのロードに失敗すると、 requireはエラー Required feature feature was not providedを通知する。

featurep feature Function
この関数は、現在のEmacsセッションでfeatureが提供されていれば (つまり、featurefeaturesのメンバであれば) tを返す。

features Variable
この変数の値は、 現在のEmacsセッションにロード済みの機能を表すシンボルのリストである。 各シンボルは、provideを呼び出すことでこのリストに追加される。 リストfeatures内の要素の順番は関係ない。


Node:Unloading, Next:, Previous:Named Features, Up:Loading

アンロード

ライブラリでロードした関数や変数を捨てさって 他のLispオブジェクト向けにメモリを回収することができます。 そうするには関数unload-featureを使います。

unload-feature feature &optional force コマンド
このコマンドは、featureを提供するライブラリをアンロードする。 つまり、当該ライブラリにおいて、defundefaliasdefsubstdefmacrodefconstdefvardefcustomで定義した関数、マクロ、変数すべてを未定義にする。 そうして、これらのシンボルに以前設定してあった自動ロードの設定を復元する。 (ロード時に、これらをシンボルの属性autoloadに保存している。)

以前の定義に復元するまえに、unload-featureremove-hookを 実行して、ライブラリ内の関数を特定のフックから取り除く。 これらのフックは、-hook-hooksで終る名前の変数、および、 loadhist-special-hooksに入っているものである。 これは、重要なフックにおいて存在しない関数を参照することで Emacsが動作不能になるのを防ぐ。

これらの処置でも誤動作防止には不十分であるときには、 ライブラリで明示的なアンロードフックを定義できる。 feature-unload-hookを定義してあると、 以前の定義を復元するまえに、 フックを削除する通常の動作のかわりに このフックをノーマルフックとして実行する。 アンロードフックでは、 ライブラリをいったんアンロードすると動作不能になるような ライブラリで変更したグローバルな状態をすべてアンドゥすべきである。

通常、unload-featureは、他のライブラリが依存している ライブラリのアンロードは拒否する。 (ライブラリabrequire(要求)していると、 ライブラリaはライブラリbに依存している。) 省略可能な引数forcenil以外であると、 依存関係を無視し、任意のライブラリをアンロードできる。

関数unload-featureはLispで書いてあり、 その動作はload-historyに基づきます。

load-history Variable
この変数の値は、ライブラリ名をそのライブラリが定義する関数や変数の名前、 そのライブラリが提供する機能、そのライブラリが要求する機能に対応付ける 連想リストである。

各要素はリストであり、1つ1つが1つのライブラリを記述する。 リストのCARは文字列であり、ライブラリ名である。 リストの残りは、以下の種類のオブジェクトから成る。

  • このライブラリで定義されたシンボル。
  • (require . feature)の形のリストであり、 要求する機能を示す。
  • (provide . feature)の形のリストであり、 提供する機能を示す。

load-historyの値には、CARnilであるような 1つの要素があってもよい。 この要素は、ファイルを訪問してないバッファ内でeval-bufferによって 作られた定義であることを示す。

コマンドeval-regionload-historyを更新しますが、 訪問先ファイルに対応する要素に、定義されるシンボルを追加するのであって、 要素を置き換えるのではありません。

あらかじめロード済みのライブラリは、load-historyに寄与しません。

loadhist-special-hooks Variable
この変数は、ライブラリ内で定義された関数を削除するために ライブラリをアンロードするまえに走査するフックのリストを保持する。


Node:Hooks for Loading, Previous:Unloading, Up:Loading

ロード時のフック

eval-after-loadを呼び出すと、 特定のライブラリをロードする/してあるときに実行するコードを指定できます。

eval-after-load library form Function
この関数は、ライブラリlibraryをロードする/してあるときに、 ライブラリlibraryのロードの最後にformを評価するように設定する。 libraryをすでにロードしてあると、 この関数はformをただちに評価する。

ライブラリ名libraryloadの引数に正確に一致する必要がある。 load-pathを探索してインストールするライブラリを探したときに 正しい結果を得るために、libraryにはディレクトリ名を含めないこと。

formでエラーが発生してもロード処理をもとに戻さないが、 formの残りは実行しない。

一般に、よく設計されたLispプログラムはこの機能を使うべきではありません。 Lispライブラリを見通しよくモジュール化して扱うには、 (1)ライブラリの(外部から使うことを意図した)変数を調べて設定し、 (2)ライブラリの関数を呼び出すことです。 (1)を行いたければ、すぐにしてかまいません。 ライブラリをロードするまで待つ必要はありません。 (2)を行うには、ライブラリをロードする必要があります (requireで行うことが好ましい)。

広く使われるプログラムに対する設計基準に合わなくても、 個人のカスタマイズでeval-after-loadを使うのはかまいません。

after-load-alist Variable
特定のライブラリをロードする/してあるときに評価する式の連想リスト。 各要素はつぎのとおり。
(filename forms...)

関数loadは、eval-after-loadを実現するために after-load-alistを調べる。


Node:Byte Compilation, Next:, Previous:Loading, Up:Top

バイトコンパイル

Emacs Lispには、Lispで書いた関数を より効率よく実行可能なバイトコード(byte-code)と呼ばれる 特別な表現に変換するコンパイラ(compiler)があります。 コンパイラはLispの関数定義をバイトコードで置き換えます。 バイトコード関数を呼び出すと、 バイトコードインタープリタ(byte-code interpreter)が その定義を評価します。

(真のコンパイル済みコードのように)計算機ハードウェアが直接実行するかわりに、 バイトコードインタープリタがバイトコンパイル済みのコードを評価するので、 バイトコードは、再コンパイルせずに計算機から計算機に移せます。 しかしながら、真のコンパイル済みコードほど速くはありません。

EmacsバイトコンパイラがLispファイルをコンパイルするときには、 --unibyteを指定してEmacsを起動したとしても、 ファイルで特に指定しなければ、 つねにファイルをマルチバイトテキストとして読みます。 コンパイルしても、コンパイルせずに同じファイルを実行した場合と同じ結果を 得るようにするためです。 See Loading Non-ASCII

一般に、Emacsの任意の版は、それよりまえの版でバイトコンパイルしたコードを 実行できますが、その逆は真ではありません。 Emacs 19.29では互換性のない大きな変更を行いましたから、 それ以降の版でコンパイルしたファイルは、 特別なオプションを指定しない限り、それ以前の版ではまったく動きません。 さらに、Emacs 19.29では、キーボード文字の修飾ビットを変更しました。 その結果、19.29よりまえの版でコンパイルしたファイルは、 修飾ビットを含む文字定数を使っているとそれ以降の版では動作しません。

バイトコンパイル中に生起するエラーについては、 See Compilation Errors


Node:Speed of Byte-Code, Next:, Up:Byte Compilation

バイトコンパイルコードの性能

バイトコンパイルした関数は、Cで書いた基本関数ほど効率よくはありませんが、 Lispで書いた版よりはよほど速く動きます。 例を示しましょう。

(defun silly-loop (n)
  "Return time before and after N iterations of a loop."
  (let ((t1 (current-time-string)))
    (while (> (setq n (1- n))
              0))
    (list t1 (current-time-string))))
=> silly-loop

(silly-loop 100000)
=> ("Fri Mar 18 17:25:57 1994"
    "Fri Mar 18 17:26:28 1994")  ; 31秒

(byte-compile 'silly-loop)
=> [コンパイルしたコードは省略]

(silly-loop 100000)
=> ("Fri Mar 18 17:26:52 1994"
    "Fri Mar 18 17:26:58 1994")  ; 6秒

この例では、解釈実行するコードでは実行に31秒必要でしたが、 バイトコンパイルしたコードでは6秒でした。 この結果は代表的なのもですが、実際の結果は大きく変動します。


Node:Compilation Functions, Next:, Previous:Speed of Byte-Code, Up:Byte Compilation

コンパイル関数

関数byte-compileで、 個々の関数定義やマクロ定義をバイトコンパイルできます。 byte-compile-fileで1つのファイル全体をコンパイルしたり、 byte-recompile-directorybatch-byte-compileで 複数個のファイルをコンパイルできます。

バイトコンパイラは、 各ファイルに対するエラーメッセージや警告メッセージを *Compile-Log*と呼ばれるバッファに出力します。 読者のプログラムに関してここに報告されたことがらは、 問題点を指摘しますが、必ずしもエラーとは限りません。

バイトコンパイルする可能性のあるファイルにマクロ呼び出しを書くときには 注意してください。 マクロ呼び出しはコンパイル時に展開されるので、 正しくコンパイルするためにはマクロは定義済みである必要があります。 詳しくは、See Compiling Macros

通常、ファイルをコンパイルしてもファイルの内容を評価したり、 ファイルをロードしません。 しかし、ファイルのトップレベルに書いたrequireは実行します。 コンパイル時に必要なマクロ定義が存在することを保証する1つの方法は、 それらを定義するファイルを要求(require)することです (see Named Features)。 コンパイルしたプログラムを実行するときに マクロ定義ファイルのロードを防ぐには、 requireの呼び出しの周りにeval-when-compileを書きます (see Eval During Compile)。

byte-compile symbol Function
この関数は、symbolの関数定義をバイトコンパイルし、 以前の定義をコンパイルしたもので置き換える。 symbolの関数定義は、関数の実際のコードであること。 つまり、コンパイラは、別のシンボルへの間接参照を辿らない。 byte-compileは、symbolのコンパイル済みの新たな定義を返す。

symbolの定義がバイトコード関数オブジェクトであると、 byte-compileはなにもせずにnilを返す。 Lispはどんなシンボルに対しても関数定義を1つだけ記録するので、 それがすでにコンパイル済みであると、 コンパイルまえのコードはどこにもないのである。 したがって、『同じ定義をコンパイルし直す』方法はない。

(defun factorial (integer)
  "Compute factorial of INTEGER."
  (if (= 1 integer) 1
    (* integer (factorial (1- integer)))))
=> factorial

(byte-compile 'factorial)
=>
#[(integer)
  "^H\301U\203^H^@\301\207\302^H\303^HS!\"\207"
  [integer 1 * factorial]
  4 "Compute factorial of INTEGER."]

結果は、バイトコード関数オブジェクトである。 この文字列には実際のバイトコードが入っている。 その各文字は、命令や命令のオペランドである。 ベクトルには、特別な命令に符号化される特定の基本関数を除いて、 関数が使うすべての定数、変数名、関数名が入っている。

compile-defun コマンド
このコマンドはポイントを含むdefunを読み取り、 それをコンパイルして、結果を評価する。 実際に関数定義であるdefunでこのコマンドを使うと、 その関数をコンパイルしたものをインストールすることになる。

byte-compile-file filename コマンド
この関数は、filenameという名前のLispコードのファイルを コンパイルしバイトコードのファイルにする。 出力ファイルの名前は、接頭辞.el.elcに換えて作る。 filename.elで終っていないときには、 filenameの末尾に.elcを付加する。

入力ファイルから一度に1つずつフォームを読みながらコンパイルを行う。 それが関数定義やマクロ定義であると、 コンパイルした関数定義やマクロ定義を書き出す。 他のフォームは一塊にして、各塊をコンパイルして書き出し、 ファイルを読むとコンパイルしたコードが実行されるようにする。 入力ファイルを読むときにすべてのコメントを捨てる。

このコマンドはtを返す。 対話的に呼び出すとファイル名を問い合わせる。

% ls -l push*
-rw-r--r--  1 lewis     791 Oct  5 20:31 push.el

(byte-compile-file "~/emacs/push.el")
     => t

% ls -l push*
-rw-r--r--  1 lewis     791 Oct  5 20:31 push.el
-rw-rw-rw-  1 lewis     638 Oct  8 20:25 push.elc

byte-recompile-directory directory flag コマンド
この関数は、directoryにある再コンパイルが必要な 個々の.elファイルを再コンパイルする。 ファイルを再コンパイルする必要があるのは、 .elcファイルが存在しても.elファイルより古い場合である。

.elファイルに対応する.elcファイルが存在しない場合には、 flagが動作を指示する。 それがnilであると、そのようなファイルは無視する。 nil以外であると、そのような各ファイルをコンパイルするかどうか ユーザーに問い合わせる。

このコマンドの戻り値は予測できない。

batch-byte-compile Function
この関数は、コマンド行に指定したファイル群に対して byte-compile-fileを実行する。 この関数はEmacsをバッチモードで実行しているときにだけ使うこと。 完了するとEmacsを終了するからである。 1つのファイルでエラーが発生しても、後続のファイルの処理には影響しないが、 エラーを起こしたファイルに対する出力ファイルは生成せず、 Emacsのプロセスは0以外の状態コードで終了する。
% emacs -batch -f batch-byte-compile *.el

byte-code code-string data-vector max-stack Function
この関数はバイトコードを実際に解釈実行する。 バイトコンパイルした関数は、実際には、 byte-codeを呼び出すような本体として定義される。 この関数を読者自身で呼び出さないこと。 この関数の正しい呼び出しを生成する方法はバイトコンパイラだけが知っている。

Emacs 18版では、バイトコードは関数byte-codeをつねに呼び出すことで 実行していた。 現在では、バイトコード関数オブジェクトの一部としてバイトコードを実行するのが 普通であり、byte-codeを明示的に呼び出すことは稀である。


Node:Docs and Compilation, Next:, Previous:Compilation Functions, Up:Byte Compilation

説明文字列とコンパイル

バイトコンパイルしたファイルからロードした関数や変数では、 それらの説明文字列は、必要に応じてそのファイルを動的に参照します。 これはEmacs内のメモリを節約しロード処理も速くなります。 というのは、ファイルのロード処理で説明文字列を処理する必要がないからです。 説明文字列を実際に参照するのは遅くなりますが、 普通、ユーザーをいらいらさせるほとではありません。

説明文字列を動的に参照することには欠点があります。

読者のサイトでEmacsを通常の手順でインストールした場合には、 これらの問題は普通起こらないはずです。 新版のインストールには別のディレクトリを使いますから、 旧版をインストールしてある限り、そのファイル群は意図した場所に 無変更で残っているはずです。

しかしながら、読者自身がEmacsを構築して、 構築したディレクトリからEmacsを使う場合、 Lispファイルを編集して再コンパイルすると、 しばしばこの問題を経験するでしょう。 そのような場合には、再コンパイルしたあとでファイルを再ロードすれば 問題を解決できます。

旧版ではこの機能を使えないので、 Emacsの(19.29以降の)最近の版でバイトコンパイルしたファイルは 旧版ではロードできません。 byte-compile-dynamic-docstringsnilを設定すれば、 コンパイル時にこの機能をオフにできます。 Emacsの旧版にロードできるようにファイルをコンパイルできるのです。 すべてのファイルをこのようにコンパイルしたり、あるいは、 この変数をファイルにローカルな束縛に指定して1つのソースファイルだけを このようにコンパイルしたりもできます。 そのようにする1つの方法は、つぎの文字列をファイルの先頭行に追加することです。

-*-byte-compile-dynamic-docstrings: nil;-*-

byte-compile-dynamic-docstrings Variable
これがnil以外であると、 バイトコンパイラは、説明文字列を動的にロードするように設定した コンパイル済みファイルを生成する。

説明文字列を動的に扱う場合、 コンパイル済みのファイルではLispリーダの特別な構文#@countを 使います。 この構文は後続のcount文字を読み飛ばします。 また、#$という構文も使います。 これは、『文字列としてのこのファイルの名前』を表します。 Lispのソースファイルでは、これらの構文を使わないのが最良です。 これらは人が読むファイル向けに設計したものではないからです。


Node:Dynamic Loading, Next:, Previous:Docs and Compilation, Up:Byte Compilation

個別関数の動的ロード

ファイルをコンパイルするとき、 動的関数ロード(dynamic function loading、 遅延ロード(lazy loading)ともいう)機能を指定できます。 動的関数ロードでは、ロードするときにファイル内の関数定義をすべて 読むわけではありません。 そのかわりに、各関数定義には、 そのファイルを指す埋め草が入っています。 それぞれの関数を初めて呼び出したときに、 その完全な定義をファイルから読み取り、埋め草を置き換えます。

動的関数ロードの利点は、ファイルをロードするよりかなり速いことです。 ユーザーが呼び出せる数多くの別々の関数を収めたファイルにおいては、 それらの1つだけを使って残りのものを使わないのであれば、 これは有利なことです。 キーボードコマンドを提供する特別なモードには、 しばしばこのような使い方のパターンがあります。 ユーザーがモードを起動しても、提供するコマンドの一部しか使わないのです。

動的関数ロードの機能には、ある種の欠点もあります。

Emacsのファイル群をインストールした普通の状況では、 このような問題は起きないはずです。 しかし、Lispファイルを読者が変更すると起こりえます。 これらの問題を回避するもっとも簡単な方法は、 再コンパイルするたびに新たにコンパイルしたファイルを ただちに再ロードすることです。

バイトコンパイラは、コンパイル時に変数byte-compile-dynamicnil以外であれば、動的関数ロードの機能を使います。 動的ロードは特定のファイルで必要なだけですから、 この変数をグローバルに設定しないでください。 そのかわりにファイルにローカルな変数束縛を使って 特定のソースファイルだけでこの機能をオンにします。 たとえば、ソースファイルの先頭行につぎのテキストを書けば、 そのようにできます。

-*-byte-compile-dynamic: t;-*-

byte-compile-dynamic Variable
これがnil以外であると、 バイトコンパイラは、動的関数ロードを使うように設定した コンパイル済みのファイルを生成する。

fetch-bytecode function Function
functionを完全にロードしていないと、 バイトコンパイルしたファイルからただちにfunctionの定義をロードする。 引数functionは、バイトコード関数オブジェクトか関数名である。


Node:Eval During Compile, Next:, Previous:Dynamic Loading, Up:Byte Compilation

コンパイル時の評価

プログラムのコンパイル時に評価されるようなコードを書くための機能です。

eval-and-compile body Special Form
このフォームは、コンパイルしたり実行したり (コンパイルしてあってもしてなくても)するときに bodyを評価するように印を付ける。

bodyを別のファイルに収め、そのファイルをrequireで参照しても 同じ結果を得ることができる。 bodyが大きい場合には、そのほうが好ましい。

eval-when-compile body Special Form
このフォームは、コンパイルしたプログラムをロードするときではなく、 プログラムのコンパイル時にbodyを評価するように印を付ける。 コンパイラが評価した結果は、コンパイルしたプログラム内に定数として現れる。 ソースファイルをコンパイルせずにロードすると、 bodyを普通どおり評価する。

Common Lispに関した注意: トップレベルでは、 Common Lispの(eval-when (compile eval) ...)の常套句に似ている。 それ以外の箇所では、Common Lispの#.リーダマクロは (解釈実行時ではなければ)eval-when-compileが行うことに近い。


Node:Byte-Code Objects, Next:, Previous:Eval During Compile, Up:Byte Compilation

バイトコード関数オブジェクト

バイトコンパイルした関数は、特別なデータ型、 バイトコード関数オブジェクト(byte-code function objects)です。

内部的には、バイトコード関数オブジェクトはベクトルによく似ています。 しかし、評価時にこのデータ型が呼び出すべき関数として現れると、 特別に扱います。 バイトコード関数オブジェクトの表示表現はベクトルに似ていますが、 開き角括弧[のまえに余分に#が付きます。

バイトコード関数オブジェクトには、少なくとも4つの要素が必要です。 最大個数に制限はありませんが、最初の6つ個の要素にだけ 普通の用途があります。 つぎのとおりです。

引数リスト
引数シンボルのリスト。
バイトコード
バイトコード命令を収めた文字列。
定数群
バイトコードが参照するLispオブジェクトのベクトル。 関数名や変数名として使われるシンボルを含む。
スタックサイズ
この関数に必要なスタックサイズの最大値。
説明文字列
(あれば)説明文字列。 さもなければnil。 説明文字列がファイルに収めてあれば、値は数かリストである。 実際の説明文字列を取得するには関数documentationを使う (see Accessing Documentation)。
対話指定
(あれば)対話指定。 これは文字列かLisp式。 対話的でない関数ではnil

バイトコード関数オブジェクトの例を表示表現でつぎに示します。

#[(&optional arg)
  "^H\204^F^@\301^P\302^H[!\207"
  [arg 1 forward-sexp]
  2
  254435
  "p"]

バイトコードオブジェクトを作る基本的な方法は、 make-byte-codeを使うことです。

make-byte-code &rest elements Function
この関数は、elementsを要素とする バイトコード関数オブジェクトを作成し返す。

バイトコード関数の要素を自分で作ったりしないでください。 それらに整合性がないと、 その関数を呼び出すとEmacsがクラッシュすることもあります。 これらのオブジェクトの作成は、バイトコンパイラに任せるべきです。 バイトコンパイラは整合した要素を作成します(と期待する)。

バイトコードオブジェクトの要素はarefで参照できます。 同じ要素群のベクトルをvconcatで作ることもできます。


Node:Disassembly, Previous:Byte-Code Objects, Up:Byte Compilation

バイトコードの逆アセンブル

人間はバイトコードを書きません。 それはバイトコンパイラの仕事です。 しかし、好奇心を満たすために逆アセンブラを用意してあります。 逆アセンブラはバイトコンパイルしたコードを人が読める形式に変換します。

バイトコードインタープリタは、単純なスタックマシンとして実装してあります。 値を自前のスタックに積み、計算に使うためにスタックから取り出し、 計算結果そのものはスタックにまた積みます。 バイトコード関数から戻るときには、スタックから値を取り出して 関数値としてその値を返します。

スタックに加えて、変数とスタックのあいだで値を転送することで、 バイトコード関数は、普通のLisp変数を使ったり、 束縛したり、値を設定できます。

disassemble object &optional stream コマンド
この関数はobjectの逆アセンブルしたコードを出力する。 streamを指定すると、そこへ出力する。 さもなければ、逆アセンブルしたコードはストリームstandard-outputへ 出力する。 引数objectは関数名かラムダ式である。

特別な例外として、この関数を対話的に使うと、 *Disassemble*という名前のバッファへ出力する。

disassemble関数の使用例を2つ示します。 バイトコードとLispソースとの対応を取れるように 特別なコメントを追加してありますが、 これらはdisassembleの出力には現れません。 これらの例は、最適化してないバイトコードです。 現在、バイトコードは、普通、最適化しますが、 目的は果たせるので、例を書き換えてありません。

(defun factorial (integer)
  "Compute factorial of an integer."
  (if (= 1 integer) 1
    (* integer (factorial (1- integer)))))
     => factorial

(factorial 4)
     => 24

(disassemble 'factorial)
     -| byte-code for factorial:
 doc: Compute factorial of an integer.
 args: (integer)

0   constant 1              ; スタックに1を積む

1   varref   integer        ; 環境からintegerの値を取得し、
                            ; スタックに積む

2   eqlsign                 ; スタックの先頭から2つの値を
                            ; 取りさって比較し、
                            ; 結果をスタックに積む

3   goto-if-nil 10          ; スタックの先頭から値を取りさり
                            ; 検査する。nilならば10へ飛び、
                            ; さもなければつぎへ進む

6   constant 1              ; スタックに1を積む

7   goto     17             ; 17へ飛ぶ(この場合、関数は1を返す)

10  constant *              ; スタックにシンボル*を積む

11  varref   integer        ; スタックにintegerの値を積む

12  constant factorial      ; スタックにfactorialを積む

13  varref   integer        ; スタックにintegerの値を積む

14  sub1                    ; スタックからintegerを取りさり、
                            ; 減した新たな値をスタックに積む

                            ; スタックの現在の内容はつぎのとおり
                            ; - integerを減らした値
                            ; - factorial
                            ; - integerの値
                            ; - *

15  call     1              ; スタックの最初(先頭)要素を使って
                            ; 関数factorialを呼び出す
                            ; 戻り値をスタックに積む

                            ; スタックの現在の内容はつぎのとおり
                            ; - factorialの
                            ;      再帰呼び出しの結果
                            ; - integerの値
                            ; - *

16  call     2              ; スタックの最初の要素の2つ
                            ; (先頭の2つ)を引数として
                            ; 関数*を呼び出し
                            ; 結果をスタックに積む

17  return                  ; スタックの先頭要素を返す
     => nil

関数silly-loopは、少々複雑です。

(defun silly-loop (n)
  "Return time before and after N iterations of a loop."
  (let ((t1 (current-time-string)))
    (while (> (setq n (1- n))
              0))
    (list t1 (current-time-string))))
     => silly-loop

(disassemble 'silly-loop)
     -| byte-code for silly-loop:
 doc: Return time before and after N iterations of a loop.
 args: (n)

0   constant current-time-string  ; current-time-stringを
                                  ; スタックの先頭に積む

1   call     0              ; 引数なしでcurrent-time-stringを
                            ; 呼び出し、結果をスタックに積む

2   varbind  t1             ; スタックから値を取りさり、
                            ; t1に束縛する

3   varref   n              ; 環境からnの値を取得し、
                            ; 値をスタックに積む

4   sub1                    ; スタックの先頭から1を引く

5   dup                     ; スタックの先頭の値を複製する
                            ; つまり、スタックの先頭の値を
                            ; コピーして、それをスタックに積む

6   varset   n              ; スタックの先頭から値を取りさり、
                            ; 値をnに束縛する

                            ; つまり、dup varsetは
                            ; スタックの先頭の値を取りさらずに
                            ; nにコピーする

7   constant 0              ; スタックに0を積む

8   gtr                     ; スタックから2つの値を取りさり、
                            ; nが0より大きいか調べ、
                            ; 結果をスタックに積む

9   goto-if-nil-else-pop 17 ; n <= 0ならば17へ飛ぶ
                            ; (whileループから抜ける)
                            ; さもなければ、スタックの先頭から
                            ; 値を取りさり、つぎへ進む

12  constant nil            ; スタックにnilを積む
                            ; (これはループの本体)

13  discard                 ; ループの本体の結果を捨てる
                            ; (whileループは副作用のために
                            ; つねに評価される)

14  goto     3              ; whileループの先頭へ飛ぶ

17  discard                 ; スタックの先頭の値を取りさって、
                            ; whileループの結果を捨てる。
                            ; これは、9での飛び越しのために
                            ; 取りさっていない値nil

18  varref   t1             ; t1の値をスタックに積む

19  constant current-time-string  ; current-time-stringを
                                  ; スタックに積む

20  call     0              ; ふたたびcurrent-time-stringを
                            ; 呼び出す

21  list2                   ; スタックの先頭から2つの値を取りさり
                            ; それらのリストを作り、
                            ; リストをスタックに積む

22  unbind   1              ; ローカルの環境のt1の束縛を解く

23  return                  ; スタックの先頭の値を返す

     => nil


Node:Advising Functions, Next:, Previous:Byte Compilation, Up:Top

Emacs Lisp関数のアドバイス

アドバイス(advice)機能により、関数の既存の定義に追加できます。 これは、Emacsの他の部分で定義された関数を ライブラリにおいてカスタマイズする見通しのよい方法です。 関数全体を再定義するよりも見通しがよいのです。

各関数は、個別に定義した複数のアドバイス断片を持てます。 それぞれのアドバイス断片は、明示的に有効にしたり無効にできます。 任意の関数の有効にしたアドバイス断片が実際にその効果を発揮するのは、 当該関数のアドバイスを活性にしたときか 当該関数をのちに定義したり再定義したときです。

使用上の注意: アドバイスは、既存関数の既存の呼び出しのふるまいを変更するのに有用である。 新たな呼び出しやキーバインドの新たなふるまいが必要な場合には、 既存関数を使う新たな関数(や新たなコマンド)を定義するほうが 見通しがよい。


Node:Simple Advice, Next:, Up:Advising Functions

単純なアドバイスの例

コマンドnext-lineは、ポイントを垂直に複数行移動します。 標準バインドはC-nです。 バッファの最終行で使うと、 (next-line-add-newlinesnil以外の場合) このコマンドは行を作るために改行を挿入し、その行に移動します。

同様な機能をprevious-lineに追加したいとします。 つまり、バッファの先頭に新たな行を挿入し、その行へ移動するのです。 どのようにすればよいでしょう?

当該関数を再定義すればできますが、それではモジュール性がよくありません。 アドバイス機能が見通しのよい代替方法を提供します。 既存の関数定義を実際に変更したりその定義を参照することなく、 関数定義に読者のコードを実質的に追加できます。 つぎのように行います。

(defadvice previous-line (before next-line-at-end (arg))
  "Insert an empty line when moving up from the top line."
  (if (and next-line-add-newlines (= arg 1)
           (save-excursion (beginning-of-line) (bobp)))
      (progn
        (beginning-of-line)
        (newline))))

この式は、関数previous-lineに対するアドバイス断片を定義します。 このアドバイス断片にはnext-line-at-endという名前が付きます。 シンボルbeforeにより、 previous-lineの通常の定義を実行するまえに実行する 事前アドバイス(before-advice)であることを意味します。 (arg)は、アドバイス断片がどのように関数の引数を参照するかを指定します。

このアドバイス断片が実行されると、必要な場面では新たに行を作りますが、 その行へはポイントを移動しません。 これはアドバイスを書く正しいやりかたです。 というのは、通常の定義がこのあとに実行され、新たに挿入した行へ移動します。

アドバイスを定義しても関数previous-lineをただちには変更しません。 つぎのようにアドバイスを活性にすると変わります。

(ad-activate 'previous-line)

これにより、関数previous-lineに対して定義してある アドバイスを使い始めます。 これ以降、C-pM-xでユーザーが起動したのか Lispから呼ばれたのかに関わらず、 この関数を起動すると、まずアドバイスを実行してから 関数の通常の定義を実行します。

この例は、アドバイスの1つのクラスである事前アドバイスの例であり、 関数の元定義のまえに実行されます。 他に2つのアドバイスクラスがあります。 元定義のあとに実行される事後アドバイス(after-advice)と 元定義の起動を包み込む式を指定する包囲アドバイス(around-advice)です。


Node:Defining Advice, Next:, Previous:Simple Advice, Up:Advising Functions

アドバイス定義

アドバイス断片を定義するには、マクロdefadviceを使います。 defadviceの呼び出しはつぎのような構文です。 defundefmacroの構文を基にしていますが、 追加部分があります。

(defadvice function (class name
                         [position] [arglist]
                         flags...)
  [documentation-string]
  [interactive-form]
  body-forms...)

ここで、functionはアドバイス対象となる関数 (やマクロやスペシャルフォーム)です。 以後、アドバイスする対象を単に『関数』と書きますが、 これにはつねにマクロやスペシャルフォームを含みます。

classはアドバイスのクラスを指定し、 beforeafteraroundのいずれかです。 事前アドバイス(before)は関数そのもののまえに実行されます。 事後アドバイス(after)は関数そのもののあとに実行されます。 包囲アドバイス(around)は関数自身の実行を包み込みます。 事後アドバイスと包囲アドバイスでは、 ad-return-valueに設定することで戻り値を変更できます。

ad-return-value Variable
アドバイスを実行しているとき、 関数の元定義の実行を完了したあとでは、この変数はその戻り値を保持する。 すべてのアドバイスを完了すると、最終的には、この値を呼び出し側へ返す。 事後アドバイスと包囲アドバイスでは、この変数に別の値を設定することで 戻り値を変更できる。

引数nameはアドバイスの名前であり、nil以外のシンボルです。 アドバイス名は、functionの特定クラスのすべてのアドバイス断片から 1つのアドバイス断片を一意に識別します。 名前でアドバイス断片を参照でき、 それを再定義したり有効にしたり無効にできます。

通常の関数定義の引数リストのかわりに、 アドバイス定義では異なる情報を必要とします。

省略可能なpositionは、指定したclassの 現在のアドバイスリストのどこに新たなアドバイスを置くかを指定します。 firstlast、あるいは、 0から数え始める位置を指定する数である必要があります (firstは0と等価)。 位置を指定しないとデフォルトはfirstです。 当該クラスの既存位置の範囲を超えている場合には、 先頭か末尾のどちらか近いほうになります。 既存のアドバイス断片を再定義する場合には、値positionは無視されます。

省略可能なarglistは、 アドバイスが使う引数リストを定義するために使います。 これは、アドバイスを実行するために生成される結合定義 (see Combined Definition)の引数リストになります。 その結果、アドバイスの式では、 引数の値を参照するためにこのリストの引数変数を使えます。

この引数リストは、関数の実際の呼び出し方を扱えるように、 もとの関数の引数リストと互換性がある必要があります。 2つ以上のアドバイス断片で引数リストを指定している場合、 すべてのアドバイスクラスの中で最初のもの(位置が最小のもの)を使います。

残りの要素flagsは、このアドバイス断片の使い方に関する情報を指定する シンボルです。 正しいシンボルとそれらの意味はつぎのとおりです。

activate
functionに対するアドバイスをただちに活性にする。 関数のアドバイスに対する変更は、当該関数のアドバイスを活性にすると 効果を持つようになる。 このフラグは、functionに対するこのアドバイス断片を定義した直後に そのようにすることを指示する。

functionが未定義(未定義のアドバイス(forward advice)と呼ぶ状況) であるとこのフラグにはなんの効果もない。 というのは、未定義関数のアドバイスは活性にできないからである。 しかし、functionを定義するとそのアドバイスは自動的に活性にされる。

protect
このアドバイス断片をそれよりまえに実行されるコードやアドバイスによる 非ローカル脱出やエラーに対して保護する。 保護したアドバイス断片は、 フォームunwind-protectの中に後始末として置かれ、 それよりまえに実行されるコードでエラーが発生したりthrowを使っても 実行される。 see Cleanups
compile
アドバイスの実行に使われる結合定義をコンパイルする。 activateとともに指定しないと、このフラグは無視する。 see Combined Definition
disable
このアドバイス断片を当初は無効にしておき、 のちに明示的に有効にしない限り使われない。 see Enabling Advice
preactivate
このdefadviceをコンパイルしたりマクロ展開したときに、 functionに対するアドバイスを活性にする。 これにより現在のアドバイスの状態に応じたアドバイス定義をコンパイルし、 必要に応じて使われるようになる。

このdefadviceをバイトコンパイルする場合にのみ意味を持つ。

省略可能なdocumentation-stringは、 このアドバイス断片の説明文字列になります。 functionに対するアドバイスが活性であると、 (documentationが返す)functionの説明文は、 関数の元定義の説明文字列とfunctionのアドバイスすべての説明文字列の 合成になります。

省略可能なinteractive-formは、 元関数の対話的ふるまいを変更するために指定します。 2つ以上のアドバイス断片でinteractive-formを指定している場合、 すべてのアドバイスの中で最初のもの(位置が最小のもの)が優先します。

空リストでもかまわないbody-formsは、アドバイスの本体です。 アドバイスの本体では、引数、戻り値、束縛環境を参照/変更したり、 いかなる種類の副作用を起こせます。

警告: マクロをアドバイスする場合、 マクロはプログラムのコンパイル時に展開されるのであって、 コンパイルしたプログラムの実行時に展開されるのではないことに注意。 アドバイスが使用するすべてのサブルーティンは、 バイトコンパイラがマクロを展開するときに必要になる。


Node:Around-Advice, Next:, Previous:Defining Advice, Up:Advising Functions

包囲アドバイス

包囲アドバイスにより、関数の元定義を包み込むLisp式を書けます。 関数の元定義を実行する場所を特別なシンボルad-do-itで指定します。 包囲アドバイスの本体に現れたこのシンボルは、 元定義(と内側の包囲アドバイス本体)のフォームを含んだprognで 置き換えられます。 例を示しましょう。

(defadvice foo (around foo-around)
  "Ignore case in `foo'."
  (let ((case-fold-search t))
    ad-do-it))

これは、fooの元定義を実行するときに 大文字小文字を区別しないで探索することを保証します。

ad-do-it Variable
これは実際には変数ではないが、包囲アドバイス内では変数のように用いる。 関数の元定義と『より内側の』包囲アドバイスを実行する場所を指定する。

包囲アドバイスでad-do-itを用いなければ、関数の元定義を実行しません。 これは、元定義を完全に無効にする手段です。 (さらに、内側の包囲アドバイス断片も無効にする。)


Node:Computed Advice, Next:, Previous:Around-Advice, Up:Advising Functions

計算アドバイス

マクロdefadvicedefunに似ていて、 アドバイスのコードやアドバイスに関する他のすべての情報を ソースコードで明示します。 関数ad-add-adviceを用いると、 その詳細を計算で求めたアドバイスを作成できます。

ad-add-advice function advice class position Function
ad-add-adviceを呼び出すと、 関数functionに対するクラスclassのアドバイス断片として adviceを追加する。 引数adviceはつぎの形式である。
(name protected enabled definition)

ここで、protectedenabledはフラグであり、 definitionはアドバイスの動作を指定する式である。 enablednilであると、 このアドバイス断片は当初は無効になる (see Enabling Advice)。

functionに指定したクラスclassのアドバイス断片がすでにあると、 positionは新しいアドバイス断片をリストのどこに置くかを指定する。 positionの値は、firstlast、あるいは、 (リストの先頭を0から数えた)数である。 範囲外の数は先頭か末尾のどちらか近いほうになる。

functionに同じ名前のアドバイス断片adviceがすでにあると、 引数positionは無視され、古いアドバイス断片を新しいもので置き換える。


Node:Activation of Advice, Next:, Previous:Computed Advice, Up:Advising Functions

アドバイスの活性化

デフォルトでは、アドバイスを定義してもその効果は発揮されません。 アドバイスした関数のアドバイスを活性にして始めて効果を発揮します。 defadviceでフラグactivateを指定すれば、 関数にアドバイスを定義したときに活性にできます。 しかし、普通は、関数ad-activateや以下の活性化コマンドを 呼び出すことで、関数のアドバイスを活性にします。

アドバイスの定義操作と活性化操作を区別することで、 アドバイスを追加するたびに関数を再定義することなる、 関数に複数のアドバイス断片を効率よく追加できます。 さらに重要なことは、関数を実際に定義するまえでも 関数にアドバイスを定義できることです。

関数のアドバイスを初めて活性にすると、 関数の元定義を保存してから、関数に対する有効なアドバイス断片すべてを 元定義と結合して新たな定義を作り出します。 (現在無効にしてあるアドバイス断片は使用しない。 see Enabling Advice。) この定義をインストールし、 以下に述べる条件に応じてバイトコンパイルする場合もあります。

アドバイスを活性にするコマンドすべてにおいて、 compiletであると、 アドバイスを実装する結合定義をコンパイルします。

ad-activate function &optional compile コマンド
このコマンドはfunctionに対するアドバイスを活性にする。

関数のアドバイスがすでに活性になっているアドバイスを 活性にしても意味があります。 当該関数のアドバイスを活性にしたあとでアドバイスを変更した場合、 その変更が効果を持つようにする操作になります。

ad-deactivate function コマンド
このコマンドはfunctionのアドバイスを不活性にする。

ad-activate-all &optional compile コマンド
このコマンドはすべての関数に対するアドバイスを活性にする。

ad-deactivate-all コマンド
このコマンドはすべての関数に対するアドバイスを不活性にする。

ad-activate-regexp regexp &optional compile コマンド
このコマンドはregexpに一致する名前のすべてのアドバイス断片を活性にする。 より正確には、regexpに一致する名前のアドバイス断片を持つ任意の 関数のすべてのアドバイスを活性にする。

ad-deactivate-regexp regexp コマンド
このコマンドはregexpに一致する名前の すべてのアドバイス断片を不活性にする。 より正確には、regexpに一致する名前のアドバイス断片を持つ任意の 関数のすべてのアドバイスを不活性にする。

ad-update-regexp regexp &optional compile コマンド
このコマンドはregexpに一致する名前のアドバイス断片を活性にするが、 すでにアドバイスが活性になっている関数に対するものだけである。

関数に対するアドバイスの再活性化は、 アドバイスを活性にしたあとに行った当該アドバイスの変更すべて (有効にしたり無効にしたアドバイス断片を含む。 see Enabling Advice)が効果を持つようにするのに便利である。

ad-start-advice コマンド
関数を定義したり再定義したときにアドバイスを自動的に活性にする。 このモードをオンにすると、アドバイスを定義するとただちに効果を持つようになる。

ad-stop-advice コマンド
関数を定義したり再定義してもアドバイスを自動的には活性にしない。

ad-default-compilation-action User Option
この変数は、関数に対するアドバイスを活性にした結果作られる 結合定義をコンパイルするかどうか制御する。

『予約活性』(see Preactivation)中にアドバイス定義を作成すると その定義はすでにコンパイルされているはずです。 というのは、preactivateフラグを指定したdefadviceを 含むファイルをバイトコンパイル中にそれが定義されたはずだからです。


Node:Enabling Advice, Next:, Previous:Activation of Advice, Up:Advising Functions

アドバイスの有効化と無効化

各アドバイス断片には、 それを有効にするか無効にするかを指定するフラグがあります。 アドバイス断片を有効にしたり無効にすることで、 アドバイス断片を未定義にしたり再定義することなくオン/オフできます。 たとえば、関数fooに対するアドバイス断片my-adviceを 無効にするには、つぎのようにします。

(ad-disable-advice 'foo 'before 'my-advice)

この関数自身は、アドバイス断片の有効化フラグを変更するだけです。 アドバイスした関数でこの変更の効果を発揮するには、 fooのアドバイスを再度活性にする必要があります。

(ad-activate 'foo)

ad-disable-advice function class name コマンド
このコマンドはfunctionに対するクラスclass内の nameで指名したアドバイス断片を無効にする。

ad-enable-advice function class name コマンド
このコマンドはfunctionに対するクラスclass内の nameで指名したアドバイス断片を有効にする。

正規表現を用いて、さまざまな関数に対する 多数のアドバイス断片を一度に無効にすることもできます。 この場合も、当該関数のアドバイスを再度活性にすることで、 その効果が発揮されます。

ad-disable-regexp regexp コマンド
このコマンドは、すべての関数のすべてのクラスの regexpに一致するアドバイス断片すべてを無効にする。

ad-enable-regexp regexp コマンド
このコマンドは、すべての関数のすべてのクラスの regexpに一致するアドバイス断片すべてを有効にする。


Node:Preactivation, Next:, Previous:Enabling Advice, Up:Advising Functions

予約活性

アドバイスを実行するための結合定義を作成することは、 ある程度手間がかかります。 ライブラリで多数の関数をアドバイスしていると、 ライブラリのロードが遅くなります。 そのような場合、あらかじめ適切な結合定義を作成する 予約活性(preactivation)を使えます。

予約活性を使うには、defadviceでアドバイスを定義するときに フラグpreactivateを指定します。 このようなdefadviceの呼び出しでは、 (有効か無効に関わらず)このアドバイス断片と 当該関数に対して現在有効になっている他のアドバイスを元定義 に結合した定義を作成します。 defadviceをコンパイルすると、その結合定義もコンパイルします。

のちに関数のアドバイスを活性にしたとき、 関数に対する有効にしたアドバイスがこの結合定義の作成に 使用したものに一致すると既存の結合定義を使います。 そのため、新たに結合定義を作成する必要がなくなります。 したがって、予約活性はけっしてまちがった結果を生じませんが、 予約活性に用いたアドバイスと活性にした有効なアドバイスが一致しないと 利点はなくなります。

不一致のために予約活性が正しく動作していない兆候の例を示します。

関数自体が定義されるまえであってもコンパイル済みの予約活性したアドバイスは 正しく動作します。 しかし、予約活性したアドバイスをコンパイルするときには 関数は定義済みである必要があります。

予約活性したアドバイスが使われない理由を調べるよい方法はありません。 できることは、 関数のアドバイスを活性にするまえに、 (関数trace-function-backgroundで) 関数ad-cache-id-verification-codeをトレースすることです。 活性にしたあと、当該関数に対してad-cache-id-verification-codeが 返した値を調べます。 verifiedならば予約活性したアドバイスが使われています。 これ以外の値は、アドバイスが不適切と判断された理由に関する情報を 与えます。

警告: 予約活性が失敗する場合が1つ知られている。 現在のアドバイスの状態に一致しなくても、 あらかじめ作成した結合定義を使ってしまう。 これは、同一関数に対する同じクラスの同一名称であるが異なるアドバイス断片を 2つのパッケージで定義している場合に発生する。 このようなことは避けること。


Node:Argument Access in Advice, Next:, Previous:Preactivation, Up:Advising Functions

アドバイスからの引数の参照

アドバイス断片の本体からアドバイスする関数の引数を参照する もっとも簡単な方法は、関数定義で用いているものと同じ名前を使うことです。 これには、元関数の引数の変数名を知る必要があります。

多くの場合、この単純な方法で十分ですが、欠点もあります。 アドバイス内に引数名を直接書き込むために、堅牢ではありません。 関数の元定義が変更されると、アドバイスは動作しません。

他の方法は、アドバイスそのものに引数リストを指定することです。 これは関数の元定義の引数名を知る必要はありませんが、制約もあります。 関数に対するすべてのアドバイスで同一の引数リストを使う必要があります。 なぜなら、すべてのアドバイスに実際に使われる引数リストは、 当該関数のアドバイス断片の最初のものだからです。

より堅牢な方法は、活性にするときに、 つまり、アドバイスを結合した定義を作成するときに 適切なフォームに展開されるマクロを使うことです。 参照用マクロは、関数の引数変数への実引数の分配方法に依存しない 実引数の位置で参照します。 Emacs Lispにおいては、引数の意味は引数リスト内での位置で決まるため、 これは堅牢です。

ad-get-arg position Macro
位置positionにある実引数を返す。

ad-get-args position Macro
位置positionから始まる実引数のリストを返す。

ad-set-arg position value Macro
位置positionにある実引数の値を設定する。

ad-set-args position value-list Macro
位置positionから始まる実引数のリストにvalue-listを設定する。

例を示します。 関数fooの定義はつぎのとおりであり、

(defun foo (x y &optional z &rest r) ...)

つぎのように呼ばれるとします。

(foo 0 1 2 3 4 5 6)

そうすると、fooの本体では、 xは0、yは1、zは2、r(3 4 5 6)です。 このとき、ad-get-argad-get-argsは、つぎの値を返します。

(ad-get-arg 0) => 0
(ad-get-arg 1) => 1
(ad-get-arg 2) => 2
(ad-get-arg 3) => 3
(ad-get-args 2) => (2 3 4 5 6)
(ad-get-args 4) => (4 5 6)

この例では、引数に値を設定できます。

(ad-set-arg 5 "five")

の効果は、6番目の引数を"five"に変更します。 fooの本体を実行するまえにこのアドバイスが実行されると、 本体内ではr(3 4 "five" 6)になります。

つぎは引数リストを変更する例です。

(ad-set-args 0 '(5 4 3 2 1 0))

fooの本体を実行するまえにこのアドバイスが実行されると、 fooの本体内では、 xは5、yは4、zは3、r(2 1 0)になります。

これらの引数参照は、実際にはLispマクロとしての実装ではありません。 アドバイス機構で特別に実装してあります。


Node:Subr Arguments, Next:, Previous:Argument Access in Advice, Up:Advising Functions

subr引数リストの定義

アドバイス機能が結合定義を作成するとき、 元関数の引数リストを知る必要があります。 基本関数に対しては、これはつねに可能とは限りません。 アドバイスが引数リストを決定できないときには、 (&rest ad-subr-args)を使います。 これはつねに動作しますが、 引数値のリストを作成するために効率的ではありません。 ad-define-subr-argsを使って、 基本関数に対する適当な引数名を宣言できます。

ad-define-subr-args function arglist Function
この関数は、関数functionの引数リストとして arglistを使うことを指定する。

たとえば、

(ad-define-subr-args 'fset '(sym newdef))

は、関数fsetの引数リストを指定します。


Node:Combined Definition, Previous:Subr Arguments, Up:Advising Functions

結合定義

関数には、n個の事前アドバイス(before-advice)、 m個の包囲アドバイス(around-advice)、 k個の事後アドバイス(after-advice)があるとします。 保護したアドバイス断片はないと仮定すると、 関数のアドバイスを実装するために作成される結合定義は つぎのようになります。

(lambda arglist
  [ [advised-docstring] [(interactive ...)] ]
  (let (ad-return-value)
    before-0-body-form...
         ....
    before-n-1-body-form...
    around-0-body-form...
       around-1-body-form...
             ....
          around-m-1-body-form...
             (setq ad-return-value
                   apply original definition to arglist)
          other-around-m-1-body-form...
             ....
       other-around-1-body-form...
    other-around-0-body-form...
    after-0-body-form...
          ....
    after-k-1-body-form...
    ad-return-value))

マクロはマクロとして再定義します。 つまり、結合定義の先頭にmacroを追加します。

元関数やアドバイス断片のどれかに対話宣言があれば、 対話宣言フォームが入ります。 対話的な基本関数をアドバイスした場合には、 特別な方法を使います。 つまり、基本関数をcall-interactivelyで呼び出して、 基本関数自身が引数を読み取るようにします。 この場合、アドバイスからは引数を参照できません。

各クラスのさまざまなアドバイスの本体フォームは、 それらの指定された順に組み立てられます。 包囲アドバイスl(around-advice l)のフォーム群は、 包囲アドバイスl - 1(around-advice l - 1)の フォームの1つに入ります。

包囲アドバイスのもっとも内側では、

元定義をarglistに適用

しますが、そのフォームは元関数の種類に依存します。 変数ad-return-valueには、その戻り値が設定されます。 この変数はすべてのアドバイス断片から見えるので、 アドバイスした関数から実際に戻るまえに、 これを参照したり変更できます。

保護したアドバイス断片を含むアドバイスした関数の構造も同じです。 唯一の違いは、フォームunwind-protectにより、 アドバイス断片でエラーを起こしたり非ローカル脱出を行っても、 保護したアドバイスが実行されることを保証します。 包囲アドバイスを1つでも保護していると、その結果として、 包囲アドバイス全体が保護されます。


Node:Debugging, Next:, Previous:Advising Functions, Up:Top

Lispプログラムのデバッグ

Emacs Lispプログラムの問題点を調べるには、 問題が発生したときにどのようにプログラムを使っているかに依存して、 3つの方法があります。

他の有用なデバッグツールは、ドリブルファイルです。 ドリブルファイルをオープンしてあると、 Emacsはすべてのキーボード入力をこのファイルにコピーします。 あとでこのファイルを調べれば、どんな入力があったかわかります。 See Terminal Input

端末設定に関した問題を解決するには、 関数open-termscriptが有用です。 See Terminal Output


Node:Debugger, Next:, Up:Debugging

Lispデバッガ

通常のLispデバッガは、フォームの評価を一時停止する機能を提供します。 評価を一時停止しているあいだ(ブレーク(break)と呼ばれる状態)は、 実行時スタックを調べたり、ローカルやグローバル変数の値を調べたり、 それらの値を変更できます。 ブレークは再帰編集なので、Emacsの通常の編集機能すべてを使えます。 デバッガを再帰的に起動するようなプログラムを実行することさえできます。 See Recursive Editing


Node:Error Debugging, Next:, Up:Debugger

エラーによるデバッガの起動

デバッガへ入るもっとも重要な時期は、Lispエラーが発生したときです。 これにより、エラーの直接原因を調べることができます。

しかし、デバッガに入るのは、エラーの通常の帰結ではありません。 多くのコマンドは (バッファの末尾でC-fを使うなどの)不適切に起動されると しばしばLispエラーを生じますが、 通常の編集ではそのたびにデバッガに入ったのではとても不便です。 そのため、エラーによってデバッガに入りたい場合には、 変数debug-on-errornil以外を設定します。 (コマンドtoggle-debug-on-errorはこれを簡単に行う。)

debug-on-error User Option
この変数は、エラーが通知され処理されないときに デバッガを呼び出すかどうか決定する。 debug-on-errortであると、 すべての種類のエラー(debug-ignored-errorsに指定したものを除く) はデバッガを呼び出す。 nilであるとデバッガを呼び出さない。

その値はデバッガを呼び出すエラー条件のリストでもよい。 たとえば、リスト(void-variable)にすると、 「値を持たない変数に関したエラー」のみがデバッガを起動する。

この変数がnil以外であると、 Emacsはプロセスのフィルタ関数や番兵に対してエラーハンドラを作成しない。 したがって、これらの関数でのエラーもデバッガを起動する。 see Processes

debug-ignored-errors User Option
この変数は、デバッガに入らないエラーの種類を指定する。 その値はエラー条件シンボルや正規表現のリストである。 エラーにこれらの条件シンボルが含まれるか エラーメッセージが正規表現の1つに一致する場合には、 debug-on-errorの値に関わらず 当該エラーではデバッガに入らない。

この変数の通常の値は、 編集ではしばしば発生するが、Lispプログラムのバグではほとんど発生しないような エラー群のリストである。 しかし、『ほとんど』は『けっして』ではない。 このリストに一致するようなエラーで読者のプログラムが失敗する場合、 エラーをデバッグするにはこのリストを変更する必要がある。 もっとも簡単な方法は、debug-ignored-errorsnilを 設定することである。

debug-on-signal User Option
通常、condition-caseで捕捉したエラーは、 たとえdebug-on-errornil以外であっても、 けっしてデバッガを起動しない。 いいかえれば、デバッガを起動するまえに、 condition-caseはエラー処理の機会を得るのである。

debug-on-signalnil以外の値を設定すると、 各エラーごとにデバッガがまず機会を得る。 debug-on-errordebug-ignored-errorsの値で指定される 条件に一致すれば、condition-caseに関わらず エラーはデバッガを起動する。

警告: この変数は強力な処方である! Emacsのさまざまな部分では通常の動作としてエラーを処理し、 読者にはエラーが発生したことさえわからない。 debug-on-signalnil以外の値を設定すると それらのエラーでデバッガに入る。

警告: debug-on-errornilであると、 debug-on-signalは意味を持たない。

ファイル.emacsをロード中に発生するエラーをデバッグするには、 オプション--debug-initを使います。 これにより、.emacsのロード中はdebug-on-errortに束縛し、 初期化ファイルでのエラーを捕捉するcondition-caseを迂回します。

読者のファイル.emacsdebug-on-errorを設定しても、 その効果は.emacsのロードを終ると持続しません。 (これはコマンド行オプション--debug-initの実装における 好ましくない特性である。) .emacsdebug-on-errorを恒久的に設定する最良の方法は、 つぎのように、after-init-hookを用いることです。

(add-hook 'after-init-hook
          '(lambda () (setq debug-on-error t)))


Node:Infinite Loops, Next:, Previous:Error Debugging, Up:Debugger

無限ループのデバッグ

プログラムが無限にループし戻ってこないときには、 まず、ループを停止する必要があります。 ほとんどのオペレーティングシステムでは、 中断を意味するC-gを使います。

普通に中断したのでは、 プログラムが無限ループした理由に関する情報は得られません。 より詳しい情報を得るには、 変数debug-on-quitnil以外を設定します。 C-gによる中断はエラーとは扱わないため、 C-gの処理に関してdebug-on-errorはなんの効果もありません。 同様に、debug-on-quitはエラーに関してなんの効果もありません。

無限ループの途中でデバッガを起動できれば、 デバッガでステップ実行コマンドを使って先へ進めます。 ループひとまわりをステップ実行すれば、 問題を解決するに十分な情報を得られるはずです。

debug-on-quit User Option
この変数は、quitが通知され処理されなかった場合に、 デバッガを呼び出すかどうかを決定する。 debug-on-quitnil以外である場合、 (C-gを打って)中断するとデバッガを呼び出す。 debug-on-quitnilであると、 中断してもデバッガを呼び出さない。 see Quitting


Node:Function Debugging, Next:, Previous:Infinite Loops, Up:Debugger

関数呼び出し時のデバッガの起動

プログラムの途中で発生する問題点を調べるための1つの有用な技法は、 ある関数を呼び出すたびにデバッガに入ることです。 問題を生じる関数に対してこのようにしておき、 当該関数をステップ実行するか、あるいは、 問題が発生する直前に呼ばれる関数に対してこのようにしておき、 その関数の呼び出しを終えてから、呼び出し側をステップ実行します。

debug-on-entry function-name コマンド
この関数は、function-nameが呼び出されるたびに デバッガを起動するようにする。 当該関数の定義の最初のフォームとして フォーム(debug 'debug)を挿入することでこれを行う。

Lispコードで定義した任意の関数は、 解釈実行コードであろうとコンパイル済みのコードであろうと、 関数に入るときにブレークするようにできる。 関数がコマンドであると、Lispから呼ばれたときや 対話的に呼ばれたときに(引数を読み取ってから)デバッガに入る。 (Cで書いた)基本関数は、この方法ではデバッグできない。

debug-on-entryを対話的に呼び出すと、 ミニバッファでfunction-nameを問い合わせる。 その関数がすでに呼び出し時にデバッガを起動するようになっていると、 debug-on-entryはなにもしない。 debug-on-entryはつねにfunction-nameを返す。

注意: debug-on-entryを使ったあとに当該関数を再定義すると、 デバッガに入るためのコードがなくなる。 実質的には、関数を再定義すると呼び出し時にブレークする機能を 取り消すことになる。

(defun fact (n)
  (if (zerop n) 1
      (* n (fact (1- n)))))
     => fact
(debug-on-entry 'fact)
     => fact
(fact 3)

------ Buffer: *Backtrace* ------
Entering:
* fact(3)
  eval-region(4870 4878 t)
  byte-code("...")
  eval-last-sexp(nil)
  (let ...)
  eval-insert-last-sexp(nil)
* call-interactively(eval-insert-last-sexp)
------ Buffer: *Backtrace* ------

(symbol-function 'fact)
     => (lambda (n)
          (debug (quote debug))
          (if (zerop n) 1 (* n (fact (1- n)))))

cancel-debug-on-entry function-name コマンド
この関数は、function-nameに対するdebug-on-entryの効果 (呼び出し時にブレークする)を取り消す。 対話的に呼び出すと、 ミニバッファでfunction-nameを問い合わせる。 function-namenilであったり空文字列であると、 すべての関数について、呼び出し時にブレークすることを取り消す。

呼び出し時にブレークする設定をしていない関数に対して cancel-debug-on-entryを呼び出してもなにもしない。 つねにfunction-nameを返す。


Node:Explicit Debug, Next:, Previous:Function Debugging, Up:Debugger

デバッガの明示的な起動

読者のプログラムに式(debug)を書くと、 その箇所でデバッガを呼び出すことができます。 つまり、ソースファイルを訪問して適当な箇所にテキスト(debug)を挿入し、 C-M-xと打ちます。 警告: 一時的なデバッグ目的でこれを行う場合には、 ファイルを保存するまえにこの挿入箇所をもとに戻すこと!

(debug)を挿入する箇所は、 余分なフォームを評価してもその値を無視できる場所でなければなりません。 ((debug)の値が無視されないと、 プログラムの実行を変えてしまう!) もっとも適した一般的な場所はprognや暗黙のprognの内側です (see Sequencing)。


Node:Using Debugger, Next:, Previous:Explicit Debug, Up:Debugger

デバッガの使い方

デバッガに入ると、それまで選択していたバッファをあるウィンドウに、 *Backtrace*という名前のバッファを別のウィンドウに表示します。 バックトレースバッファでは、各行は現在実行中のLisp関数の各レベルです。 このバッファの先頭には、デバッガを起動するに至った理由 (エラーで起動されたときにはエラーメッセージと関連データ) を表すメッセージがあります。

バックトレースバッファは読み出し専用であり、 各文字をデバッガコマンドであると定義した 特別なメジャーモード、debuggerモードを使います。 Emacsの通常の編集コマンドも使えます。 したがって、エラー発生時に編集していたバッファを調べるためにウィンドウを 切り替えたり、バッファを切り替えたり、ファイルを訪れたり、 その他のどんな編集でもできます。 しかし、デバッガは再帰編集レベル(see Recursive Editing)であるので、 デバッグを終えるときには、バックトレースバッファに戻ってから デバッガを(コマンドqで)終了するのが賢い方法です。 デバッガを終了すると、再帰編集から抜けバックトレースバッファを削除します。

バックトレースバッファでは、実行中の関数とその引数の値を表示します。 また、スタックフレームを記述する行へポイントを移動することで スタックフレームを指定できます。 (スタックフレームとは、Lispインタープリタが関数の起動に関する情報を 記録しておく場所である。) ポイントがある行に対応するフレームをカレントフレーム(current frame)と 呼びます。 デバッガのある種のコマンドはカレントフレームに作用します。

デバッガ自身はバイトコンパイルしたものを実行する必要があります。 というのは、デバッガ自身が使用するスタックフレームのサイズを 仮定しているからです。 解釈実行だとこの仮定が成り立ちません。


Node:Debugger Commands, Next:, Previous:Using Debugger, Up:Debugger

デバッガコマンド

デバッガ内(debuggerモード)では、 通常のカーソル移動コマンドに加えて以下の特別なコマンドを使えます。 (ウィンドウやバッファの切り替えなどのEmacsの通常の機能も使えることに留意。)

デバッガコマンドのもっとも重要な使い方はステップ実行であり、 これにより制御の流れを調べることです。 デバッガは、解釈実行版の関数の制御構造をステップ実行できますが、 バイトコンパイルした関数ではできません。 バイトコンパイルした関数をステップ実行したい場合には、 同じ関数を解釈実行版の定義に置き換える必要があります。 (これには、関数のソースを訪れて、その定義内でC-M-xと打つ。)

debuggerモードのコマンド一覧を以下に示します。

c
デバッガを終了し実行を継続する。 継続可能であれば、 (デバッガ内で行った変数値やデータ構造に対する変更などの副作用を除いて) デバッガを起動しなかったかのようにプログラムの実行を再開する。

継続が可能なのは、 関数呼び出し時や終了時、明示的な起動、中断によりデバッガに入った場合である。 エラーが原因でデバッガが起動されたときには継続できない。

d
実行を継続するが、任意のLisp関数を呼び出すとデバッガに入る。 これにより、式の部分式をステップ実行して 部分式が計算する値やその動作を調べることができる。

このようにしてデバッガを起動した関数呼び出しのスタックフレームには 自動的に印が付き、そのスタックから抜けるとデバッガがふたたび呼び出される。 この印を消すにはコマンドuを使う。

b
フレームから抜けるとデバッガに入るようにカレントフレームに印を付ける。 このように印を付けたフレームには、バックトレースバッファでは星印が付く。
u
カレントフレームから抜けるときにデバッガに入らない。 これは、当該フレームに対するコマンドbを取り消す。 視覚的にはバックトレースバッファの当該行から星印が取られる。
e
ミニバッファでLisp式を読み取り、それを評価し、その値をエコー領域に表示する。 この操作の一環として、デバッガは重要なある種の変数や カレントバッファを変更する。 eはそれらの値をデバッガの外側の値に一時的に復元するので、 それらを調べたり変更したりできる。 これによりデバッガは透過的になる。 対照的に、M-:はデバッガ内で特別なことは行わない。 デバッガ内での変数値を表示する。
R
eと同様であるが、 バッファ*Debugger-record*での評価結果も保存する。
q
デバッグ中のプログラムを終了する。 Emacsのトップレベルのコマンド実行へ戻る。

C-gでデバッガへ入ったが、 実際には中断したいのであってデバッグはしたくない場合には コマンドqを使う。

r
デバッガから値を指定して戻る。 その値は、ミニバッファで式を読み取り、それを評価して得る。

bで指定したりdでフレームに入ることで) Lispの呼び出しフレームから抜けでたためにデバッガが起動された場合に、 コマンドrは有用である。 コマンドrで指定した値は、当該フレームの値として使われる。 このコマンドは、debugを呼び出してその戻り値を使う場合にも有用である。 さもなければ、rcと同じ効果であり、指定した戻り値は関係ない。

エラーでデバッガに入った場合にはrは使えない。


Node:Invoking the Debugger, Next:, Previous:Debugger Commands, Up:Debugger

デバッガの起動

ここでは、デバッガを起動するために使われる関数debugの詳細を述べます。

debug &rest debugger-args Function
この関数はデバッガに入る。 *Backtrace*(あるいはデバッガの第2レベルに再帰的に入ると *Backtrace*<2>など)という名前のバッファに切り替え、 Lisp関数の呼び出しスタックに関する情報でこのバッファを満たす。 そして再帰編集に入りdebuggerモードのバックトレースバッファを表示する。

debuggerモードのコマンドcrで再帰編集から抜けだし、 debugはそれ以前のバッファに切り替え debugを呼び出したところへ戻る。 これは、関数debugが呼び出し側へ戻る唯一の手段である。

debugger-argsの使い途は、 debugが引数の残りをバッファ*Backtrace*の先頭に表示し、 ユーザーが読めるようにすることである。 以下に述べる場合を除いて、これがこれらの引数の唯一の用途である。

debugの第1引数が特定の値を持つ場合、特別な意味がある。 (通常、これらの値はEmacs内部で用いるだけであり、 プログラマがdebugを呼ぶときには使わない。) 以下にこれらの特別な値を示す。

lambda
第1引数がlambdaであると、 debug-on-next-callnil以外であるために 関数に入るときにdebugを呼び出したことを意味する。 デバッガはバッファの先頭にテキスト行Entering:を表示する。
debug
第1引数がdebugであると、 関数に入るときにデバッガを起動するようになっていたために debugを呼び出したことを示す。 デバッガは、lambdaの場合と同様に、Entering:を表示する。 さらに、当該関数のスタックフレームに関数から 戻るときにデバッガを起動するように印を付ける。
t
第1引数がtであると、 debug-on-next-callnil以外であるときに フォームの並びを評価したために debugを呼び出したことを示す。 デバッガはバッファの先頭行につぎの行を表示する。
Beginning evaluation of function call form:

exit
第1引数がexitであると、 スタックフレームから抜けるときにデバッガを呼び出すように印を 付けたスタックフレームから抜けたことを示す。 この場合、debugの第2引数はフレームからの戻り値である。 デバッガはバッファの先頭行にReturn value:に続けて戻り値を表示する。
error
第1引数がerrorであると、 エラーやquitが通知されたが処理されないためにデバッガに入ったことを示し、 Signaling:に続けて通知されたエラーとsignalの引数を表示する。 たとえばつぎのとおり。
(let ((debug-on-error t))
  (/ 1 0))

------ Buffer: *Backtrace* ------
Signaling: (arith-error)
  /(1 0)
...
------ Buffer: *Backtrace* ------

エラーが通知されたときには、 変数debug-on-errornil以外であるはずである。 quitが通知されたときには、 変数debug-on-quitnil以外であるはずである。

nil
明示的にデバッガに入るときには、 debugger-argsの先頭としてnilを使う。 debugger-argsの残りはバッファの先頭行に表示される。 この機能を用いてメッセージを表示でき、 たとえば、debugを呼び出した条件の覚え書きにする。


Node:Internals of Debugger, Previous:Invoking the Debugger, Up:Debugger

デバッガの内部

本節では、デバッガが内部的に使用する関数や変数について述べます。

debugger Variable
この変数の値は、デバッガを起動するために呼び出す関数である。 その値は、可変個数の引数を取る関数(あるいは典型的には関数名)であること。 その関数でなんらかのデバッガに入ると仮定する。 この変数のデフォルト値はdebug

Lispが関数に渡す最初の引数で、呼び出した理由を表す。 引数の規約はdebugに記述してある。

backtrace コマンド
この関数は、現在活性なLisp関数呼び出しのトレースを表示する。 これは、debugがバッファ*Backtrace*を 満たすために用いる関数である。 どの関数呼び出しが活性であるかを 判断するためにスタックを参照する必要があるためCで書いてある。 戻り値はつねにnil

以下の例では、Lisp式で明示的にbacktraceを呼び出す。 これにより、バックトレースをストリームstandard-outputに出力する。 ここではバッファbacktrace-outputに出力する。 バックトレースの各行は、1つの関数呼び出しを表す。 関数の引数値すべてが判ればそれらを行に表示する。 それらが計算途中であれば、その旨を行に表示する。 スペシャルフォームの引数は省略する。

(with-output-to-temp-buffer "backtrace-output"
  (let ((var 1))
    (save-excursion
      (setq var (eval '(progn
                         (1+ var)
                         (list 'testing (backtrace))))))))

     => nil

----------- Buffer: backtrace-output ------------
  backtrace()
  (list ...computing arguments...)
  (progn ...)
  eval((progn (1+ var) (list (quote testing) (backtrace))))
  (setq ...)
  (save-excursion ...)
  (let ...)
  (with-output-to-temp-buffer ...)
  eval-region(1973 2142 #<buffer *scratch*>)
  byte-code("...  for eval-print-last-sexp ...")
  eval-print-last-sexp(nil)
* call-interactively(eval-print-last-sexp)
----------- Buffer: backtrace-output ------------

文字*は、 抜け出るときにデバッガを起動する印が付いているフレームを表す。

debug-on-next-call Variable
この変数がnil以外であると、 つぎにevalapplyfuncallを呼び出すまえに デバッガを呼び出すことを指定する。 デバッガに入るとdebug-on-next-callnilに設定する。

デバッガのコマンドdは、この変数を設定することで動作する。

backtrace-debug level flag Function
この関数は、levelの深さのスタックフレームに 値flagに応じてフレームから抜け出るときのデバッガ呼び出しの印を付ける。 flagnil以外であると、 のちに当該フレームから抜けるとデバッガに入る。 非ローカルな脱出で当該フレームから抜けるときにもデバッガに入る。

この関数はデバッガのみが使用する。

command-debug-status Variable
この変数は、現在の対話的コマンドのデバッグ状況を記録する。 コマンドが対話的に呼び出されるたびに、 この変数はnilに束縛される。 デバッガはこの変数に設定することで、 同じコマンドの起動中にデバッガが将来起動された場合に備えて 情報を残すことができる。

デバッガにとっては、通常のグローバル変数ではなくこの変数を使う利点は、 以降のコマンド起動にデータが繰り越さないことである。

backtrace-frame frame-number Function
関数backtrace-frameは、Lispデバッガで使うことを意図している。 深さframe-numberのスタックフレームで進行中の計算に関する情報を返す。

当該フレームで引数の評価を完了していなければ(あるいはスペシャルフォーム)、 値は(nil function arg-forms...)

当該フレームで引数の評価を完了し関数を呼び出していれば、 値は(t function arg-values...)

戻り値において、functionは評価したリストのCARであるか、 マクロ呼び出しではlambda式である。 関数に引数&restがあれば、リストarg-valuesの残りで表現される。

frame-numberが範囲外であると、backtrace-framenilを返す。


Node:Edebug, Next:, Previous:Debugger, Up:Debugging

edebug

edebugはEmacs Lispプログラムのソースレベルデバッガであり、 つぎのことを行えます。

以下の最初の3つの節では、edebugを使うのに十分な情報を与えます。


Node:Using Edebug, Next:, Up:Edebug

edebugの使い方

edebugでLispプログラムをデバッグするには、 デバッグしたいLispコードをまず処置(instrument)しておく必要があります。 これを行う簡単な方法は、関数やマクロの定義にポイントを移動してから、 C-u C-M-x(前置引数を指定したeval-defun)を実行します。 コードを処置する別の方法については、See Instrumenting

関数をいったん処置しておけば、当該関数を呼び出すとedebugを活性にします。 edebugが活性になると実行を停止し、 読者が選択したedebugの実行モードに応じて、 関数をステップ実行したりデバッグコマンドを検査しながら 表示を更新しつつ実行を継続します。 デフォルトの実行モードはステップ実行であり、 いったん実行を停止します。 See Edebug Execution Modes

edebugでは、デバッグ中のLispコードのソースを 表示したEmacsバッファを読者は見ます。 このバッファをソースコードバッファと呼びます。 このバッファは一時的に読み出し専用です。

左端の矢印は、関数の実行中の行を表します。 ポイントの初期位置は関数の実行中の行にありますが、 読者自身がポイントを移動すると変わります。

(以下の)facの定義を処置してから(fac 3)を実行したとすると、 つぎのようになります。 ポイントはifのまえの開き括弧にあります。

(defun fac (n)
=>-!-(if (< 0 n)
      (* n (fac (1- n)))
    1))

edebugが関数内で実行を停止できる箇所を停止位置(stop point)と呼びます。 これらは、リストである各部分式の前後と各変数参照のうしろにあります。 関数facの中にある停止位置をピリオドで示します。

(defun fac (n)
  .(if .(< 0 n.).
      .(* n. .(fac (1- n.).).).
    1).)

ソースコードバッファでは、Emacsのlispモードのコマンドに加えて edebugの特別なコマンドを使えます。 たとえば、つぎの停止位置まで実行するには edebugコマンド<SPC>を打ちます。 facに入ったあとで<SPC>を1回打つと、 つぎのような表示になります。

(defun fac (n)
=>(if -!-(< 0 n)
      (* n (fac (1- n)))
    1))

式のうしろでedebugが実行を停止すると、 式の値をエコー領域に値を表示します。

多用される他のコマンドには、 停止位置にブレークポイントを設定するb、 ブレークポイントに達するまで実行するg、 edebugを終了してトップレベルのコマンドループへ戻るqがあります。 edebugのコマンド一覧を表示するには?を打ちます。


Node:Instrumenting, Next:, Previous:Using Edebug, Up:Edebug

edebug向けの処置

Lispコードのデバッグにedebugを使うためには、 コードをまず処置する必要があります。 コードを処置すると、適当な箇所でedebugを起動する追加のコードを挿入します。

いったんedebugをロードすると、 コマンドC-M-xeval-defun)は再定義されます。 定義内で前置引数を指定して起動すると 定義を評価するまえに処置するようになります。 (ソースコード自体は変更しない。) 変数edebug-all-defsnil以外であると、 前置引数の意味を逆にします。 つまり、前置引数を指定しない限りC-M-xは関数定義を処置します。 変数edebug-all-defsのデフォルト値はnilです。 コマンドM-x edebug-all-defsは変数edebug-all-defsの値を トグルします。

edebug-all-defsnil以外であると、 コマンドeval-regioneval-current-buffereval-bufferも それらが評価する定義を処置します。 同様に、edebug-all-formsは、 定義以外のフォームであってもeval-region任意のフォームを処置するかどうか制御します。 これは、ミニバッファでのロードや評価には適用されません。 コマンドM-x edebug-all-formsはこのオプションをトグルします。

別のコマンドM-x edebug-eval-top-level-formは、 edebug-all-defsedebug-all-formsの値に関わらず 任意のトップレベルのフォームを処置するために使えます。

edebugが動作中は、 コマンドIedebug-instrument-callee)で、 ポイントのうしろのフォームから呼ばれる関数やマクロの定義を 処置済みでなければ処置できます。 これは、edebugが当該関数のソースを探せる場合にのみ可能です。 edebugをロード後には、 eval-regionは、処置していないものも含めて、 評価した各定義の位置を記録しています。 関数を処置後に呼び出してステップ実行する コマンドi(see Jumping)も参照してください。

edebugは、標準のスペシャルフォームすべて、 式を引数とするinteractiveフォーム、 無名ラムダ式、他の定義フォームをどのように処置するかわかっています。 edebugは、マクロ呼び出しを引数に持つユーザー定義マクロをどのように 処置すべきかわかりませんから、読者がそれを指示する必要があります。 詳しくは、See Instrumenting Macro Calls

edebugは、あるセッションで初めてコードを処置する場合、 フックedebug-setup-hookを実行してから それにnilを設定します。 これを利用すると、読者が使用するパッケージに対応した edebug用仕様(see Instrumenting Macro Calls)を edebugを使用する場合にのみロードするようにできます。

定義から処置を取り除くには、 処置しないような方法でその定義を単に再評価するだけです。 けっして処置せずにフォームを評価する方法は2つあります。 ファイルをloadするか、 ミニバッファでeval-expressionM-:)を使います。

edebugが処置中に構文エラーを検出すると、 コードのエラー箇所にポイントを置いて、 エラーinvalid-read-syntaxを通知します。

edebugの内側で使える他の評価関数についてはSee Edebug Eval


Node:Edebug Execution Modes, Next:, Previous:Instrumenting, Up:Edebug

edebugの実行モード

edebugには読者がデバッグしているプログラムを実行するための 実行モードが複数あります。 これらをedebugの実行モードと呼びます。 これらをメジャーモードやマイナモードと混同しないでください。 edebugの実行モードは、停止するまでにどの程度edebugが実行を継続するか、 たとえば、各停止位置で停止するのかつぎのブレークポイントまで継続するのか、 また、停止するまでに評価の進行状況をどの程度edebugが表示するのかを 決定します。

通常、あるモードにおいて、 プログラムを継続するコマンドを打つことでedebugの実行モードを指定します。 以下にそれらのコマンドの一覧を示します。 Sを除くすべてのコマンドは、 少なくともある程度プログラムの実行を再開します。

S
停止: プログラムをいっさい実行せずに、 edebugコマンドの入力を待つ(edebug-stop)。
<SPC>
ステップ実行: つぎに出会う停止位置で止まる(edebug-step-mode)。
n
つぎ: 式のうしろでつぎに出会う停止位置で止まる (edebug-next-mode)。 Edebug Miscedebug-forward-sexpも参照。
t
トレース: edebugの各停止位置で1秒間休止する (edebug-trace-mode)。
T
高速トレース: 各停止位置で表示を更新するが休止しない (edebug-Trace-fast-mode)。
g
実行: つぎのブレークポイントまで実行する (edebug-go-mode)。 see Breakpoints
c
継続: 各ブレークポイントで1秒間休止してから継続する (edebug-continue-mode)。
C
高速継続: 各ブレークポイントへポイントを移動するが休止しない (edebug-Continue-fast-mode)。
G
非停止実行: ブレークポイントを無視する (edebug-Go-nonstop-mode)。 Sや編集コマンドを打てば停止できる。

一般に、上記一覧の上にある実行モードほど下にあるものに比べると プログラムをゆっくり実行、つまり、早く停止します。

実行中やトレース中には、edebugコマンドをなにか打てば実行に割り込めます。 edebugはつぎの停止位置でプログラムを止め、 読者が打ったコマンドを実行します。 たとえば、実行中にtを打てば、つぎの停止位置でトレースモードに 切り替わります。 単に実行を停止するにはSを使います。

読者の関数が入力を読み取る場合、実行に割り込むつもりで打った文字を 関数が読み取ってしまうかもしれません。 読者のプログラムがいつ入力するかに注意していれば、 このような意図しない結果を避けることができます。

本節で述べたコマンドを含むキーボードマクロは動作しません。 つまり、プログラムを再開するためにedebugから抜けると キーボードマクロの制御を失ってしまいます。 これを修正するのは簡単ではありません。 また、edebugの外側でキーボードマクロを定義したり実行しても、 edebug内のコマンドにはなんの影響もありません。 これは普通は利点です。 しかし、オプションedebug-continue-kbd-macro (see Edebug Options)も参照してください。

edebugの新たなレベルに入ると、変数edebug-initial-modeの値を 実行モードの初期値とします。 デフォルトでは、これはステップ実行モードを指定します。 処置した関数を1つのコマンドから複数回呼び出すなどして edebugの同一レベルに再度入ることができることに注意してください。


Node:Jumping, Next:, Previous:Edebug Execution Modes, Up:Edebug

ジャンプ

本節で述べるコマンドは、指定した位置に達するまで実行します。 iを除くすべてのものは、停止する場所に一時的なブレークポイントを 設定してから実行モードに移行します。 意図したブレークポイントより先に別のブレークポイントに達しても 実行を停止します。 ブレークポイントについて詳しくはSee Breakpoints

非ローカル脱出は、読者が意図したプログラムの停止すべき 一時的なブレークポイントを迂回するため、 これらのコマンドは非ローカル脱出があると意図したように動作しません。

h
ポイント位置付近の停止位置まで進む(edebug-goto-here)。
f
プログラムの式1つ分先へ進む(edebug-forward-sexp)。
o
囲んでいるS式の終りまでプログラムを実行する。
i
ポイントのあとのフォームから呼ばれる関数やマクロへ進む。

コマンドhは、一時的なブレークポイントを使って、 ポイント位置付近の停止位置まで進みます。 ブレークポイントについて詳しくはSee Breakpoints

コマンドfは、プログラムの式1つ分先へ進みます。 より正確には、C-M-fによる移動箇所へ一時的なブレークポイントを設定し、 プログラムがブレークポイントで停止するような実行モードで実行します。

前置引数nを指定すると、 ポイント位置からn個先のS式に一時的なブレークポイントを設定します。 囲んでいるリストの残り要素数がnより少なければ、 囲んでいる式の末尾で停止します。

C-M-fの移動先はプログラムが実際に停止するであろう箇所です。 これが正しくない場合もあり、たとえば、condでは正しくありません。

コマンドfは、柔軟性のために、 停止位置ではなくポイント位置でforward-sexpを使います。 現在の停止位置から式1つだけ実行したい場合には、 まずwと打ってポイントを停止位置に移動してからfを打ちます。

コマンドoは式から『出る』まで実行します。 ポイントを含むS式の末尾に一時的なブレークポイントを置きます。 このS式が関数定義そのものである場合には、 oは定義の最後のS式の手前まで実行します。 現在この箇所にいた場合には、関数から戻ってから停止します。 いいかえれば、最後のS式のあとに位置していない限り、 このコマンドは現在実行中の関数から抜けません。

コマンドiは、 ポイント位置のあとにあるリストフォームから呼ばれる関数やマクロへ進み、 最初に出会った停止位置で止まります。 そのフォームはこれから評価されるフォームである必要はありません。 しかし、評価されるフォームが関数呼び出しである場合には、 引数を評価するまえにこのコマンドを使うことを覚えておいてください。 さもないとこのコマンドを使う時期が遅すぎます。

コマンドiは、呼び出す関数やマクロが処置されていないと それらを処置します。 これは便利ですが、それらの関数やマクロは、明示的に処置を取り除かない限り、 処置したままになります。


Node:Edebug Misc, Next:, Previous:Jumping, Up:Edebug

edebugのその他のコマンド

edebugの他のコマンドを以下に示します。

?
edebugのヘルプメッセージを表示する(edebug-help)。
C-]
1つまえのレベルのコマンドレベルへ戻る(abort-recursive-edit)。
q
エディタのトップレベルのコマンドループへ戻る(top-level)。 edebugのすべての動作中のレベルを含めて、すべての再帰編集レベルから抜ける。 しかし、フォームunwind-protectcondition-caseで保護した 処置済みのコードがあるとデバッガを再開する。
Q
qと同様であるが保護したコードでも停止しない (top-level-nonstop)。
r
もっとも最近の式の既知の結果をエコー領域に再表示する (edebug-previous-result)。
d
わかりやすいようにedebug自体の関数を除外してバックトレースを表示する (edebug-backtrace)。

edebugのバックトレースバッファでは、 標準のデバッガのようにはデバッガのコマンドを使えない。

実行を継続するとバックトレースバッファは自動的に削除される。

edebugの再帰編集から、edebugを再帰的に活性にするコマンドを起動できます。 edebugが活性であるときにはいつでもqでトップレベルへ戻るか、 C-]で1つの再帰編集レベルを抜けることができます。 保留している評価すべてのバックトレースはdで表示できます。


Node:Breakpoints, Next:, Previous:Edebug Misc, Up:Edebug

ブレークポイント

edebugのステップ実行モードは、つぎの停止位置に達すると実行を停止します。 edebugが実行を止める方法は3つあります。 ブレークポイント、グローバルブレーク条件、ソースのブレークポイントです。

edebugを使用中には、読者がテスト中のプログラムにブレークポイント (breakpoint)、つまり、実行を停止すべき箇所を設定できます。 Using Edebugで定義した任意の停止位置にブレークポイントを設定できます。 ブレークポイントの設定や解除において対象となる停止位置は、 ソースコードバッファのポイント位置かそのあとにある停止位置です。 ブレークポイントに関するedebugコマンドはつぎのとおりです。

b
ポイント位置かそのうしろにある停止位置にブレークポイントを設定する (edebug-set-breakpoint)。 前置引数を指定すると、一時的なブレークポイントになる (そこでプログラムが停止すると解除される)。
u
ポイント位置かそのうしろにある停止位置の(あれば)ブレークポイントを解除する (edebug-unset-breakpoint)。
x condition <RET>
conditionnil以外の値に評価される場合にのみ プログラムを停止する条件付きブレークポイントを設定する (edebug-set-conditional-breakpoint)。 前置引数を指定すると、一時的なブレークポイントになる。
B
現在の定義内にあるつぎのブレークポイントにポイント位置を移動する (edebug-next-breakpoint)。

edebug内では、bでブレークポイントを設定し、 uで解除できます。 まず目的のedegugの停止位置にポイント位置を移動し、 bを打ってその箇所にブレークポイントを設定したり、 uを打ってその箇所のブレークポイントを解除します。 設定されていないブレークポイントを解除しても、なにも起こりません。

定義を再評価したり再処置すると、その中のブレークポイントすべてを解除します。

条件付きブレークポイント(conditional breakpoint)は、 プログラムがこの箇所に達するたびに条件を検査します。 条件を評価中に発生するどんなエラーも無視し、 nilとして扱います。 条件付きブレークポイントを設定するにはxを使い、 条件式はミニバッファで指定します。 すでに条件付きブレークポイントを設定してある停止位置に 条件付きブレークポイントを設定し直すと、 それまでの条件式がミニバッファに入るので編集できます。

ブレークポイントを設定するコマンドに前置引数を指定すると、 条件付き/無条件ブレークポイントを一時的なものにできます。 一時的ブレークポイントでプログラムが停止すると、 そのブレークポイントは自動的に解除されます。

edebugのモードが非停止実行でなければ、 edebugはブレークポイントでつねに停止するか休止します。 非停止実行モードでは、ブレークポイントを完全に無視します。

ブレークポイントの場所を確認するには、コマンドBを使います。 同じ関数内のポイント箇所のうしろにあるブレークポイントか、 後続のものがなければ最初のブレークポイントにポイント位置を移動します。 このコマンドは実行を継続しません。 バッファ内で単にポイントを移動するだけです。


Node:Global Break Condition, Next:, Up:Breakpoints

グローバルブレーク条件

グローバルブレーク条件(global break condition)は、 指定した条件が満たされると、その場所に関わらず、実行を停止させます。 edebugは各停止位置においてグローバルブレーク条件を評価します。 これがnil以外の値であると、 ブレークポイントに達したかのように、 実行モードに依存して実行を停止するか休止します。 条件の評価中にエラーが発生しても実行は停止しません。

条件式はedebug-global-break-conditionに保存されます。 コマンドXで新たな条件式を指定できます (edebug-set-global-break-condition)。

グローバルブレーク条件は、読者のコードのどこでイベントが発生するかを 調べるもっとも簡単な方法ですが、コードの実行速度をかなり遅くします。 ですから、使用しない場合には条件をnilに再設定すべきです。


Node:Source Breakpoints, Previous:Global Break Condition, Up:Breakpoints

ソース上のブレークポイント

定義内のすべてのブレークポイントは、定義を処置し直すたびに失われます。 ブレークポイントを失いたくない場合には、 ソース上のブレークポイント(source breakpoint)を指定できます。 これはソースコード上で関数edebugを呼び出すだけです。 もちろん、条件付けして呼び出せます。 たとえば、関数facにおいて、引数がゼロの場合に停止するには、 以下に示すように最初の行を挿入します。

(defun fac (n)
  (if (= n 0) (edebug))
  (if (< 0 n)
      (* n (fac (1- n)))
    1))

関数facを処置してこの関数を呼び出すと、 edebugの呼び出しはブレークポイントのように動作します。 実行モードに応じて、edebugはその箇所で停止するか休止します。

edebugを呼び出したコードが処置済みでなければ、 この関数はdebugを呼び出します。


Node:Trapping Errors, Next:, Previous:Breakpoints, Up:Edebug

エラーの捕捉

Emacsは、通常、エラーが通知されてもcondition-caseで処理されなかった 場合、エラーメッセージを表示します。 edebugが活性であり処置済みのコードを実行していると、 edebugは処理されなかったエラーすべてに反応します。 この動作をedebug-on-erroredebug-on-quitで カスタマイズできます。 See Edebug Options

edebugがエラーに反応すると、 エラーを起こすまえ出会った最後の停止位置を表示します。 この位置は、実際にエラーを起こした処置してない関数の呼び出し位置である 場合もあります。 未束縛な変数のエラーでは、最後の停止位置は、 当該変数の参照位置からかなり離れている場合があります。 そのような場合には、完全なバックトレースを表示したいでしょう (see Edebug Misc)。

edebugが活性なときにdebug-on-errordebug-on-quitを変更しても、 edebugが不活性になったときにそれらの変更を取り消してしまいます。 さらに、edebugの再帰編集中は、これらの変数はedebugの外側での値に 束縛されます。


Node:Edebug Views, Next:, Previous:Trapping Errors, Up:Edebug

edebugのビュー

これらのedebugのコマンドは、edebugに入るまえのバッファやウィンドウの 状態を調べるものです。 外部ウィンドウ構成は、edebugの外側でのウィンドウの集まりや内容に 関するものです。

v
外部ウィンドウ構成を一時的に見る (edebug-view-outside)。
p
edebugの外側でのカレントバッファと外側でのポイント位置を 一時的に表示する(edebug-bounce-point)。 前置引数nは、かわりに休止秒数を指定する。
w
ソースコードバッファで現在の停止位置にポイント位置を戻す (edebug-where)。

同じバッファを表示している別のウィンドウでこのコマンドを使うと、 それ以後、そのウィンドウに現在の定義が表示されるようになる。

W
edebugが外部ウィンドウ構成を保存/復元するかどうかをトグルする (edebug-toggle-save-windows)。

前置引数を指定すると選択したウィンドウだけの保存/復元をトグルする。 ソースコードバッファを表示していないウィンドウを指定するには、 グローバルキーマップのC-x X Wを使う必要がある。

vで外部ウィンドウ構成を見ることができます。 あるいは、(edebugの外側での)カレントバッファが表示されていなくても pでカレントバッファのポイント位置を見ることができます。 ポイント位置を移動したら、 wでソースコードバッファの停止位置へ戻れます。

外部ウィンドウ構成を保存しないようにWを使うたびに、 edebugは保存しておいた外部ウィンドウ構成を破棄します。 そのため、保存するように戻しても、 (プログラムを続行することで)edebugを抜けると、 現在のウィンドウ構成は変更されません。 しかし、*edebug**edebug-trace*の自動再表示は、 十分なウィンドウが開いてないと、 読者が見たいバッファと衝突するかもしれません。


Node:Edebug Eval, Next:, Previous:Edebug Views, Up:Edebug

評価

edebugの内側では、edebugが動作していないがごとく式を評価できます。 edebugは、式の評価と表示に対して見えないようにします。 edebugが明示的に保存/復元する場合を除いて、 副作用を持つ式の評価も期待どおり動作します。 この処理に関して詳しくはSee The Outside Context

e exp <RET>
edebugの外側の文脈で式expを評価する (edebug-eval-expression)。 つまり、edebugは評価への干渉を最小限にとどめようとする。
M-: exp <RET>
edebug自身の文脈で式expを評価する。
C-x C-e
edebugの外側の文脈でポイント位置のまえの式を評価する (edebug-eval-last-sexp)。

edebugはcl.el(版2.03以降)内の構文 lexical-letmacroletsymbol-macroletで 作成されるレキシカル(テキスト上の)束縛を参照する式の評価を扱えます。


Node:Eval List, Next:, Previous:Edebug Eval, Up:Edebug

評価リストバッファ

*edebug*と呼ばれる評価リストバッファを使って、 式を対話的に評価できます。 さらに、edebugが表示を更新するたびに自動的に評価される 式の評価リストを設定することもできます。

E
評価リストバッファ*edebug*へ切り替える (edebug-visit-eval-list)。

バッファ*edebug*では、以下の特別なコマンドに加えて lisp対話モード (see Lisp Interaction) のコマンドも使えます。

C-j
外側の文脈でポイント位置のまえの式を評価し、 その値をバッファに挿入する (edebug-eval-print-last-sexp)。
C-x C-e
edebugの外側の文脈でポイント位置のまえの式を評価する (edebug-eval-last-sexp)。
C-c C-u
バッファの内容から新たな評価リストを構築する (edebug-update-eval-list)。
C-c C-d
ポイント位置にある評価リストグループを削除する (edebug-delete-eval-item)。
C-c C-w
ソースコードバッファに切り替え現在の停止位置に戻る (edebug-where)。

*scratch*で行うのと同様に、 評価リストウィンドウではC-jC-x C-eで式を評価できますが、 それらはedebugの外側の文脈で評価されます。

実行を継続すると、対話的に入力した式(やその結果)は破棄されますが、 実行を停止するたびに評価される式から成る評価リスト(evaluation list) を設定できます。

これを行うには、評価リストバッファにて、 1つ以上の評価リストグループ(evaluation list group)を書きます。 評価リストグループは、1つ以上のLisp式から成ります。 グループはコメント行で区切ります。

コマンドC-c C-uedebug-update-eval-list)は、 バッファを走査して各グループの最初の式を使って 評価リストを再構築します。 (各グループの2番目の式は計算結果を表示した値とみなす。)

edebugに入るたびに、各式に続けてその現在値をバッファに挿入することで 評価リストを再表示します。 このとき、各式がそれぞれグループになるようにコメント行も挿入します。 したがって、バッファのテキストを変更せずに再度C-c C-uと打つと、 評価リストは実質的には変更されません。

評価リストの評価中にエラーが発生すると、 エラーメッセージを評価結果とみなして文字列で表示します。 したがって、現在の文脈では不正な変数を式に使っても 読者のデバッグを遮ることはありません。

評価リストウィンドウに数個の式を追加したときのようすを以下に示します。

(current-buffer)
#<buffer *scratch*>
;---------------------------------------------------------------
(selected-window)
#<window 16 on *scratch*>
;---------------------------------------------------------------
(point)
196
;---------------------------------------------------------------
bad-var
"Symbol's value as variable is void: bad-var"
;---------------------------------------------------------------
(recursion-depth)
0
;---------------------------------------------------------------
this-command
eval-last-sexp
;---------------------------------------------------------------

グループを削除するには、そこへポイントを移動してC-c C-dと打ちます。 あるいは、グループのテキストを単に削除してからC-c C-uで 評価リストを更新します。 評価リストに新たに式を追加するには、 適切な位置に式を挿入し、新たなコメント行を挿入します。 (コメント行にマイナス記号を挿入する必要はない。 コメントの内容は関係ない。) そして、C-c C-uと打ちます

*edebug*を選択したあとは、 C-c C-wでソースコードバッファへ戻れます。 読者が実行を継続するとバッファ*edebug*は削除され、 つぎに必要なときに再度作成されます。


Node:Printing in Edebug, Next:, Previous:Eval List, Up:Edebug

edebugでの出力

読者のプログラムの式が循環したリスト構造を含む値を作り出す場合、 edebugがそれを出力しようとするとエラーになります。

循環構造を扱う1つの方法は、出力を切り詰めるために print-lengthprint-levelを設定することです。 edebugが読者のためにこれを行います。 それらがnilであると、 edebugはprint-lengthprint-levelを50に束縛します。 (実際は、edebugが使う値は e-debug-print-lengthe-debug-print-levelが指定する。) See Output Variables

edebug-print-length User Option
nil以外であると、edebugが結果を出力するときには、 これをprint-lengthに束縛する。 デフォルト値は50

edebug-print-level User Option
nil以外であると、edebugが結果を出力するときには、 これをprint-levelに束縛する。 デフォルト値は50

パッケージcust-printを使えば、 循環構造や要素を共有する構造をより的確に出力することもできます。

cust-printをロードしてedebugでのみこの特別な出力を使うようにするには、 単にコマンドM-x edebug-install-custom-printを使うだけです。 標準の出力関数に戻すには、M-x edebug-uninstall-custom-printを使います。

循環構造を作るコードの例を示します。

(setq a '(x y))
(setcar a a)

特別な出力ではこれをResult: #1=(#1# y)と出力します。 #1=の記法は、これに続く構造に1というラベルを付けます。 また、#1#の記法はすでにラベル付けした構造を参照します。 この記法は、リストやベクトルの任意の共有された要素に使われます。

edebug-print-circle User Option
nil以外であると、edebugが結果を出力するときには、 これをprint-circleに束縛する。 デフォルト値はnil

他のプログラムでもこの特別な出力を使えます。 詳しくは、cust-print.elを参照してください。


Node:Trace Buffer, Next:, Previous:Printing in Edebug, Up:Edebug

トレースバッファ

edebugは、実行トレースを*edebug-trace*というバッファに保存することで それらを記録できます。 これは、関数名とそれらの引数、戻り値から成る 関数呼び出しとその戻りの記録です。 トレース記録を有効にするには、 edebug-tracenil以外の値を設定します。

トレースバッファを作成することとトレース実行モードとは 同じではありません(see Edebug Execution Modes)。

トレース記録を有効にしていると、 各関数へ入るときと出るときに、トレースバッファに行が追加されます。 関数へ入るときの記録は、::::{に関数名と引数値が続きます。 関数から出るときの記録は、::::}に関数名とその結果が続きます。

入るときの:の個数は、再帰の深さを表します。 関数呼び出しの対応する開始や対応する終了を探すために トレースバッファでは中括弧を使えます。

関数edebug-print-trace-beforeedebug-print-trace-afterを 再定義すれば、関数へ入ったときと出るときのトレース記録をカスタマイズできます。

edebug-tracing string body... Macro
このマクロはフォームbodyの周りにトレース情報を追加する。 引数stringは、トレースバッファに入れるテキストを指定する。 すべての引数を評価する。 edebug-tracingbodyの最後のフォームの値を返す。

edebug-trace format-string &rest format-args Function
この関数はトレースバッファにテキストを挿入する。 テキストは(apply 'format format-string format-args)で 計算する。 区切りとして改行も挿入する。

edebug-tracingedebug-traceは、 edebugが活性でない場合であっても呼ばれるとトレースバッファに行を挿入します。 トレースバッファにテキストを挿入するとき、 挿入した最後の行が見えるようにウィンドウをスクロールします。


Node:Coverage Testing, Next:, Previous:Trace Buffer, Up:Edebug

カバレッジテスト

edebugでは、初歩的なカバレッジテストや実行頻度を表示できます。

カバレッジテストでは、各式の結果を以前の結果と比較します。 現在のEmacsセッションでカバレッジテストを始めて以降、 プログラムの各フォームが異なる2つの値を返せば、 当該フォームを『カバーした』とみなします。 したがって、読者のプログラムについてカバレッジテストを行うには、 さまざまな条件でそれを実行して正しく動作しているか注意します。 読者が各フォームが異なる2つの値を返すように試行し終れば、 edebugはそのように通知します。

カバレッジテストは実行速度を遅くするので、 edebug-test-coveragenil以外の場合にのみテストします。 すべての処置済み関数の実行に関する頻度数計測は、 非停止実行モードであってもカバレッジテストのオン/オフに関わらず行います。

ある定義に関するカバレッジテストと頻度数計測を表示するには M-x edebug-display-freq-countを使います。

edebug-display-freq-count コマンド
このコマンドは、現在の定義の各行について頻度数データを表示する。

頻度数は、コードの各行のあとにコメント行として表示され、 コマンドundoでそれらのコメント行の挿入をアンドゥできる。 頻度数は、式のまえの(や式のうしろの)の直下、 あるいは、変数の最後の文字に表示される。 表示を簡素にするために、頻度数が同じ行のまえのほうの式の頻度数と同じであると 表示しない。

式の頻度数に続く文字=は、 その式を評価するたびに同じ値を返したことを意味する。 いいかえれば、カバレッジテストとしては、 その式はまだ『カバーして』いないことになる。

ある定義に関する頻度数計測とカバレッジデータをクリアするには、 eval-defunで単に再処置すればよい。

たとえば、edebug-test-coveragetとし、 ソース上のブレークポイントを設定して(fac 5)を評価すると、 ブレークポイントに達したときの頻度数データはつぎのようになります。

(defun fac (n)
  (if (= n 0) (edebug))
;#6           1      0 =5
  (if (< 0 n)
;#5         =
      (* n (fac (1- n)))
;#    5               0
    1))
;#   0

コメント行は、facが6回呼ばれたことを表します。 最初のif文は、5回とも同じ結果を返したのです。 2番目のifについても同じです。 facの再帰呼び出しは1度も戻っていません。


Node:The Outside Context, Next:, Previous:Coverage Testing, Up:Edebug

外側の文脈

edebugは、読者がデバッグ中のプログラムに対しては透過であるように努めますが、 完全にうまくいくとは限りません。 また、eで読者が式を評価するときや評価リストバッファでも、 外側の文脈を一時的に復元して透過であるように努めます。 本節では、edebugが復元する文脈について正確に説明し、 edebugが透過にならない場合についても説明します。


Node:Checking Whether to Stop, Next:, Up:The Outside Context

停止すべきかどうかの検査

edebugに入ると、トレース情報を作るのかプログラムを停止するのかを 決定するまえであってもある種のデータを保存/復元する必要が つねにあります。


Node:Edebug Display Update, Next:, Previous:Checking Whether to Stop, Up:The Outside Context

edebugの表示の更新

edebugが(トレースモードなどで)なにかを表示する必要があると、 edebugの『外側』の現在のウィンドウ構成を保存します (see Window Configurations)。 (プログラムを続行して)edebugを抜けるときには、 以前のウィンドウ構成を復元します

Emacsは休止するときにのみ表示を更新します。 通常、プログラムを続行しても、休止したり入力を読むことなく ブレークポイントやステップ実行によりedebugへ戻ります。 そのような場合、Emacsには(edebugの)『外側』のようすを再表示する 機会が与えられません。 見かけ上、ウィンドウの表示は直前にedebugが活性であったときと同じになります。

なにかを表示するためにedebugに入っても以下のデータを保存/復元しますが、 エラーや中断が起こると、故意に復元しないものもあります。


Node:Edebug Recursive Edit, Previous:Edebug Display Update, Up:The Outside Context

edebugの再帰編集

edebugに入ってユーザーコマンドを読み取るとき、 以下のデータを保存し(のちに復元し)ます。


Node:Instrumenting Macro Calls, Next:, Previous:The Outside Context, Up:Edebug

マクロ呼び出しの処置

edebugがLispマクロを呼び出す式を処置するとき、 それを正しく行うにはマクロに関する余分な情報を必要とします。 マクロ呼び出しのどの部分式が評価されるフォームであるかを 明確に判定する方法がないからです。 (マクロ本体で明示的に評価されるか、 結果の展開形が評価されるときか、あるいは、さらにあと)

したがって、edebugが出会う各マクロについて、 当該マクロの呼び出し形式を記述するedebug用仕様を定義する必要があります。 これには、def-edebug-specを使います。

def-edebug-spec macro specification マクロ
マクロmacroの呼び出しのどの式が評価されるかを指定する。 単純なマクロでは、specificationは マクロ定義の仮引数リストに似ているが、 その指定はマクロ引数よりも汎用性がある。

引数macroはマクロ名だけでなく任意のシンボルでよい。

例題マクロfor(see Argument Evaluation)の edebug用仕様の等価な定義例2つを示します。

(def-edebug-spec for
  (symbolp "from" form "to" form "do" &rest form))

(def-edebug-spec for
  (symbolp ['from form] ['to form] ['do body]))

specificationに指定するものとその引数の処理方法は次表のとおりです。

t
すべての引数を評価するように処置する。
0
引数はいっさい処置しない。
シンボル
edebug用仕様を持つシンボルをかわりに使う。 この間接参照は別の種類の仕様を得るまで繰り返す。 これにより、別のマクロから仕様を継承できる。
リスト
リストの各要素は、呼び出しフォームの引数の型を記述する。 仕様リストの各要素については次節で述べる。


Node:Specification List, Next:, Up:Instrumenting Macro Calls

仕様リスト

マクロ呼び出しの引数のあるものは評価し別のものは評価しない場合には、 edebug用仕様に仕様リスト(specification list)が必要になります。 複数の引数に一致する仕様リストの要素もありますが、 後続の要素の処理を修飾する要素もあります。 後者は仕様キーワード(specification keyword)と呼ばれ、 (&optionalのように)&で始まるシンボルです。

仕様リストには、それ自体がリストである引数に一致する部分リストや グループ化に使うベクトルを含んでもかまいません。 部分リストやグループは仕様リストを階層に分けます。 仕様キーワードはそれらを含む部分リストやグループの残りに適用されます。

仕様リストに選択肢や繰り返しが含まれる場合、 実際のマクロ呼び出しに一致させるにはバックトラックが必要な場合もあります。 詳しくはSee Backtracking

edebug用仕様では、正規表現による一致と文脈自由文法の構文を使えます。 対応した括弧に囲まれた部分リスト、フォームの再帰的処理、 間接仕様による再帰です。

仕様リストの要素に指定できるものとそれらの意味を以下に示します。

sexp
処置しない評価しない1つのLispオブジェクト。
form
処置した評価する1つの式。
place
Common Lispのsetf構文のように値を格納する場所。
body
&rest formの省略形。 以下の&restを参照。
function-form
関数フォーム。 クォートした関数シンボル、クォートしたラムダ式、 あるいは、(関数シンボルやラムダ式に評価される)フォーム。 これは、ラムダ式である引数が、 functionではなくquoteでクォートされるときに有用である。 というのは、ラムダ式の本体をいずれかの方法で処置するからである。
lambda-expr
クォートしていないラムダ式。
&optional
この仕様リスト内の後続の要素すべては省略可能。 一致しないと、edebugはただちにこのレベルの一致を止める。

数個の省略可能な要素に省略不可な要素を続けるには、 [&optional specs...]を使う。 数個の要素がすべて一致するかまったく一致しないことを指定するには、 &optional [specs...]を使う。 以下のdefunの例を参照。

&rest
この仕様リスト内の後続の要素すべてを0回以上繰り返す。 最後の繰り返しでは、仕様リストの要素すべてに一致するまえに 式を使い尽くしても問題にはならない。

数個の要素のみを繰り返すには[&rest specs...]を使う。 各繰り返しですべてが一致するような数個の要素を指定するには、 &rest [specs...]を使う。

&or
仕様リスト内の後続の各リストは選択肢を表す。 選択肢の1つに一致しなければ、仕様&orは失敗。

&orに続く各要素は1つの選択肢を表す。 複数の要素を1つの選択肢としてグループにまとめるには、 それらを[...]で囲む。

&not
&orを使ったかように後続の要素を選択肢として一致させるが、 どれかが一致すると仕様は失敗。 どれにも一致しなければ、仕様&notは成功。
&define
仕様は定義フォームに対するものであることを表す。 定義フォームそのものは処置しない (つまり、edbugは定義フォームの前後で停止しない)が、 この内側にあるフォームは典型的には処置される。 キーワード&defineはリスト仕様の最初の要素である必要がある。
nil
現在の引数リストのレベルにおいて一致する引数がなければ成功する。 さもなければ失敗。 部分リスト仕様と以下のバッククォートの例を参照。
gate
いかなる引数とも一致しないが、このゲートを通ると、 このレベルの仕様の残りの部分と一致を調べる際には バックトラックを禁止する。 これは主により詳しい構文エラーメッセージを生成するために使う。 詳しくはBacktrackingを参照。 例については以下のletを参照。
その他のシンボル
仕様リストのその他のシンボルは述語であるか間接仕様である。

シンボルにedebug用仕様があれば、 この間接仕様は、シンボルのかわりに使われる仕様リストであるか、 引数を処理するために呼び出される関数であること。 仕様は、マクロ向けにdef-edebug-specで定義した仕様であってもよい。 以下のdefunの例を参照。

さもなければ、シンボルは述語であること。 述語は引数で呼び出され、述語がnilを返すと仕様は失敗する。 いずれの場合でも、当該引数は処置されない。

適当な述語には、symbolpintegerpstringpvectorpatomがある。

[elements...]
要素のベクトルは要素群を単一のグループ仕様にまとめる。 この意味はベクトルの意味とは関係ない。
"string"
引数はstringという名前のシンボルであること。 この仕様は、symbolの名前がstringである クォートとしたシンボル'symbolと等価であるが、 文字列のほうが望ましい。
(vector elements...)
引数は、仕様内のelementsに一致するものを要素とするベクトルであること。 以下のバッククォートの例を参照。
(elements...)
その他のリストは部分リスト仕様であり、 引数は仕様elementsに一致するものを要素とするリストであること。

部分リスト仕様はドット対リストでもよく、その場合、 対応するリスト引数はドット対リストである。 あるいは、ドット対リスト仕様の最後のCDRは ((spec . [(more specs...)])などの グループや間接仕様を介した) 別の部分リスト仕様であってもよいが、 それらの要素はドット対ではないリスト引数に一致する。 これは、以下のバッククォートの例のような再帰仕様に有用である。 このような再帰を終らせるうえの仕様nilも参照。

(specs . nil)(specs . (sublist-elements...))のような部分リスト仕様は (specs sublist-elements...)と等価であることに注意。

&defineのうしろに追加できる仕様の一覧を以下に示します。 以下のdefunの例を参照してください。

name
引数はシンボルであり、定義フォームの名前である。

定義フォームには単一の名前フィールドがある必要はなく、 複数の名前フィールドを持っていてもよい。

:name
この構造は引数には実際には一致しない。 :nameに続く要素はシンボルであること。 定義に対する追加の名前要素として使う。 定義の名前に一意で静的な要素を追加するために使う。 複数あってもよい。
arg
引数はシンボルであり、定義フォームの引数の名前である。 しかし、ラムダリストキーワード(&で始まるシンボル)は許されない。
lambda-list
ラムダリスト、すなわち、ラムダ式の引数リストに一致する。
def-body
引数は、定義内のコード本体である。 これは、上に述べたbodyに似ているが、 定義本体は定義に関連した情報を調べる異なるedebug呼び出しで処置する必要がある。 定義内のフォームの最上位レベルのリストにはdef-bodyを使う。
def-form
引数は、定義内の単一の最上位レベルのフォームである。 これはdef-bodyに似ているが、 フォームのリストではなく単一のフォームに一致するものに使う。 特別な場合として、def-formは フォームを実行したときにトレース情報を出力しないことを意味する。 以下のinteractiveの例を参照。


Node:Backtracking, Next:, Previous:Specification List, Up:Instrumenting Macro Calls

仕様内でのバックトラック

仕様の一致がある箇所で失敗しても、 必ずしも構文エラーが通知されるとは限りません。 そのかわりに、選択肢すべてを試し尽くすまでバックトラックします。 最終的に、引数リストの各要素は仕様内のいずれかの要素に一致する必要があり、 仕様内の各必須要素はいずれかの引数に一致する必要があります。

構文エラーを検出しても、より高いレベルの選択肢を使い切るまでは報告されず、 実際のエラー箇所から離れた箇所にポイントが置かれます。 しかし、エラー発生時にバックトラックが禁止されていれば、 ただちにエラーが報告されます。 さまざまな状況でバックトラックが自動的に再許可されることに注意してください。 &optional&rest&orで新たに選択肢が指定されたり、 部分リストやグループや間接仕様を処理し始めると、 自動的に再許可されます。 バックトラックの許可/禁止の効果は、 現在処理しているレベルやそれより低いレベルに限定されます。

任意のフォーム仕様(つまり、formbodydef-formdef-body)の一致処理中には、バックトラックを禁止します。 これらの仕様は任意のフォームに一致するので、 エラーはより上のレベルではなくフォーム自身にあるはずです。

また、クォートしたシンボルや文字列の仕様に一致すると バックトラックを禁止します。 というのは、通常、これは構造を認識したことを意味するからです。 しかし、すべてが同一シンボルで始まる選択肢を指定する場合には、 ["foo" &or [first case] [second case] ...]のように、 そのシンボルを選択肢から括り出せばバックトラックするようにできます。

多くの場合では、バックトラックを自動的に禁止するこれらの2つの方法で十分ですが、 仕様gateを使ってバックトラックを明示的に禁止すると有用な場合もあります。 上位の選択肢が適用できないとわかっている場合に有用です。 仕様letの例を参照してください。


Node:Specification Examples, Previous:Backtracking, Up:Instrumenting Macro Calls

仕様の例

以下の例を参考にするとedebug用仕様を理解しやすいでしょう。

スペシャルフォームletには束縛と本体の並びがあります。 各束縛は、シンボル、あるいは、シンボルと省略可能な式から成る部分リストです。 以下のedebug用仕様では、部分リストの内側にあるgateで、 部分リストを一度みつけるとバックトラックを禁止していることに 注意してください。

(def-edebug-spec let
  ((&rest
    &or symbolp (gate symbolp &optional form))
   body))

edebugは、defundefmacro、 および、対応する引数リストと仕様interactiveに対しては、 以下のedebug用仕様を使います。 式の引数は実際には関数本体の外側で評価されるので、 対話宣言フォームを特別扱いする必要があります。

(def-edebug-spec defmacro defun) ; 仕様defunの間接参照
(def-edebug-spec defun
  (&define name lambda-list
           [&optional stringp]   ; あれば、説明文字列に一致する
           [&optional ("interactive" interactive)]
           def-body))

(def-edebug-spec lambda-list
  (([&rest arg]
    [&optional ["&optional" arg &rest arg]]
    &optional ["&rest" arg]
    )))

(def-edebug-spec interactive
  (&optional &or stringp def-form))    ; def-formを参照

以下のバッククォートに対する仕様は、 ドット対リストの一致の仕方と再帰を終らせるnilの使い方を示します。 また、ベクトルの要素の一致の仕方も示します。 (edebugが実際に定義している仕様では、 失敗の可能性がある非常に深い再帰をもたらすためドット対リストを扱わない。)

(def-edebug-spec ` (backquote-form))   ; わかりやすいように別名を付ける

(def-edebug-spec backquote-form
  (&or ([&or "," ",@"] &or ("quote" backquote-form) form)
       (backquote-form . [&or nil backquote-form])
       (vector &rest backquote-form)
       sexp))


Node:Edebug Options, Previous:Instrumenting Macro Calls, Up:Edebug

edebugのオプション

以下のオプションはedebugの動作に影響します。

edebug-setup-hook User Option
edebugを使うまえに呼び出す関数群。 新たな値に設定されるたびに、edebugはこれらの関数を呼び出し、 そのあとでedebug-setup-hooknilに再設定する。 これを用いて、edebugを使用する場合にのみ、 使用するパッケージに対応するedebug用仕様をロードできる。 see Instrumenting

edebug-all-defs User Option
これがnil以外であると、 defundefmacroのような定義フォームを普通に評価すると、 edebug用にそれらを処置する。 これは、eval-defuneval-regioneval-buffereval-current-bufferにも適用される。

このオプションの値をトグルするにはコマンドM-x edebug-all-defsを使う。 see Instrumenting

edebug-all-forms User Option
これがcodenil以外であると、コマンドeval-defuneval-regioneval-buffereval-current-bufferは、 定義しないフォームの場合であってもすべてのフォームを処置する。 これは、ロードやミニバッファでの評価には適用されない。

このオプションの値をトグルするにはコマンドM-x edebug-all-formsを使う。 see Instrumenting

edebug-save-windows User Option
これがnil以外であると、edebugはウィンドウ構成を保存/復元する。 これには時間がかかるので、読者のプログラムがウィンドウ構成に 依存しないのならば、この変数はnilに設定しておくほうがよい。

値がリストであると、リスト内のウィンドウのみを保存/復元する。

edebugのコマンドWを使ってこの変数を対話的に変更できる。 see Edebug Display Update

edebug-save-displayed-buffer-points User Option
これがnil以外であると、edebugは表示されているすべてのバッファの ポイントを保存/復元する。

選択していないウィンドウに表示されたバッファのポイントを変更する コードをデバッグ中には、別のバッファのポイントを保存/復元する必要がある。 edebugやユーザーが当該ウィンドウを選択すると、 そのバッファのポイントはウィンドウのポイント位置に移動する。

すべてのバッファでポイントを保存/復元するには 各ウィンドウを2度選択する必要があるため手間がかかる。 そのため、必要な場合にのみこの機能を有効にする。 see Edebug Display Update

edebug-initial-mode User Option
この変数がnil以外であれば、 edebugが初めて動作するときの初期の動作モードを指定する。 可能な値は、 stepnextgoGo-nonstop, traceTrace-fastcontinueContinue-fast

デフォルト値はstep。 see Edebug Execution Modes

edebug-trace User Option
nil以外であると、関数へ入るときと出るときのトレースを表示することを 意味する。 トレース出力は、*edebug-trace*という名前のバッファに、 関数へ入るときと出るときを各行に再帰の深さで字下げして表示する。

デフォルト値はnilTrace Bufferedebug-tracingも参照。

edebug-test-coverage User Option
nil以外であれば、edebugはデバッグ対象のすべての式のカバレッジ テストを行う。 see Coverage Testing

edebug-continue-kbd-macro User Option
nil以外であれば、 edebugの外側で実行するキーボードマクロを定義したり実行する。 デバッグしないので注意してこのオプションを使うこと。

edebug-on-error User Option
debug-on-errorの以前の値がnilであると、 edebugはdebug-on-errorにこの値を束縛する。 see Trapping Errors

edebug-on-quit User Option
debug-on-quitの以前の値がnilであると、 edebugはdebug-on-quitにこの値を束縛する。 see Trapping Errors

edebugが動作中にedebug-on-erroredebug-on-quitの値を 変更しても、新たなコマンドでedebugをつぎに起動するまでは これらの値は使用されない。

edebug-global-break-condition User Option
nil以外であると、各停止位置で検査される式である。 結果がnil以外であるとブレークする。 エラーは無視する。 see Global Break Condition


Node:Syntax Errors, Next:, Previous:Edebug, Up:Debugging

不正なLisp構文のデバッグ

Lispリーダは不正な構文を報告しますが、どこに問題があるかは報告できません。 たとえば、式を評価中のエラー『End of file during parsing』 (構文解析中にファイルの終り)は、開き括弧(あるいは開き角括弧)が 多すぎることを表します。 Lispリーダは括弧が対応していないことをファイルの末尾で検出しますが、 どこに閉じ括弧があるべきかは判断できません。 同様に、『Invalid read syntax: ")"』(不正な構文:")")は 閉じ括弧が多すぎるか開き括弧が足りないことを表しますが、 どこに括弧が足りないかは判断できません。 それでは、どこを変更すべきかどのように調べるのでしょう?

問題が単純な括弧の非対応でなければ、 各関数定義の先頭でC-M-eを試し、 関数定義の末尾に移動するかどうかをみるのは有用な技法です。 正しく移動しなければ、その関数に問題があります。

Lispによくある構文エラーは括弧の非対応なので、 これらの場面について詳しい助言を述べておきます。 (さらに、対応括弧表示モードをオンにしてポイントを移動すると非対応を 探しやすい。)


Node:Excess Open, Next:, Up:Syntax Errors

開き括弧の過剰

最初の手順は、括弧が対応していない関数定義を探すことです。 開き括弧が過剰であれば、ファイルの末尾に閉じ括弧を挿入し C-M-bbackward-sexp)を打ちます。 こうすると、括弧が対応していない関数定義の先頭へ移動します。 (そうしたら、C-<SPC> C-_ C-u C-<SPC>と打って、 当該箇所にマークを設定してから閉じ括弧の挿入を取り消し、 最終的にマークへ戻る。)

つぎの手順は、なにが悪いか正確に判断することです。 プログラムを調べる以外にこれを確実に行う方法はありませんが、 しばしば、既存の字下げが括弧のありかたを予想する鍵になります。 これを利用するもっとも簡単な方法はC-M-qで字下げし直し、 どのようになるか見ることです。 まだやらないでください! まず読み進んてください。

これを行うまえに、関数定義に充分な数の閉じ括弧があることを確認してください。 さもないと、C-M-qがエラーになったり、 ファイルの末尾までを字下げし直してしまいます。 ですから、関数定義の末尾へ移動して閉じ括弧を挿入しておきます。 C-M-eを使って移動しないでください。 というのは、関数定義の括弧の対応が取れていないと失敗するからです。

関数定義の先頭へ移動してC-M-qを打ちます。 通常、ある場所から関数の末尾までの行が右へずれます。 その場所の近くで、閉じ括弧が足りなかったり開き括弧が多すぎるのです。 (しかし、これが正しいと仮定してはならない。 コードを調べて確認すること。) 不具合箇所がみつかったならば、 意図した括弧に対しては古い字下げが適しているでしょうから C-_C-M-qをアンドゥします。

問題を解決できたと思ったら、再度C-M-qを使います。 古い字下げが意図した括弧の入れ子に対応していて、 必要な括弧を挿入できているならば、 C-M-qはなにも変えないはずです。


Node:Excess Close, Previous:Excess Open, Up:Syntax Errors

閉じ括弧の過剰

過剰な閉じ括弧に対処するには、まず、ファイルの先頭に開き括弧を挿入し、 その括弧のまえでC-M-fを打って、 括弧が対応していない関数定義の末尾を探します。 (そして、C-<SPC> C-_ C-u C-<SPC>と打って、 当該箇所にマークを設定して開き括弧の挿入をアンドゥし、 最終的にマークへ戻る。)

その関数定義の先頭でC-M-fと打って、 実際に対応している閉じ括弧を探します。 これにより、関数定義が終るべき場所より手前の箇所に移動するはずです。 この付近に余分な閉じ括弧がみつかることもあるでしょう。

その場所に問題がなければ、つぎにすべきことは、 関数定義の先頭でC-M-qと打つことです。 ある範囲の行が左にずれるでしょう。 もしそうならば、開き括弧が足りないか余分な閉じ括弧は、 そのような行の先頭付近にあるでしょう。 (しかし、これが正しいと仮定してはならない。 コードを調べて確認すること。) 不具合箇所がみつかったならば、 意図した括弧に対しては古い字下げが適しているでしょうから C-_C-M-qをアンドゥします。

問題を解決できたと思ったら、再度C-M-qを使います。 古い字下げが意図した括弧の入れ子に対応していて、 必要な括弧を挿入できているならば、 C-M-qはなにも変えないはずです。


Node:Compilation Errors, Previous:Syntax Errors, Up:Debugging

コンパイル時の問題のデバッグ

バイトコンパイル時にエラーが発生したときは、 通常、読者がコンパイルしているプログラムの不正な構文に原因があります。 コンパイラはバッファ*Compile-Log*に適切なエラーメッセージを 表示してから停止します。 メッセージにはエラーとなった関数の名前があったりなかったりします。 いずれにしても、つぎのようにしてファイルのどこでエラーが生じたかを調べます。

まず、バッファ *Compiler Input*に切り替えます。 (バッファ名が空白で始まり、そのため、 M-x list-buffersでは表示されないことに注意。) このバッファにはコンパイルしたプログラムが入っていて、 ポイント位置はバイトコンパイラがどこまで読み取ったかを表します。

エラーの原因が不正なLisp構文であるならば、 ポイント位置が不正構文を検出した箇所を正確に表します。 エラー原因が近くにあるとは限りません! エラーを探すために前節の方法を使ってください。

正しく読み取ったフォームのコンパイル中にエラーを検出したときには、 ポイントはそのフォームの末尾に位置しています。 この場合、この方法ではエラー箇所を正確に判別できませんが、 どの関数を確認すべきかを示しています。


Node:Read and Print, Next:, Previous:Debugging, Up:Top

Lispオブジェクトの読み取りと表示

表示(printing)とは Lispオブジェクトをテキスト表現へ変換する操作であり、 読み取り(reading)は逆の変換操作です。 これには、Lisp Data Typesで述べた表示表現と入力構文を用います。

本章では、読み取りや表示を行うLisp関数について述べます。 また、(読み取るときに)テキストをどこから得たり、 (表示するときに)どこへ出すかを指定する ストリーム(stream)についても述べます。


Node:Streams Intro, Next:, Up:Read and Print

読み取りと表示の概要

Lispオブジェクトの読み取りとは、 テキスト表現のLisp式を解析して対応するLispオブジェクトを生成することを 意味します。 これにより、プログラムはLispコードのファイルからLispへ取り込まれます。 テキストをオブジェクトの入力構文(read syntax)と呼びます。 たとえば、テキスト(a . 5)は、 CARaでありCDRが数5であるコンスセルの入力構文です。

Lispオブジェクトの表示とは、 オブジェクトを表現するテキストを生成することを意味します。 つまり、オブジェクトをその表示表現 (see Printed Representation)に変換します。 上に述べたコンスセルを表示するとテキスト(a . 5)を生成します。

読み取りと表示は、多かれ少なかれ、逆操作です。 与えられたテキスト断片を読み取ることで得られたオブジェクトを表示すると、 しばしば、同じテキストを生成します。 オブジェクトを表示することによって得られたテキストを読み取ると、 通常、似たようなオブジェクトを生成します。 たとえば、シンボルfooを表示するとテキストfooを生成し、 そのテキストを読み取るとシンボルfooが返されます。 要素がabであるリストを表示すると テキスト(a b)を生成し、 そのテキストを読み取ると 要素がabである(もとと同じではないが)リストを生成します。

しかし、これら2つの操作は厳密には逆操作ではありません。 3種類の例外があります。


Node:Input Streams, Next:, Previous:Streams Intro, Up:Read and Print

入力ストリーム

テキストを読み取るほとんどのLisp関数は、 ストリーム(stream)を引数として受け付けます。 入力ストリームは、読み取るべきテキストの文字をどこからどのように得るのかを 指定します。 入力ストリームとして使える型は以下のとおりです。

buffer
入力文字はバッファbufferのポイント直後の文字から読み取られる。 1文字読むごとにポイントを進める。
marker
入力文字は、マーカmarkerがあるバッファの マーカ直後の文字から読み取られる。 1文字読むごとにマーカ位置を進める。 ストリームがマーカであるときには、バッファのポイント位置は影響しない。
string
入力文字は文字列stringの先頭文字から必要な文字数だけ読み取られる。
function
入力文字は関数functionが生成する。 この関数は2種類の呼び出し方を扱える必要がある。
t
ストリームとしてtを使うと、ミニバッファから読み取ることを意味する。 実際には、ミニバッファを表示しユーザーが指定したテキストから成る文字列を作り、 それを入力ストリームとして使う。
nil
入力ストリームとしてnilを指定すると、 standard-inputの値をかわりに使うことを意味する。 その値はデフォルト入力ストリームであり、 nil以外の入力ストリームであること。
symbol
入力ストリームとしてのシンボルは、 そのシンボルの(あれば)関数定義と等価である。

バッファであるストリームからの読み取りの例を 読み取り前後のポイント位置を含めて示します。

---------- Buffer: foo ----------
This-!- is the contents of foo.
---------- Buffer: foo ----------

(read (get-buffer "foo"))
     => is
(read (get-buffer "foo"))
     => the

---------- Buffer: foo ----------
This is the-!- contents of foo.
---------- Buffer: foo ----------

最初の読み取りでは空白を読み飛ばしていることに注意してください。 読み取りでは、意味あるテキストのまえにある白文字はいくつでも読み飛ばします。

つぎは、マーカをストリームとして読み取る例です。 マーカの初期位置は下に示したバッファの先頭にあります。 読み取った値はシンボルThisです。

---------- Buffer: foo ----------
This is the contents of foo.
---------- Buffer: foo ----------

(setq m (set-marker (make-marker) 1 (get-buffer "foo")))
     => #<marker at 1 in foo>
(read m)
     => This
m
     => #<marker at 5 in foo>   ;; 最初の空白の直前

つぎは文字列の内容から読み取ります。

(read "(When in) the course")
     => (When in)

以下の例は、ミニバッファから読み取ります。 プロンプトはLisp expression: です。 (ストリームtから読むとつねにこのプロンプトが使われる。) ユーザーの入力はプロンプトに続けて示してあります。

(read t)
     => 23
---------- Buffer: Minibuffer ----------
Lisp expression: 23 <RET>
---------- Buffer: Minibuffer ----------

最後は、useless-streamという名前の関数をストリームにした例です。 このストリームを使うまえに、 変数useless-listを文字のリストで初期化します。 そうすると、関数useless-streamを呼び出すたびに リスト内のつぎの文字を返すか、 リストの先頭に追加して文字を読み戻します。

(setq useless-list (append "XY()" nil))
     => (88 89 40 41)

(defun useless-stream (&optional unread)
  (if unread
      (setq useless-list (cons unread useless-list))
    (prog1 (car useless-list)
           (setq useless-list (cdr useless-list)))))
     => useless-stream

つぎのようにしてストリームを使って読み取ります。

(read 'useless-stream)
     => XY

useless-list
     => (40 41)

リストには開き括弧と閉じ括弧が残っていることに注意してください。 Lispリーダが開き括弧に出会うとこれで入力を終えると決定し、 それを読み戻すのです。 この時点で読み取りを試みると、 ()を読み取ってnilを返します。

get-file-char Function
この関数は、関数loadで開いた入力ファイルから読み取るための 入力ストリームとして内部的に使われる。 読者はこの関数を使ってはならない。


Node:Input Functions, Next:, Previous:Input Streams, Up:Read and Print

入力関数

本節では読み取りに関係するLisp関数や変数について述べます。

以下の関数では、streamは入力ストリーム(前節参照)を表します。 streamnilであったり省略すると、 standard-inputの値をデフォルトにします。

読み取り中に閉じていないリストやベクトル、文字列に出会うと、 エラーend-of-fileを通知します。

read &optional stream Function
この関数はstreamから1つのLisp式のテキスト表現を読み取り、 それをLispオブジェクトとして返す。 これは基本的なLisp入力関数である。

read-from-string string &optional start end Function
この関数はstringのテキストから先頭のLisp式のテキスト表現を読み取る。 読み取った式をCAR、文字列に残っているつぎの文字 (つまり読み取っていない最初の文字)の位置を表す整数をCDR とするコンスセルを返す。

startが指定してあると、文字列のstartで添字付け (先頭文字の添字は0)されるところから読み始める。 endを指定すると、その添字位置の直前で読み取りを終らせ、 文字列には残りの文字がないかのように扱う。

例:

(read-from-string "(setq x 55) (setq y 5)")
     => ((setq x 55) . 11)
(read-from-string "\"A short string\"")
     => ("A short string" . 16)

;; 最初の文字から読み始める
(read-from-string "(list 112)" 0)
     => ((list 112) . 10)
;; 2番目の文字から読み始める
(read-from-string "(list 112)" 1)
     => (list . 5)
;; 7番目の文字から読み始め、9番目の文字で読み終える
(read-from-string "(list 112)" 6 8)
     => (11 . 8)

standard-input Variable
この変数はデフォルトの入力ストリーム、 つまり、引数streamnilである場合にreadが使う ストリームを保持する。


Node:Output Streams, Next:, Previous:Input Functions, Up:Read and Print

出力ストリーム

出力ストリームは表示で生成した文字群をどのように扱うかを指定します。 ほとんどの表示関数は省略可能な引数として出力ストリームを受け付けます。 出力ストリームとして使える型は以下のとおりです。

buffer
出力文字はバッファbufferのポイント位置に挿入される。 文字が挿入されるたびにポイント位置は進められる。
marker
出力文字はマーカmarkerがあるバッファのマーカ位置に挿入される。 文字を挿入するたびにマーカ位置は進められる。 ストリームがマーカであるときには、バッファのポイント位置は影響せず、 この種の表示ではポイントを移動しない。
function
出力文字は関数functionに渡され、この関数が文字の保存に責任を持つ。 1つの文字を引数として出力する文字数の回数だけ呼び出され、 読者の望む場所に文字を保存する責任を持つ。
t
出力文字はエコー領域に表示される。
nil
出力ストリームとしてnilを指定すると、 standard-outputの値をかわりに使うことを意味する。 その値はデフォルト出力ストリームであり、 nil以外であること。
symbol
出力ストリームとしてのシンボルは、 そのシンボルの(あれば)関数定義と等価である。

正当な出力ストリームの多くは、入力ストリームとしても正当です。 入力ストリームと出力ストリームの違いは、 オブジェクト型の違いというよりは、 読者がLispオブジェクトをどのように使うかです。

バッファを出力ストリームとして使った例を示します。 ポイントの初期位置は以下に示すようにthehの直前にあります。 終了後でも、ポイントは同じhの直前に位置しています。

---------- Buffer: foo ----------
This is t-!-he contents of foo.
---------- Buffer: foo ----------

(print "This is the output" (get-buffer "foo"))
     => "This is the output"

---------- Buffer: foo ----------
This is t
"This is the output"
-!-he contents of foo.
---------- Buffer: foo ----------

つぎは、マーカを出力ストリームとして用いた例です。 バッファfooのマーカの初期位置は、 単語thethのあいだにあります。 終了後には、マーカは挿入したテキストを越えて同じhの直前に位置します。 ポイント位置はなんの影響もないことに注意してください。

---------- Buffer: foo ----------
This is the -!-output
---------- Buffer: foo ----------

(setq m (copy-marker 10))
     => #<marker at 10 in foo>

(print "More output for foo." m)
     => "More output for foo."

---------- Buffer: foo ----------
This is t
"More output for foo."
he -!-output
---------- Buffer: foo ----------

m
     => #<marker at 34 in foo>

つぎは、エコー領域への出力の例です。

(print "Echo Area output" t)
     => "Echo Area output"
---------- Echo Area ----------
"Echo Area output"
---------- Echo Area ----------

最後は、関数を出力ストリームとして使った例を示します。 関数eat-outputは与えられた文字を受け取り、 それをリストlast-outputの先頭にコンスします (see Building Lists)。 終了後には、リストがすべての出力文字を保持していますが逆順です。

(setq last-output nil)
     => nil

(defun eat-output (c)
  (setq last-output (cons c last-output)))
     => eat-output

(print "This is the output" 'eat-output)
     => "This is the output"

last-output
     => (10 34 116 117 112 116 117 111 32 101 104
    116 32 115 105 32 115 105 104 84 34 10)

リストの順番を逆にすれば正しい順序の出力になります。

(concat (nreverse last-output))
     => "
\"This is the output\"
"

concatを呼び出してリストを文字列に変換し、 内容を読みやすいようにしました。


Node:Output Functions, Next:, Previous:Output Streams, Up:Read and Print

出力関数

本節ではLispオブジェクトを表示する、 つまり、オブジェクトを表示表現に変換するLisp関数について述べます。

Emacsの表示関数のなかには、正しく読み取れるように クォート文字を出力に追加するものがあります。 使用されるクォート文字は"\です。 これらは、文字列とシンボルを区別したり、 文字列やシンボル内の句読点文字を読み取るときに区切り文字として扱うこと を防ぎます。 詳しくはSee Printed Representation。 出力関数を選べば、クォートのありなしを指定できます。

テキストをLispシステムへ読み取る意図がある場合には、 曖昧さを避けるためにクォート文字付きで表示するべきです。 Lispプログラマに対してLispオブジェクトを明確に記述する場合も同様です。 しかし、人間向けの見やすい出力が目的であれば、 クォートせずに表示するのが普通はよいでしょう。

Lispオブジェクトはそれ自身を参照できます。 自己参照しているオブジェクトを普通の方法で表示するには 無限のテキストが必要であり、 そのような試みは無限再帰をもたらします。 Emacsはそのような再帰を検出し、 すでに表示したオブジェクトを再帰的に表示するかわりに #levelを表示します。 たとえば、#0は、現在の表示操作においてレベル0のオブジェクトを 再帰的に参照することを示します。

(setq foo (list nil))
     => (nil)
(setcar foo foo)
     => (#0)

以下の関数では、streamは出力ストリームを表します。 (出力ストリームについては前節を参照。) streamnilであったり省略すると、 standard-outputの値をデフォルトにします。

print object &optional stream Function
関数printは便利な表示方法である。 オブジェクトobjectの表示表現を ストリームstreamに出力し、 objectの前後に改行を1つずつ表示する。 クォート文字を使う。 printobjectを返す。 たとえばつぎのとおり。
(progn (print 'The\ cat\ in)
       (print "the hat")
       (print " came back"))
     -|
     -| The\ cat\ in
     -|
     -| "the hat"
     -|
     -| " came back"
     -|
     => " came back"

prin1 object &optional stream Function
この関数はオブジェクトobjectの表示表現を ストリームstreamに出力する。 printのようには出力を区切る改行を表示しないが、 printと同様にクォート文字を用いる。 objectを返す。
(progn (prin1 'The\ cat\ in)
       (prin1 "the hat")
       (prin1 " came back"))
     -| The\ cat\ in"the hat"" came back"
     => " came back"

princ object &optional stream Function
この関数はオブジェクトobjectの表示表現を ストリームstreamに出力する。 objectを返す。

この関数は、readではなく人が読みやすい出力を意図しており、 クォート文字を挿入せず、文字列を囲むダブルクォートも出力しない。 空白も追加しない。

(progn
  (princ 'The\ cat)
  (princ " in the \"hat\""))
     -| The cat in the "hat"
     => " in the \"hat\""

terpri &optional stream Function
この関数はストリームstreamに改行を出力する。 関数名は『terminate print』の略。

write-char character &optional stream Function
この関数は文字characterをストリームstreamへ出力する。 characterを返す。

prin1-to-string object &optional noescape Function
この関数は同じ引数に対してprin1が表示するであろう テキストから成る文字列を返す。
(prin1-to-string 'foo)
     => "foo"
(prin1-to-string (mark-marker))
     => "#<marker at 2773 in strings.texi>"

noescapenil以外であると、 出力にはクォート文字を使わない。 (この引数は、Emacs 19版以降で使える。)

(prin1-to-string "foo")
     => "\"foo\""
(prin1-to-string "foo" t)
     => "foo"

文字列としてのLispオブジェクトの表示表現を得るための別の方法については、 String Conversionformatを参照。

with-output-to-string body... Macro
このマクロは、standard-outputを文字列への出力と設定して フォームbodyを実行する。 そして、その文字列を返す。

たとえば、カレントバッファの名前がfooであると

(with-output-to-string
  (princ "The buffer is ")
  (princ (buffer-name)))

"The buffer is foo"を返す。


Node:Output Variables, Previous:Output Functions, Up:Read and Print

出力に影響する変数

standard-output Variable
この変数の値はデフォルトの出力ストリーム、つまり、 引数streamnilの場合に表示関数が用いるストリーム。

print-escape-newlines Variable
この変数がnil以外であると、 文字列内の改行文字を\n、ページ送り文字を\fと表示する。 通常、これらの文字は実際の改行やページ送りとして表示される。

この変数は、クォート付きで表示する表示関数prin1printに影響を与える。 princには影響しない。 prin1を用いた例を示す。

(prin1 "a\nb")
     -| "a
     -| b"
     => "a
b"

(let ((print-escape-newlines t))
  (prin1 "a\nb"))
     -| "a\nb"
     => "a
b"

2番目の式では、prin1の呼び出し中には print-escape-newlinesのローカル束縛が有効であるが、 結果を表示するときには有効ではない。

print-escape-nonascii Variable
この変数がnil以外であると、 クォート付きで表示する出力関数prin1printは、 文字列内のユニバイト非ASCII文字を無条件で バックスラッシュ列として表示する。

これらの関数は、出力ストリームがマルチバイトバッファや マルチバイトバッファのマーク位置であると、 この変数の値に関係なくユニバイト非ASCII文字に対して バックスラッシュ列を用いる。

print-escape-multibyte Variable
この変数がnil以外であると、 クォート付きで表示する表示関数prin1printは、 文字列内のマルチバイト非ASCII文字を無条件で バックスラッシュ列として表示する。

これらの関数は、出力ストリームがユニバイトバッファや ユニバイトバッファのマーク位置であると、 この変数の値に関係なくマルチバイト非ASCII文字に対して バックスラッシュ列を用いる。

print-length Variable
この変数の値は、任意のリスト、ベクトル、ブールベクトルを表示するときの 最大要素数である。 表示するオブジェクトがこれより多くの要素を持つと、 「…」で省略する。

値がnil(デフォルト)であると無制限。

(setq print-length 2)
     => 2
(print '(1 2 3 4 5))
     -| (1 2 ...)
     => (1 2 ...)

print-level Variable
この変数の値は、表示するときの括弧や角括弧の入れ子の最大の深さ。 この制限を越える任意のリストやベクトルは「…」で省略する。 値がnil(デフォルト)であると無制限。


Node:Minibuffers, Next:, Previous:Read and Print, Up:Top

ミニバッファ

ミニバッファ(minibuffer)は、単純な数値前置引数ではなく、 より複雑な引数を読み取るためにEmacsのコマンドが使う特別なバッファです。 これらの引数には、ファイル名、バッファ名、 (M-xでの)コマンド名があります。 ミニバッファは、エコー領域と同様に、フレームの最下行に表示されますが、 引数を読み取るときにのみ表示されます。


Node:Intro to Minibuffers, Next:, Up:Minibuffers

ミニバッファの紹介

ほとんどの意味において、ミニバッファはEmacsの普通のバッファです。 編集コマンドなどのバッファでのほとんどの操作は、 ミニバッファでも普通に動作します。 しかし、バッファを操作するコマンドの多くは、 ミニバッファには適用できません。 ミニバッファの名前はつねに*Minibuf-numberという形式であって、 変更できません。 ミニバッファはミニバッファ専用の特別なウィンドウだけに表示されます。 これらのウィンドウはつねにフレームの最下行に現れます。 (ミニバッファを持たないフレームや、 ミニバッファ用ウィンドウのみの特殊なフレームもある。 Minibuffers and Framesを参照。)

ミニバッファ用のウィンドウは通常は1行だけです。 ウィンドウサイズを変更するコマンドで一時的に大きさを変えられますが、 ミニバッファから抜けると通常サイズに戻ります。 ミニバッファ用ウィンドウのサイズを恒久的に変更するには、 ミニバッファを使っていないときに、フレームの別のウィンドウにおいて ウィンドウサイズを変更するコマンドを使います。 ミニバッファだけを持つフレームの場合、 フレームのサイズを変更すればミニバッファのサイズを変更できます。

すでにミニバッファが活性であるときにコマンドがミニバッファを使用することを 再帰ミニバッファと呼びます。 最初のミニバッファの名前は *Minibuf-0*です。 再帰ミニバッファは、名前の最後の数を増やして命名します。 (名前は空白で始まるため、通常のバッファの一覧には表示されない。) 再帰ミニバッファの中で、もっとも内側の(つまりもっとも再帰が深い)ものが 活性なミニバッファです。 これを単にミニバッファと呼びます。 変数enable-recursive-minibuffersを設定すれば、 再帰ミニバッファを許可したり禁止できます。 あるいは、コマンドシンボルにこの名前の属性を入れます (see Minibuffer Misc)。

他のバッファと同様に、ミニバッファは 複数のローカルキーマップ(see Keymaps)を使うことがあります。 これらには、さまざまな終了コマンドや補完コマンド(see Completion) が含まれます。


Node:Text from Minibuffer, Next:, Previous:Intro to Minibuffers, Up:Minibuffers

ミニバッファでのテキスト文字列の読み取り

多くの場合、テキストを文字列として読み取るためにミニバッファを使います。 Lispオブジェクトのテキスト表現を読み取るためにも使えます。 ミニバッファでの入力のもっとも基本的な関数は read-from-minibufferであり、どちらの目的にも使えます。

多くの場合、Lisp関数の途中でミニバッファの入力関数を呼ぶべきではありません。 そのかわりに、interactiveの指定で、 コマンドの引数を読み取る操作の一部として すべてのミニバッファ入力を行います。 See Defining Commands

read-from-minibuffer prompt-string &optional initial-contents keymap read hist default inherit-input-method Function
この関数は、ミニバッファから入力を得るもっとも汎用の方法である。 デフォルトでは、任意のテキストを受け取り文字列として返す。 しかし、readnil以外であれば、 readを用いてテキストを Lispオブジェクトへ変換する(see Input Functions)。

この関数がまず行うことは、ミニバッファを活性にし、 プロンプトprompt-stringとともに表示することである。 prompt-stringは文字列であること。 これで、ユーザーはミニバッファでテキストを編集できるようになる。

ユーザーがミニバッファを抜けるコマンドを打つと、 read-from-minibufferは ミニバッファ内のテキストから戻り値を構築する。 通常、当該テキストを含む文字列を返す。 しかし、readnil以外であると、 read-from-minibufferはテキストを読み取った結果である Lispオブジェクトを評価せずに返す。 (読み取りについてはsee Input Functions。)

引数defaultは、履歴コマンドで使うデフォルト値を指定する。 これは文字列かnilであること。 readnil以外である場合、 ユーザーの入力が空であるときには、 readへの入力としてもdefaultを用いる。 しかし、(readnilである)通常の場合、 ユーザーの入力が空のとき、read-from-minibufferdefaultを返さずに空文字列""を返す。 この意味において、この関数は本章の他のミニバッファ用入力関数と異なる。

keymapnil以外であると、 ミニバッファのローカルキーマップとして用いる。 keymapを省略したりnilであると、 minibuffer-local-mapの値をキーマップとして用いる。 キーマップを指定することは、 補完などのさまざまな応用向けにミニバッファをカスタマイズする もっとも重要な方法である。

引数histは、ミニバッファでの入力を保存し履歴コマンドを使用可能に するために用いる履歴リスト変数を指定する。 デフォルトはminibuffer-historyである。 see Minibuffer History

変数minibuffer-allow-text-propertiesnil以外であると、 返される文字列には、ミニバッファで指定されたテキスト属性が含まれる。 さもなければ、値を返すときにすべてのテキスト属性を取り除く。

引数inherit-input-methodnil以外であると、 ミニバッファに入るまえにどのバッファにいたかに関わらず、 そのバッファから現在の入力方式(see Input Methods)と enable-multibyte-characters(see Text Representations)の設定を 継承する。

initial-contentsが文字列であれば、 read-from-minibufferは、 ユーザーがテキスト編集を始めるまえに、 この文字列をミニバッファに挿入しその末尾にポイントを置く。 この文字列を初期内容とするミニバッファが現れる。

あるいは、initial-contentsは、 (string . position)という形式のコンスセルでもよい。 これは、文字列stringをミニバッファに挿入し、 ポイントは末尾にではなく 先頭からposition番目の文字に置くことを意味する。

使用上の注意: 引数initial-contentsdefaultは、 多かれ少なかれ同じことを行う代替方法を提供する。 read-from-minibufferの1つの呼び出しにおいて、 両者の機能を同時に使うことに意味はない。 一般には、defaultを使うことを勧める。 というのは、ユーザーがデフォルト値を望む場合にはデフォルト値を挿入でき、 それ以外の場合にはデフォルト値を削除しなくてもよいからである。

read-string prompt &optional initial history default inherit-input-method Function
この関数はミニバッファから文字列を読み取り、それを返す。 引数promptinitialは、 read-from-minibufferと同様に使われる。 使用するキーマップはminibuffer-local-mapである。

省略可能な引数historyは、nil以外であると、 履歴リストと(省略可能な)リスト内での初期位置を指定する。 省略可能な引数defaultは、 ユーザー入力が空の場合に返されるデフォルト値であり、文字列であること。 省略可能な引数inherit-input-methodは、 カレントバッファの入力方式を継承するかどうかを指定する。

この関数は関数read-from-minibufferの インターフェイスを単純化したものである。

(read-string prompt initial history default inherit)
==
(let ((value
       (read-from-minibuffer prompt initial nil nil
                             history default inherit)))
  (if (equal value "")
      default
    value))

minibuffer-allow-text-properties Variable
この変数がnilであると、 read-from-minibufferはミニバッファで指定されたすべての テキスト属性を返すまえに取り除く。 すべてのミニバッファがread-from-minibufferを使うので、 この変数はすべてのミニバッファ入力に適用される。

この変数の値に関わらず、 補完関数は無条件にテキスト属性を廃棄することに注意。

minibuffer-local-map Variable
ミニバッファから読み取るときのデフォルトのローカルキーマップ。 デフォルトでは、以下のバインディングである。
C-j
exit-minibuffer
<RET>
exit-minibuffer
C-g
abort-recursive-edit
M-n
next-history-element
M-p
previous-history-element
M-r
next-matching-history-element
M-s
previous-matching-history-element

read-no-blanks-input prompt &optional initial inherit-input-method Function
この関数はミニバッファから文字列を読み取るが、 入力には白文字を許さず、白文字は入力を終らせる。 引数promptinitialinherit-input-methodは、 read-from-minibufferと同様に使われる。

これは関数read-from-minibufferの インターフェイスを単純化したものであり、 引数keymapとしてminibuffer-local-ns-mapの値を渡す。 キーマップminibuffer-local-ns-mapでは C-qを再バインドしないため、 クォートすれば空白を文字列に含めることができる

(read-no-blanks-input prompt initial)
==
(read-from-minibuffer prompt initial minibuffer-local-ns-map)

minibuffer-local-ns-map Variable
この組み込み変数は、関数read-no-blanks-inputが ミニバッファ用のローカルキーマップとして使うキーマップである。 デフォルトでは、minibuffer-local-mapのバインディングに加えて 以下のバインディングである。
<SPC>
exit-minibuffer
<TAB>
exit-minibuffer
?
self-insert-and-exit


Node:Object from Minibuffer, Next:, Previous:Text from Minibuffer, Up:Minibuffers

ミニバッファでのLispオブジェクトの読み取り

本節では、ミニバッファでLispオブジェクトを読み取る関数について述べます。

read-minibuffer prompt &optional initial Function
この関数はミニバッファを用いてLispオブジェクトを読み取り、 それを評価せずに返す。 引数promptinitialは、 read-from-minibufferと同様に使われる。

これは関数read-from-minibufferの インターフェイスを単純化したものである。

(read-minibuffer prompt initial)
==
(read-from-minibuffer prompt initial nil t)

初期入力として文字列"(testing)"を与えた例を示す。

(read-minibuffer
 "Enter an expression: " (format "%s" '(testing)))

;; 以下のようにミニバッファが表示される

---------- Buffer: Minibuffer ----------
Enter an expression: (testing)-!-
---------- Buffer: Minibuffer ----------

デフォルトとして初期入力を使うには、ユーザーはただちに<RET>を打てばよい。 あるいは、入力を編集する。

eval-minibuffer prompt &optional initial Function
この関数はミニバッファを用いてLisp式を読み取り、 それを評価してその結果を返す。 引数promptinitialは、 read-from-minibufferと同様に使われる。

この関数はread-from-minibufferの インターフェイスを単純化したものである。

(eval-minibuffer prompt initial)
==
(eval (read-minibuffer prompt initial))

edit-and-eval-command prompt form Function
この関数はミニバッファを用いてLisp式を読み取り、それを評価する。 このコマンドとeval-minibufferとの違いは、 初期フォームformを省略できないことであり、 このフォームをテキスト文字列としではなく表示表現に 変換するLispオブジェクトとして扱うことである。 prin1を用いて表示するので、 これが文字列であると初期テキストにはダブルクォート文字(")が現れる。 see Output Functions

edit-and-eval-commandはまず、promptをプロンプトとして ミニバッファを活性にする。 続いて、ミニバッファにformの表示表現を挿入し、ユーザーに編集させる。 ユーザーがミニバッファから抜けると、 編集後のテキストをreadで読み取り評価する。 評価結果がedit-and-eval-commandの値になる。

以下の例では、すでに正しいフォームである 初期テキストの式をユーザーに提示する。

(edit-and-eval-command "Please edit: " '(forward-word 1))

;; 上の式を評価後には、ミニバッファは以下のようになる

---------- Buffer: Minibuffer ----------
Please edit: (forward-word 1)-!-
---------- Buffer: Minibuffer ----------

ただちに<RET>を打つと、 ミニバッファから抜けて式を評価するので、 ポイントを1単語分先へ進めることになる。 この例では、edit-and-eval-commandnilを返す。


Node:Minibuffer History, Next:, Previous:Object from Minibuffer, Up:Minibuffers

ミニバッファの履歴

ミニバッファ履歴リスト(minibuffer history list)は ミニバッファでの以前の入力を記録し、 ユーザーがそれらを手軽に再利用できるようにします。 履歴リストは実際にはシンボルでありリストではありません。 最新のものが先頭にある(以前の入力の)文字列のリストを値とする変数です。

異なる種類の入力に用いる多くの別々の履歴リストがあります。 ミニバッファを利用するたびに適した履歴リストを指定するのは、 Lispプログラマの責任です。

基本的なミニバッファ入力関数 read-from-minibuffercompleting-readの両者は、 読者が指定する履歴リストを省略可能な引数histとして受け付けます。 指定可能な値はつぎのとおりです。

variable
変数variable(シンボル)を履歴リストとして用いる。
(variable . startpos)
変数variable(シンボル)を履歴リストとして用い、 初期履歴位置をstartpos (履歴リストの最新要素を0とする整数)と仮定する。

startposを指定した場合、整合性を保つために、 履歴リストの当該要素をミニバッファの初期内容にも指定すること。

histを指定しなければ、 デフォルトの履歴リストminibuffer-historyを用いる。 その他の標準的な履歴リストについては以下を参照。 読者が独自の履歴リスト変数を作成してもよい。 初めて使用するまえに単にnilで初期化しておく。

read-from-minibuffercompleting-readの両者は 履歴リストに新たな要素を自動的に追加し、 リスト上の要素を再利用するためのコマンドをユーザーに提供する。 履歴リストを使うために読者のプログラムで行うべきことは、 履歴リストを初期化し必要なときにその名前を入力関数に渡すだけである。 ミニバッファ入力関数が履歴リストを使用していないときには、 履歴リストを変更しても安全である。

標準的なミニバッファ履歴リスト変数を以下にあげておく。

minibuffer-history Variable
ミニバッファの履歴入力用のデフォルトの履歴リスト。

query-replace-history Variable
query-replace(および同様のコマンド)の引数用の履歴リスト。

file-name-history Variable
ファイル名引数用の履歴リスト。

buffer-name-history Variable
バッファ名引数用の履歴リスト。

regexp-history Variable
正規表現引数用の履歴リスト。

extended-command-history Variable
拡張コマンド名である引数用の履歴リスト。

shell-command-history Variable
シェルコマンドである引数用の履歴リスト。

read-expression-history Variable
Lisp式として評価する引数用の履歴リスト。


Node:Completion, Next:, Previous:Minibuffer History, Up:Minibuffers

補完

補完(completion)とは、 名前の省略から始まる名前の残り部分を補充する機能です。 ユーザー入力を正しい名前のリストと比較し、 すでにユーザーが入力したものに名前が どの程度一致するかを決定することで補完します。 たとえば、C-x bswitch-to-buffer)と打って、 切り替えたいバッファ名の始めの数文字を打って <TAB>(minibuffer-complete)を打つと、 Emacsは可能な限りその名前を補充します。

Emacsの標準のコマンドは、 シンボル、ファイル、バッファ、プロセスの名前を補完できます。 本節の関数を用いれば、その他の種類の名前の補完も実装できます。

関数try-completionは補完のための基本関数です。 与えられた文字列の集まりから 初期文字列にもっとも適合する最長のものを返します。

関数completing-readは補完のための上位レベルの インターフェイスを提供します。 completing-readの呼び出しには、 正しい名前のリストを決定する方法を指定します。 この関数は、補完に有用なコマンドを数個のキーにバインドした ローカルキーマップを使うミニバッファを活性にします。 その他の関数は、特定の種類の名前を補完して読み取るために 単純化したインターフェイスを提供します。


Node:Basic Completion, Next:, Up:Completion

基本補完関数

2つの関数try-completionall-completionsは、 それ自身ではミニバッファを使いません。 これらについて本章で述べるのは、 ミニバッファを使う上位レベルの補完機能と同列にしておくためです。

try-completion string collection &optional predicate Function
この関数は、collectionにあるstringを補完する 共通の最長な部分文字列を返す。 collectionの値は、連想リスト、オブジェクト配列、あるいは、 実質的な文字列の集まりを返す関数(下記参照)であること。

補完では、collectionで指定した各補完候補と stringを比較する。 補完候補の先頭部分がstringに等しければ、 その補完候補は一致するという。 一致する補完候補がなければ、try-completionnilを返す。 たった1つの補完候補に一致し、かつ、完全に一致すれば、 try-completiontを返す。 さもなければ、一致する補完候補すべてに共通する最長の文字列を値とする。

collectionが連想リスト(see Association Lists)であると、 連想リストの要素のCAR群が補完候補の集まりになる。

collectionがオブジェクト配列(see Creating Symbols)であると、 オブジェクト配列内のすべてのシンボルの名前が補完候補の集まりになる。 グローバル変数obarrayは、インターンしたすべてのLispシンボルの 名前を収めたオブジェクト配列を保持する。

新たなオブジェクト配列を作成する唯一の正しい方法は、 まず空で作成してからinternで1つ1つシンボルを追加することである ことに注意。 なお、1つのシンボルを複数のオブジェクト配列にはインターンできない。

引数predicatenil以外である場合、 それは1引数の関数であること。 その関数は一致する補完候補の検査に使われ、 predicatenil以外を返す場合にのみ一致した候補とみなす。 predicateに渡す引数は、 (CARが文字列である)連想リストのコンスセルであるか、 オブジェクト配列からの(シンボル名ではない)シンボルである。

collectionには、関数であるシンボルを使うこともできる。 その関数には補完処理を完遂する責任がある。 try-completionはその関数が返したものを返す。 その関数は3引数、つまり、 stringpredicatenilで呼ばれる。 (第3引数がある理由は、 all-completionsでも同じ関数を使い、 いずれの場合にも適切に動作できるようにするため。) see Programmed Completion

以下の最初の例では、 文字列fooは連想リストの3つのCARに一致する。 すべての一致はfoobaで始まるため、これが結果になる。 2番目の例では、たった1つの一致があり、しかも、完全に一致するので、 値はtである。

(try-completion
 "foo"
 '(("foobar1" 1) ("barfoo" 2) ("foobaz" 3) ("foobar2" 4)))
     => "fooba"

(try-completion "foo" '(("barfoo" 2) ("foo" 3)))
     => t

つぎの例では、forwで始まるシンボルが多数あり、 それらはすべて単語forwardで始まる。 ほとんどのシンボルでは、これに-が続くが、 すべてがそうではないので、forwardまでしか補完できない。

(try-completion "forw" obarray)
     => "forward"

最後の例は、述語testの検査に通るのは3つの一致のうち2つだけである (文字列foobazは短すぎる)。 両者は文字列foobarで始まる。

(defun test (s)
  (> (length (car s)) 6))
     => test
(try-completion
 "foo"
 '(("foobar1" 1) ("barfoo" 2) ("foobaz" 3) ("foobar2" 4))
 'test)
     => "foobar"

all-completions string collection &optional predicate nospace Function
この関数はstringの補完すべてのリストを返す。 この関数の引数は、try-completionのものと同じである。

collectionが関数であると、 stringpredicatetの3引数で呼ばれる。 all-completionsはこの関数が返す値を返す。 see Programmed Completion

nospacenil以外であると、 stringが空白で始まらない限り、空白で始まる補完は無視する。

try-completionの例に示した関数testを用いた例を示す。

(defun test (s)
  (> (length (car s)) 6))
     => test

(all-completions
 "foo"
 '(("foobar1" 1) ("barfoo" 2) ("foobaz" 3) ("foobar2" 4))
 'test)
     => ("foobar1" "foobar2")

completion-ignore-case Variable
この変数の値がnil以外であると、 Emacsは補完において大文字小文字を区別しない。


Node:Minibuffer Completion, Next:, Previous:Basic Completion, Up:Completion

補完とミニバッファ

本節ではミニバッファからの補完による読み取り用の 基本インターフェイスについて述べます。

completing-read prompt collection &optional predicate require-match initial hist default inherit-input-method Function
この関数は、与えられた補完でユーザーを補佐して ミニバッファで文字列を読み取る。 文字列であるプロンプトpromptでミニバッファを活性にする。

実際の補完は、collectionpredicateを 関数try-completionに渡して行う。 これは、補完を用いるローカルキーマップでバインドされたコマンドで行われる。

require-matchnilであると、 ミニバッファでの入力に関わらず ミニバッファから抜けるコマンドは動作する。 require-matchtであると、 ミニバッファでの入力がcollectionの1つの要素に補完できない限り、 ミニバッファから抜ける通常のコマンドは動作しない。 require-matchnilでもtでもないと、 ミニバッファでの入力がcollectionの1つの要素に一致しない限り、 ミニバッファから抜けるコマンドは動作しない。

しかし、require-matchの値に関わらず、 空の入力はつねに許される。 その場合、completing-readdefaultを返す。 defaultの値は(nilでなければ)履歴コマンドを介しても ユーザーが使える。

ミニバッファが空の状態で<RET>を打つと、 ユーザーは空入力で抜けることができる。 そうすると、completing-read""を返す。 これにより、読み取った値に対してコマンドが使うどんなデフォルトでも指定できる。 require-matchの値、および、collectionに空文字列が 含まれるかどうかに関わらず、ユーザーはこのようにして<RET>で戻れる。

関数completing-readread-minibufferを呼び出すことで動作する。 require-matchnilであると、 キーマップとしてminibuffer-local-completion-mapを使い、 nil以外であるとminibuffer-local-must-match-mapを使う。 see Completion Commands

引数histは、入力を保存しミニバッファ履歴コマンドで 使う履歴リスト変数を指定する。 デフォルトはminibuffer-historyである。 see Minibuffer History

initialnil以外であると、 completing-readはこれを入力の一部としてミニバッファに挿入する。 これにより、ユーザーは補完コマンドとともに入力を編集できる。 ほとんどの場合、initialではなくdefaultを使うことを勧める。

引数inherit-input-methodnil以外であると、 ミニバッファに入るまえのカレントバッファがなんであれ、 カレントバッファから現在の入力方式(see Input Methods)と enable-multibyte-characters(see Text Representations) の設定を継承する。

組み込み変数completion-ignore-casenil以外であると、 大文字小文字を区別せずに候補に対して入力を比較する。 see Basic Completion

completing-readを用いた例を以下に示す。

(completing-read
 "Complete a foo: "
 '(("foobar1" 1) ("barfoo" 2) ("foobaz" 3) ("foobar2" 4))
 nil t "fo")

;; 上の式を評価するとミニバッファはつぎのようになる

---------- Buffer: Minibuffer ----------
Complete a foo: fo-!-
---------- Buffer: Minibuffer ----------

ユーザーが<DEL> <DEL> b <RET>を打つと、 completing-readbarfooを返す。

関数completing-readは、 補完を実際に行うコマンドに情報を渡すために3つの変数を束縛する。 3つの変数とは、minibuffer-completion-tableminibuffer-completion-predicateminibuffer-completion-confirmである。 これらについて詳しくは、Completion Commandsを参照。


Node:Completion Commands, Next:, Previous:Minibuffer Completion, Up:Completion

補完を行うミニバッファコマンド

本節では、補完を行うためにミニバッファで用いられるキーマップ、 コマンド、ユーザーオプションについて述べます。

minibuffer-local-completion-map Variable
completing-readは、 補完候補の1つと完全に一致しなくてもよい場合に ローカルキーマップとしてこの値を使う。 デフォルトでは、このキーマップのバインディングはつぎのとおり。
?
minibuffer-completion-help
<SPC>
minibuffer-complete-word
<TAB>
minibuffer-complete

他の文字はminibuffer-local-map (see Text from Minibuffer)と同様にバインドされる。

minibuffer-local-must-match-map Variable
completing-readは、 補完候補の1つと完全に一致する必要がある場合に ローカルキーマップとしてこの値を使う。 そのため、ミニバッファから無条件に抜けるコマンドexit-minibufferに バインドしたキーはない。 デフォルトでは、このキーマップのバインディングはつぎのとおり。
?
minibuffer-completion-help
<SPC>
minibuffer-complete-word
<TAB>
minibuffer-complete
C-j
minibuffer-complete-and-exit
<RET>
minibuffer-complete-and-exit

他の文字はminibuffer-local-mapと同様にバインドされる。

minibuffer-completion-table Variable
この変数の値は、ミニバッファでの補完に用いられる 連想リストやオブジェクト配列である。 これは、completing-readtry-completionに渡すものを 保持したグローバル変数である。 minibuffer-complete-wordなどの ミニバッファ補完コマンドで使用される。

minibuffer-completion-predicate Variable
この変数の値は、completing-readtry-completionへ渡す述語である。 この変数は、他のミニバッファ補完関数でも使われる。

minibuffer-complete-word コマンド
この関数は、ミニバッファの内容を多くても1単語分補完する。 ミニバッファの内容に対応する補完がたった1つであっても、 単語構成文字ではない文字以降は補充しない。 see Syntax Tables

minibuffer-complete コマンド
この関数は、ミニバッファの内容を可能な限り補完する。

minibuffer-complete-and-exit コマンド
この関数は、確認が必要でないとき、つまり、 minibuffer-completion-confirmnilであるときには、 ミニバッファの内容を補完後に抜ける。 確認が必要であるときには、 このコマンドをただちに繰り返すことで確認をとる。 このコマンドは、連続して2回呼ばれると、 確認しないようにプログラムしてある。

minibuffer-completion-confirm Variable
この変数の値がnil以外の場合、 Emacsはミニバッファから抜けるまえに補完を確認してくる。 関数minibuffer-complete-and-exitは、 抜けるまえにこの変数の値を検査する。

minibuffer-completion-help コマンド
この関数は、ミニバッファの現在の内容に対する補完のリストを作る。 引数collectionとして変数minibuffer-completion-tableの値を、 引数predicateとしてminibuffer-completion-predicateの値を 用いてall-completionsを呼び出すことで動作する。 補完のリストは、*Completions*という名前のバッファに テキストとして表示される。

display-completion-list completions Function
この関数は、通常はバッファであるストリームstandard-outputcompletionsを表示する。 (ストリームについては詳しくはsee Read and Print。) 引数completionsは、普通は、all-completionsが 返した補完のリストであるが、そうでなくてもよい。 各要素は、シンボルか文字列であり、その場合、そのまま表示される。 各要素が2つの文字列から成るリストである場合、 文字列を連結したものを表示する。

この関数は、minibuffer-completion-helpから呼ばれる。 以下のように、with-output-to-temp-bufferとともに 用いるのがもっとも一般的である。

(with-output-to-temp-buffer "*Completions*"
  (display-completion-list
    (all-completions (buffer-string) my-alist)))

completion-auto-help User Option
この変数がnil以外であると、 つぎの補充文字が一意に決まらない場合には、 自動的に補完のリストを表示する。


Node:High-Level Completion, Next:, Previous:Completion Commands, Up:Completion

高レベルの補完関数

本節では、特定の種類の名前を補完付きで読み取るための 高レベルの便利な関数について述べます。

多くの場合、これらの関数をLisp関数の途中では呼び出さないでください。 可能な場合には、interactiveの指定で、 コマンドの引数を読み取る操作の一部としてすべてのミニバッファ入力を 行ってください。 See Defining Commands

read-buffer prompt &optional default existing Function
この関数はバッファ名を読み取り、文字列として返す。 引数defaultはデフォルトの名前を表し、 ユーザーがミニバッファから空で抜け出したときに返される値である。 nil以外であるときには、文字列かバッファであること。 これはプロンプトとして現れるが、 ミニバッファには初期入力として挿入されない。

existingnil以外であると、 指定した名前は既存のバッファ名であること。 テキストが正しくないとミニバッファから抜ける通常のコマンドは動作せず、 <RET>は正しい名前を探すため補完を行う。 (しかし、defaultが正しいかどうかは検査しない。 ユーザーがミニバッファを空で抜ければ、 なんであろうとdefaultが返される。)

以下の例では、ユーザーはminibuffer.tと入力してから<RET>を打つ。 引数existingtであり、 入力した名前で始まる唯一のバッファ名はminibuffer.texiであるので、 この名前が値になる。

(read-buffer "Buffer name? " "foo" t)
;; 上の式を評価すると、ミニバッファは空で
;; つぎのようなプロンプトが表示される

---------- Buffer: Minibuffer ----------
Buffer name? (default foo) -!-
---------- Buffer: Minibuffer ----------

;; ユーザーはminibuffer.t <RET>と打つ
     => "minibuffer.texi"

read-buffer-function Variable
この変数は、バッファ名の読み取り方を指定する。 たとえば、この変数にiswitchb-read-bufferを設定すると、 バッファ名を読み取るためにread-bufferを呼び出す すべてのEmacsコマンドは、 バッファ名を読むためにパッケージiswitchbを使うようになる。

read-command prompt &optional default Function
この関数はコマンド名を読み取り、Lispシンボルとして返す。 引数promptは、read-from-minibufferと同様に使われる。 なんであってもcommandptを返せばコマンドであり、 commandptを返すシンボルはコマンド名であることに注意。 see Interactive Call

引数defaultは、ユーザー入力が空だった場合に返したい値を指定する。 これは、シンボルか文字列であること。 文字列であると、read-commandは、これを返すまえにインターンする。 defaultnilであると、デフォルトを指定しないことを意味し、 ユーザー入力が空であると戻り値はnilである。

(read-command "Command name? ")

;; 上の式を評価後には、ミニバッファは空で
;; つぎのようなプロンプトが表示される

---------- Buffer: Minibuffer ----------
Command name?
---------- Buffer: Minibuffer ----------

ユーザーがforward-c <RET>と打つと、 この関数はforward-charを返す。

関数read-commandcompleting-readのインターフェイスを 単純化したものである。 既存のLispシンボルの集まりから補完するために変数obarrayを使い、 コマンド名のみを対象とするために述語commandpを使う。

(read-command prompt)
==
(intern (completing-read prompt obarray
                         'commandp t nil))

read-variable prompt &optional default Function
この関数はユーザー変数の名前を読み取り、シンボルとして返す。

引数defaultは、ユーザー入力が空だった場合に返したい値を指定する。 これは、シンボルか文字列であること。 文字列であると、read-variableは、これを返すまえにインターンする。 defaultnilであると、デフォルトを指定しないことを意味し、 ユーザー入力が空であると戻り値はnilである。

(read-variable "Variable name? ")

;; 上の式を評価後には、ミニバッファは空で
;; つぎのようなプロンプトが表示される

---------- Buffer: Minibuffer ----------
Variable name? -!-
---------- Buffer: Minibuffer ----------

ユーザーがfill-p <RET>と打つと、 read-variablefill-prefixを返す。

この関数はread-commandに似ているが、 commandpのかわりに述語user-variable-pを使う。

(read-variable prompt)
==
(intern
 (completing-read prompt obarray
                  'user-variable-p t nil))
User-Chosen Coding Systemsの関数read-coding-systemread-non-nil-coding-systemも参照してください。


Node:Reading File Names, Next:, Previous:High-Level Completion, Up:Completion

ファイル名の読み取り

ここでは、ファイル名を読み取るように設計された高レベルの 別の補完関数について述べます。 デフォルトディレクトリの自動挿入などの特別な機能を提供します。

read-file-name prompt &optional directory default existing initial Function
この関数は、promptをプロンプトとし、 補完を行ってミニバッファでファイル名を読み取る。 defaultnil以外であると、 ユーザーが単に<RET>を打つと、この関数はdefaultを返す。 defaultが正しいかどうかは検査せず、 それがなんであれ、ユーザーがミニバッファを空で抜けるとそれを返す。

existingnil以外であると、 ユーザーは既存ファイルの名前を指定する必要がある。 <RET>は、可能ならば正しい名前に補完を行うが、 それが正しくない場合には抜けない。 existingの値がnilでもtでもないと、 <RET>は補完後の確認を必要とする。 existingnilであると、 存在しないファイルの名前も許す。

引数directoryは、相対ファイル名の補完に用いるディレクトリを指定する。 insert-default-directorynil以外であると、 初期入力としてdirectoryをミニバッファに挿入する。 カレントバッファのdefault-directoryの値がデフォルトになる。

initialを指定すると、 (directoryがあればそれを挿入後に)バッファに 挿入される初期ファイル名になる。 この場合、ポイントはinitialの先頭に置かれる。 initialのデフォルトはnilであり、 いかなるファイル名も挿入しない。 initialの動作を見るには、コマンドC-x C-vを試してほしい。 注意: ほとんどの場合、initialではなくdefaultを使うことを勧める。

例を示す。

(read-file-name "The file is ")

;; 上の式を評価後には、ミニバッファはつぎのようになる

---------- Buffer: Minibuffer ----------
The file is /gp/gnu/elisp/-!-
---------- Buffer: Minibuffer ----------

manual <TAB>を打つと、つぎのようになる。

---------- Buffer: Minibuffer ----------
The file is /gp/gnu/elisp/manual.texi-!-
---------- Buffer: Minibuffer ----------

ユーザーが<RET>と打つと、 read-file-nameは ファイル名を文字列"/gp/gnu/elisp/manual.texi"として返す。

insert-default-directory User Option
この変数はread-file-nameが使う。 その値は、read-file-nameが、 デフォルトディレクトリの名前と(あれば)初期ファイル名を ミニバッファに入れて動作を開始するかどうかを制御する。 この変数の値がnilであると、 read-file-nameは (引数initialで初期入力を指定しない限り) ミニバッファに初期入力を入れない。 その場合でも、相対ファイル名の補完には デフォルトディレクトリを使うが表示はしない。

例を示す。

;; デフォルトディレクトリを入れて始める
(let ((insert-default-directory t))
  (read-file-name "The file is "))

---------- Buffer: Minibuffer ----------
The file is ~lewis/manual/-!-
---------- Buffer: Minibuffer ----------

;; ミニバッファは空であり、プロンプトのみ
(let ((insert-default-directory nil))
  (read-file-name "The file is "))

---------- Buffer: Minibuffer ----------
The file is -!-
---------- Buffer: Minibuffer ----------


Node:Programmed Completion, Previous:Reading File Names, Up:Completion

プログラム補完

意図した補完候補を持った連想リストやオブジェクト配列を 作成することが困難な場合もあります。 そのような場合、与えられた文字列に対する補完を計算する 独自の関数を与えることができます。 これをプログラム補完(programmed completion)と呼びます。

この機能を使うには、completing-readの引数collectionに 関数定義を持つシンボルを渡します。 関数completing-readは、 try-completionall-completionsに 読者の補完関数を渡すようにして、読者の関数にすべてを任せます。

補完関数はつぎの3つの引数を受け取ります。

3つの操作型に対応してフラグの値は3つあります。

補完関数collectionには関数シンボルに加えて、 ラムダ式(関数であるリスト)も許すほうが 一貫性があって見通しがよいはずですが、それは不可能です。 リストには補完候補表としての意味がすでにあり、連想リストがそれです。 関数としての可能性もある通常の連想リストの扱いに失敗するようでは、 信頼性がなくなります。 そのため、読者が補完に使用したい関数は、 シンボルに入れておく必要があるのです。

Emacsは、ファイル名の補完にはプログラム補完を用います。 See File Name Completion


Node:Yes-or-No Queries, Next:, Previous:Completion, Up:Minibuffers

Yes/Noの問い合わせ

本節ではユーザーにyes/noを問い合わせるための関数について述べます。 関数y-or-n-pには、1文字で答えます。 誤った答えでも重大な問題に至らないような問い合わせに便利です。 yes-or-no-pには3文字か4文字で答える必要があるため、 より重要な問い合わせに適しています。

これらの関数がマウスを使って起動されたコマンドから呼ばれると、 より正確には、last-nonmenu-event(see Command Loop Info)が nilかリストであると、 関数は問い合わせのための対話ボックスやポップアップメニューを使います。 さもなければ、キーボード入力を使います。 呼び出しにおいてlast-nonmenu-eventに適切な値を束縛することで マウスかキーボード入力の使用を強制できます。

厳密にいえば、yes-or-no-pはミニバッファを使いますが、 y-or-n-pは使いません。 ですが、両者をここで説明しておきます。

y-or-n-p prompt Function
この関数はユーザーに問い合わせ、エコー領域で入力を待ちます。 ユーザーがyを打てばtを返し、 nを打てばnilを返します。 さらに、<SPC>を「y」、<DEL>を「n」ともみなします。 C-]C-gのように『中断』ともみなします。 というのは、問い合わせはミニバッファを使っているようにみえるので、 これから抜けるためにユーザーがC-]を使いそうだからである。 応答は1文字であり、<RET>で終える必要はない。 大文字と小文字は同じ意味である。

『問い合わせ』では、エコー領域にpromptを表示し、 文字列(y or n) が続きます。 入力が正しい応答(yn<SPC><DEL>、中断など)でないと、 関数はPlease answer y or n.を表示して 問い合わせるを繰り返す。

応答は編集できないので、この関数は実際にはミニバッファを使わない。 ミニバッファが使うのと同じ画面領域を使う エコー領域(see The Echo Area)を実際には使う。 問い合わせ中は、カーソルはエコー領域に移動する。

応答とその意味は、 たとえynであっても組み込まれているわけではない。 キーマップquery-replace-mapがそれらを指定する。 see Search and Replace

以下の例では、ユーザーはまずqを打つが、これは正しくない。 つぎのプロンプトに対して、ユーザーはyを打つ。

(y-or-n-p "Do you need a lift? ")

;; 上の式を評価後には、エコー領域には
;; つぎのプロンプトが表示される

---------- Echo area ----------
Do you need a lift? (y or n)
---------- Echo area ----------

;; ユーザーがqを打つと、つぎのようになる

---------- Echo area ----------
Please answer y or n.  Do you need a lift? (y or n)
---------- Echo area ----------

;; ユーザーが正しい応答を打つと
;; 問い合わせのうしろに表示される

---------- Echo area ----------
Do you need a lift? (y or n) y
---------- Echo area ----------

ここでは、エコー領域のメッセージを複数行示したが、 実際には、1度に1つのメッセージだけが表示される。

y-or-n-p-with-timeout prompt seconds default-value Function
y-or-n-pと同様だが、ユーザーがseconds秒以内に答えないと、 入力を待たずにdefault-valueを返す。 これにはタイマを使う。 Timersを参照。 引数secondsは整数でも浮動小数点でもよい。

yes-or-no-p prompt Function
この関数はユーザーに問い合わせ、ミニバッファでの入力を仮定する。 ユーザーがyesを入力するとtを返し、 noを入力するとnilを返す。 応答を終えるためにユーザーは<RET>を打つ必要がある。 大文字と小文字は同じ意味である。

yes-or-no-pは、まず、promptに続けて (yes or no) をエコー領域に表示する。 ユーザーは正しい応答の1つを入力する必要がある。 さもないと、この関数はPlease answer yes or no.を2秒ほど 表示してから問い合わせを繰り返す。

yes-or-no-py-or-n-pよりもユーザーの手間を必要とし、 より重要な決定に適している。

例を示す。

(yes-or-no-p "Do you really want to remove everything? ")

;; 上の式を評価後には、つぎのプロンプトが
;; 空のミニバッファとともに表示される

---------- Buffer: minibuffer ----------
Do you really want to remove everything? (yes or no)
---------- Buffer: minibuffer ----------

ユーザーは、まずy <RET>を打つが、 この関数は完全な単語yesを要求するので正しくない。 以下のプロンプトを少し時間をおいて表示する。

---------- Buffer: minibuffer ----------
Please answer yes or no.
Do you really want to remove everything? (yes or no)
---------- Buffer: minibuffer ----------


Node:Multiple Queries, Next:, Previous:Yes-or-No Queries, Up:Minibuffers

複数のY/Nの問い合わせ

各バッファについて『バッファを保存するか』などの 一連の単純な問い合わせをする場合には、 個々に問い合わせるかわりに map-y-or-n-pを用いてまとめて問い合わせるべきです。

map-y-or-n-p prompter actor list &optional help action-alist Function
この関数は、各問について1文字の応答をエコー領域から読み取ることで、 ユーザーに一連の問い合わせを行う。

listの値は、問い合わせ対象のオブジェクトを指定する。 オブジェクトのリストであるか、生成関数であること。 関数である場合、それは引数なしで呼ばれ、 つぎの問い合わせ対象のオブジェクトを返すか、 問い合わせの終了を意味するnilを返す。

引数prompterは、各問い合わせをどのように問うかを指定する。 prompterが文字列であると、問い合わせ文はつぎのように計算される。

(format prompter object)

ここで、objectは(listから得た) 問い合わせ対象のオブジェクトである。

文字列でなければ、prompterは 1引数(問い合わせ対象のオブジェクト)の関数であり、 問い合わせ文を返す。 値が文字列であれば、それがユーザーへの問い合わせ文になる。 関数は、(ユーザーに問い合わせずに) 当該オブジェクトを処理することを意味するtか、 (ユーザーに問い合わせずに)当該オブジェクトを無視することを意味する nilを返してもよい。

引数actorは、ユーザーの応答に対してどのように動作するかを指定する。 これは1引数の関数であり、ユーザーが「はい」と答えたオブジェクトで 呼ばれる。 引数は、つねにlistから得たオブジェクトである。

引数helpを指定する場合、つぎの形のリストであること。

(singular plural action)

ここで、 singularは操作対象のオブジェクトを 記述する単数形の名詞を含んだ文字列であり、 pluralは対応する複数形の名詞であり、 actionは動作を記述する他動詞であること。

helpを指定しないと、デフォルトは ("object" "objects" "act on")である。

各問い合わせでは、ユーザーは当該対象オブジェクトに対する操作に yYSPCで答える。 nN、<DEL>は、そのオブジェクトを無視する。 !はそのオブジェクトを含めて後続のものも処理する。 <ESC>やqは(後続のオブジェクトをすべて無視して)抜ける。 .(ピリオド)は現在の対象オブジェクトを処理してから抜ける。 C-hはヘルプメッセージを表示する。 これらは、query-replaceが受け付ける応答と同じである。 キーマップquery-replace-mapが、 query-replaceと同様に map-y-or-n-pに対する(応答の)意味を定義する。 Search and Replaceを参照。

action-alistを使って、 可能な応答とそれらの意味を追加指定することもできる。 これは、(char function help)の形の要素から成る 連想リストであり、それぞれが1つの追加応答を定義する。 この要素の中で、 charは(応答である)1つの文字、 functionは1引数(listからのオブジェクト)の関数、 helpは文字列である。

ユーザーがcharで答えると、 map-y-or-n-pfunctionを呼び出す。 これがnil以外を返せば、当該オブジェクトを『処理』したとみなして、 map-y-or-n-plistのつぎのオブジェクトに移る。 nilであると、同じオブジェクトについてプロンプトを繰り返す。

map-y-or-n-pがマウスを使って起動されたコマンドから呼ばれると、 より正確には、last-nonmenu-event(see Command Loop Info)が、 nilかリストであると、 関数は問い合わせのための対話ボックスやポップアップメニューを使う。 その場合、キーボード入力やエコー領域は使わない。 呼び出しにおいてlast-nonmenu-eventに適切な値を束縛することで マウスかキーボード入力の使用を強制できる。

map-y-or-n-pの戻り値は、処理したオブジェクトの個数である。


Node:Reading a Password, Next:, Previous:Multiple Queries, Up:Minibuffers

パスワードの読み取り

別のプログラムへ渡すパスワードを読み取るには、 関数read-passwdを使います。

read-passwd prompt &optional confirm default Function
この関数は、プロンプトpromptを表示してパスワードを読み取る。 ユーザーが入力するパスワードは表示せず、 そのかわりにパスワードの各文字ごとに.を表示する。

省略可能な引数confirmnil以外であると、 パスワードを2回読み取り、両者が同一である必要がある。 同一でないと、連続して2回同じパスワードを打つまで ユーザーは何度でも繰り返す必要がある。

省略可能な引数defaultは、ユーザーが空のパスワードを 入力したときに返すデフォルトのパスワードを指定する。 defaultnilであると、 read-passwdはそのような場面では空文字列を返す。


Node:Minibuffer Misc, Previous:Reading a Password, Up:Minibuffers

ミニバッファに関するその他

本節では、ミニバッファに関係する他の基本関数や変数について述べます。

exit-minibuffer コマンド
このコマンドは活性なミニバッファから抜ける。 通常、ミニバッファのローカルキーマップでキーにバインドされる。

self-insert-and-exit コマンド
このコマンドは(Command Loop Infolast-command-charにある) 最新のキーボード入力文字を活性なミニバッファに挿入してから抜ける。

previous-history-element n コマンド
このコマンドは、ミニバッファの内容を n番目まえの(古い)履歴要素の値で置き換える。

next-history-element n コマンド
このコマンドは、ミニバッファの内容を n番目先のより新しい履歴要素の値で置き換える。

previous-matching-history-element pattern コマンド
このコマンドは、ミニバッファの内容を pattern(正規表現)に一致するまえの(古い)履歴要素の値で置き換える。

next-matching-history-element pattern コマンド
このコマンドは、ミニバッファの内容を pattern(正規表現)に一致するつぎの(新しい)履歴要素の値で置き換える。

minibuffer-prompt Function
この関数は、現在活性なミニバッファのプロンプト文字列を返す。 活性なミニバッファがなければnilを返す。

minibuffer-prompt-width Function
この関数は、現在活性なミニバッファのプロンプト文字列の表示幅を返す。 活性なミニバッファがなければ0を返す。

minibuffer-setup-hook Variable
ミニバッファに入るたびに実行されるノーマルフック。 see Hooks

minibuffer-exit-hook Variable
ミニバッファから抜けるたびに実行されるノーマルフック。 see Hooks

minibuffer-help-form Variable
この変数の現在値は、 ミニバッファの内側でhelp-formのローカルな束縛に使われる。 (see Help Functions)。

active-minibuffer-window Function
この関数は、現在活性なミニバッファのウィンドウを返す。 あるいは、活性なミニバッファがなければnilを返す。

minibuffer-window &optional frame Function
この関数は、フレームframeで使われるミニバッファ用ウィンドウを返す。 framenilであると、カレントフレームを意味する。 フレームで使うミニバッファ用ウィンドウは、 そのフレームの一部である必要はない。 ミニバッファを持たないフレームでは、 他のフレームのミニバッファ用ウィンドウを使う。

window-minibuffer-p window Function
この関数は、windowがミニバッファ用ウィンドウであると nil以外を返す。

与えられたウィンドウがミニバッファ用であるかどうかを調べるために、 (minibuffer-window)の戻り値と比較するのは正しくありません。 というのは、フレームが複数個あると 複数のミニバッファ用ウィンドウがあるからです。

minibuffer-window-active-p window Function
この関数は、ミニバッファ用ウィンドウwindowが活性であると nil以外を返す。

minibuffer-scroll-window Variable
この変数の値がnil以外であると、 値はウィンドウオブジェクトであること。 ミニバッファで関数scroll-other-windowが呼ばれると、 scroll-other-windowはこのウィンドウをスクロールする。

最後に、再帰ミニバッファ(see Recursive Editing)を扱う 関数と変数について述べます。

minibuffer-depth Function
この関数は、活性なミニバッファの現在の深さを非負整数で返す。 活性なミニバッファがなければ0を返す。

enable-recursive-minibuffers User Option
この変数がnil以外であると、 ミニバッファ用ウィンドウが活性であっても、 (find-fileなどの)ミニバッファを使うコマンドを起動できる。 そのような起動では、新たなミニバッファに対する再帰編集レベルが作られる。 内側の(深い)ミニバッファを編集中には、 外側の(浅い)レベルのミニバッファは見えない。

この変数がnilであると、 ミニバッファ用ウィンドウが活性なときには、 別のウィンドウに切り替えたとしてもミニバッファコマンドは使えない。

コマンド名にnil以外の 属性enable-recursive-minibuffersがあると、 当該コマンドをミニバッファから起動したときでさえ、 当該コマンドはミニバッファを使って引数を読み取れます。 ミニバッファコマンドnext-matching-history-element (ミニバッファでは通常M-s)は、この機能を使っています。


Node:Command Loop, Next:, Previous:Minibuffers, Up:Top

コマンドループ

読者がEmacsを起動すると、Emacsはほぼただちにエディタコマンドループ (editor command loop)に入ります。 このループは、キー列を読み取り、それらの定義を実行し、結果を表示します。 本章では、これがどのように行われるのか、および、 Lispプログラムからこれを行うためのサブルーティンについて述べます。


Node:Command Overview, Next:, Up:Command Loop

コマンドループの概要

コマンドループがまず始めに行うことはキー列、 つまり、コマンドへ変換されるイベント列を読むことです。 これには関数read-key-sequenceを呼び出します。 読者のLispコードでもこの関数を呼び出せます(see Key Sequence Input)。 Lispプログラムでは、read-event(see Reading One Event)で 低レベルの入力を行ったり、 discard-input(see Event Input Misc)で 処理待ち中の入力を破棄できます。

キー列は現在活性なキーマップを介してコマンドに変換されます。 この処理方法についてはSee Key Lookup。 この結果は、キーボードマクロであるか、 対話的に呼び出し可能な関数であるはずです。 キーがM-xであると、別のコマンドの名前を読み取り、 そのコマンドを呼び出します。 これはコマンドexecute-extended-command(see Interactive Call)で 処理されます。

コマンドを実行するには、まず、その引数を読む必要があります。 これは、command-execute(see Interactive Call)を呼び出して 行います。 Lispで書かれたコマンドでは、 interactive指定が引数の読み方を指示します。 前置引数(see Prefix Command Arguments)を使ったり、 プロンプトを表示してミニバッファ(see Minibuffers)から読みます。 たとえば、コマンドfind-fileには、 ミニバッファからファイル名を読むことを指示した interactive指定があります。 コマンドの関数本体ではミニバッファを使いません。 このコマンドをLispコードから関数として呼び出す場合、 通常のLisp関数の引数としてファイル名文字列を指定する必要があります。

コマンドが文字列やベクトル(つまり、キーボードマクロ)である場合、 execute-kbd-macroを用いてそれらを実行します。 読者自身がこの関数を呼び出してもかまいません(see Keyboard Macros)。

動作中のコマンドの実行を止めるには、C-gを打ちます。 この文字は中断(quitting)を引き起こします(see Quitting)。

pre-command-hook Variable
エディタコマンドループは、各コマンドのまえにこのノーマルフックを実行する。 その際、this-commandにはこれから実行するコマンドが保持され、 last-commandには直前のコマンドがある。 see Hooks

post-command-hook Variable
エディタコマンドループは、 (中断やエラーのために完了しなかったコマンドを含めて) 各コマンドのあとにこのノーマルフックを実行する。 初めてコマンドループに入ったときにも実行する。 その際、this-commandには実行し終えたばかりのコマンドがあり、 last-commandにはその前のコマンドがある。 see Hooks

pre-command-hookpost-command-hookの実行中は、 中断を禁止します。 これらのフックの1つを実行中にエラーが起きると、 エラーの無限ループを防ぐために、 フックの実行を終了しフック変数をnilにします。


Node:Defining Commands, Next:, Previous:Command Overview, Up:Command Loop

コマンドの定義

Lisp関数の本体に、スペシャルフォームinteractiveを呼び出す フォームがトップレベルにあると、Lisp関数はコマンドになります。 このフォームは実際に呼び出されてもなにもしませんが、 このフォームがあることで、対話的に呼び出せることを表します。 その引数が、対話的呼び出しにおける引数の読み方を制御します。


Node:Using Interactive, Next:, Up:Defining Commands

interactiveの使い方

本節では、Lisp関数を対話的に呼び出し可能なコマンドにするフォーム interactiveの書き方について述べます。

interactive arg-descriptor Special Form
このスペシャルフォームは、これを含む関数がコマンドであり、 (M-xや当該関数にバインドしたキー列を入力することで) 対話的に呼び出せることを宣言する。 引数arg-descriptorは、コマンドを対話的に呼び出したときに コマンドに対する引数の計算方法を宣言する。

他の関数と同様に、コマンドはLispプログラムからも呼び出せるが、 その場合、呼び出し側が引数を渡し、arg-descriptorにはなんの効果もない。

フォームinteractiveが効果を発揮するのは、 コマンドループ(実際にはサブルーティンcall-interactively)が 関数を呼び出すまえに関数定義を走査してこのフォームを探すからである。 関数が呼び出されると、フォームinteractiveを含めて その本体のフォームが実行されるが、そのとき、 interactiveは引数を評価せずに単にnilを返す。

引数arg-descriptorには3つの可能性があります。


Node:Interactive Codes, Next:, Previous:Using Interactive, Up:Defining Commands

interactiveのコード文字

以下に述べるコード文字の説明では、 つぎに定義するいくつかのキーワードを含みます。

「補完」
補完を使える。 completing-readを使って引数を読むため、 <TAB>、<SPC>、<RET>は名前を補完する (see Completion)。 ?は補完候補のリストを表示する。
「既存」
既存オブジェクトの名前を必要とする。 不正な名前は受け付けない。 現在の入力が正しくないとミニバッファから抜けるコマンドは動作しない。
「デフォルト」
ミニバッファにユーザーがなにもテキストを入力しないときに 使われるなんらかのデフォルト値。 デフォルトはコード文字に依存する。
「入出力なし」
このコード文字は、入力をまったく読まずに引数を計算する。 したがって、プロンプト文字列を使わず、 読者が指定したプロンプト文字列は無視する。

コード文字はプロンプト文字列を使わないが、 この文字が文字列の最後の文字でない場合には改行を続けること。

「プロンプト」
コード文字の直後にプロンプトが続く。 プロンプトは文字列の終りか改行で終る。
「スペシャル」
このコード文字は、対話指定文字列の先頭でのみ意味を持ち、 プロンプトや改行を必要としない。 これは1つの孤立した文字である。

以下に、interactiveに使うコード文字を説明します。

*
カレントバッファが読み出し専用であるとエラーを通知する。 「スペシャル」。
@
このコマンドを起動したキー列の最初のマウスイベントが表すウィンドウを選択する。 「スペシャル」。
a
関数名(つまり、fboundpを満たすシンボル)。 「既存」、「補完」、「プロンプト」。
b
既存バッファの名前。 デフォルトでは、カレントバッファ(see Buffers)の名前を使う。 「既存」、「補完」、「デフォルト」、「プロンプト」。
B
バッファ名。 バッファが既存である必要はない。 デフォルトでは、カレントバッファ以外の最近使ったバッファの名前を使う。 「補完」、「デフォルト」、「プロンプト」。
c
文字。 カーソルはエコー領域には移動しない。 「プロンプト」。
C
コマンド名(つまり、commandpを満たすシンボル)。 「既存」、「補完」、「プロンプト」。
d
整数としてのポイント位置(see Point)。 「入出力なし」。
D
ディレクトリ名。 デフォルトは、カレントバッファのカレントデフォルトディレクトリ default-directory(see System Environment)。 「既存」、「補完」、「デフォルト」、「プロンプト」。
e
コマンドを起動したキー列の最初やつぎのマウスイベント。 より正確には、eはリストであるイベントを取得するので、 読者はリスト内のデータを調べられる。 see Input Events。 「入出力なし」。

1つのコマンドの対話指定で複数回eを使える。 コマンドを起動したキー列がn個のリストであるイベントである場合、 n番目のeは、n番目のそのようなイベントを与える。 eでは、 ファンクションキーやASCII文字などのリストでないイベントは数えない。

f
既存ファイルの名前(see File Names)。 デフォルトディレクトリはdefault-directory。 「既存」、「補完」、「デフォルト」、「プロンプト」。
F
ファイル名。 ファイルが既存である必要はない。 「補完」、「デフォルト」、「プロンプト」。
i
無関係な引数。 このコードは、引数の値につねにnilを与える。 「入出力なし」。
k
キー列(see Keymap Terminology)。 現在のキーマップにおいてコマンドがみつかる(あるいは未定義コマンド)まで イベントを読み続ける。 キー列引数は、文字列かベクトルとして表現される。 カーソルはエコー領域には移動しない。 「プロンプト」。

この種の入力は、describe-keyglobal-set-keyなどの コマンドで使われる。

K
キー列であり、読者がその定義を変更することを意図している。 これはkと同様に動作するが、 キー列の最後の入力イベントに対しては、 未定義キーを定義済みのものに変換するために(必要なときに)普通使われる 変換処理を抑制する。
m
整数としてのマーク位置。 「入出力なし」。
M
カレントバッファの入力方式を用いてミニバッファで読んだ任意のテキスト。 文字列として返す (see Input Methods)。 「プロンプト」。
n
ミニバッファで読んだ数。 入力が数でないと、ユーザーに再入力を促す。 もし前置引数があってもそれは使わない。 「プロンプト」。
N
数値前置引数。 前置引数がなければ、nで数を読む。 数を必要とする。 see Prefix Command Arguments。 「プロンプト」。
p
数値前置引数。 (このpは小文字。) 「入出力なし」。
P
生の前置引数。 (このPは大文字。) 「入出力なし」。
r
2つの数値引数としてのポイントとマーク。 小さいほうが先にくる。 これは、1つではなく2つの連続した引数を指定する唯一のコード文字。 「入出力なし」。
s
ミニバッファで読んだ任意のテキスト。 文字列として返す(see Text from Minibuffer)。 C-jか<RET>で入力を終える。 (これらの文字を入力に含めるにはC-qを使う。) 「プロンプト」。
S
ミニバッファで読んだ名前をインターンしたシンボル。 白文字で入力を終える。 (文字列に白文字を含めるにはC-qを使う。) (丸括弧や角括弧などの)通常はシンボルを終える他の文字は、 ここではシンボルを終端しない。 「プロンプト」。
v
ユーザーオプションと宣言された変数 (つまり、述語user-variable-pを満たす)。 see High-Level Completion。 「既存」、「補完」、「プロンプト」。
x
入力構文で表されたLispオブジェクト。 C-jか<RET>で終える。 オブジェクトは評価しない。 see Object from Minibuffer。 「プロンプト」。
X
xのようにLispフォームを読むが、評価しその値がコマンドの引数になる。 「プロンプト」。
z
コーディングシステム名(シンボル)。 ユーザーの入力が空であると、引数の値はnil。 see Coding Systems。 「補完」、「既存」、「プロンプト」。
Z
このコマンドに前置引数を指定した場合にのみ、 コーディングシステム名(シンボル)。 前置引数がないと、Zは引数の値にnilを与える。 「補完」、「既存」、「プロンプト」。


Node:Interactive Examples, Previous:Interactive Codes, Up:Defining Commands

interactiveの使用例

ここではinteractiveの例を示します。

(defun foo1 ()              ; foo1は引数なし
    (interactive)           ; 2単語分先へ進める
    (forward-word 2))
     => foo1

(defun foo2 (n)             ; foo2は1引数
    (interactive "p")       ; 数値前置引数
    (forward-word (* 2 n)))
     => foo2

(defun foo3 (n)             ; foo3は1引数
    (interactive "nCount:") ; ミニバッファで読む
    (forward-word (* 2 n)))
     => foo3

(defun three-b (b1 b2 b3)
  "Select three existing buffers.
Put them into three windows, selecting the last one."
    (interactive "bBuffer1:\nbBuffer2:\nbBuffer3:")
    (delete-other-windows)
    (split-window (selected-window) 8)
    (switch-to-buffer b1)
    (other-window 1)
    (split-window (selected-window) 8)
    (switch-to-buffer b2)
    (other-window 1)
    (switch-to-buffer b3))
     => three-b
(three-b "*scratch*" "declarations.texi" "*mail*")
     => nil


Node:Interactive Call, Next:, Previous:Defining Commands, Up:Command Loop

対話的呼び出し

コマンドループでは、キー列をコマンドへ変換し終えると、 関数command-executeを用いてそのコマンドを起動します。 コマンドが関数であれば、command-executeは引数を読み取り、 コマンドを呼び出すcall-interactivelyを呼びます。 読者自身がこれらの関数を呼び出してもかまいません。

commandp object Function
objectが対話的呼び出しに適していれば、 つまり、objectがコマンドであればtを返す。 さもなければnilを返す。

対話的呼び出しが可能なオブジェクトには、 (キーボードマクロとして扱われる)文字列やベクトル、 トップレベルでinteractiveを呼び出しているラムダ式、 そのようなラムダ式をコンパイルしたバイトコード関数オブジェクト、 対話的(autoloadの4番目の引数がnil以外) と宣言された自動ロードオブジェクト、 一部の基本関数が含まれる。

シンボルの関数定義がcommandpを満たせば、 シンボルもcommandpを満たす。

キーやキーマップはコマンドではない。 それらはコマンドを探すために使われる(see Keymaps)。

commandpの実用的な使用例については、 Accessing Documentationdocumentationを参照。

call-interactively command &optional record-flag keys Function
この関数は、対話的呼び出し可能な関数commandを その対話指定に従って引数を読み取り呼び出す。 commandが関数でなかったり、 対話的に呼び出せない(つまり、コマンドでない)場合には、 エラーを通知する。 キーボードマクロ(文字列やベクトル)はコマンドとみなすが、 それらは関数でないため、この関数はキーボードマクロを受け付けない。

record-flagnil以外であると、 コマンドとその引数を無条件にリストcommand-historyに追加する。 さもなければ、引数を読むために コマンドがミニバッファを使った場合にのみ追加する。 see Command History

もし引数keysを指定すると、コマンドがそれを起動したイベントを 問い合わせたときに与えるイベント列を指定する。

command-execute command &optional record-flag keys Function
この関数はcommandを実行する。 引数commandcommandpを満たすこと。 つまり、対話的呼び出し可能な関数かキーボードマクロであること。

commandが文字列やベクトルであると、 execute-kbd-macroで実行される。 関数であると、省略可能なrecord-flagとともに関数を call-interactivelyに渡す。

シンボルは、その関数定義を使って処理する。 autoloadで定義されたシンボルは、 対話的呼び出し可能な関数と宣言されていればコマンドとみなす。 そのような定義では、指定されたライブラリをロードしてから シンボルの定義を再検査して処理する。

もし引数keysを指定すると、コマンドがそれを起動したイベントを 問い合わせたときに与えるイベント列を指定する。

execute-extended-command prefix-argument コマンド
この関数はcompleting-read(see Completion)を使って ミニバッファでコマンド名を読む。 そしてcommand-executeを使って指定されたコマンドを実行する。 コマンドが返した値がexecute-extended-commandの値になる。

コマンドが前置引数を必要とする場合、prefix-argumentの値を受け取る。 execute-extended-commandが対話的に呼ばれた場合、 現在の生の前置引数がprefix-argumentとして使われ、 それが実行するコマンドへ渡される。

execute-extended-commandは通常M-xに定義付けられ、 そのため、プロンプトとして文字列M-x を使う。 (execute-extended-commandを起動するために使われた イベントをプロンプトにするべきであるが、 それを実装するのは手間がかかる。) もし前置引数を指定すると、その内容もプロンプトの一部になる。

(execute-extended-command 1)
---------- Buffer: Minibuffer ----------
1 M-x forward-word RET
---------- Buffer: Minibuffer ----------
     => t

interactive-p Function
この関数は、これ(interactive-pの呼び出し)を含んだ関数が call-interactivelyで対話的に呼び出されるとtを返す。 (Lispからcall-interactivelyが呼び出されても、 エディタコマンドループが直接呼び出しても違いはない。) これを含んだ関数がLispの評価(あるいはapplyfuncall)で 呼び出された場合は、対話的呼び出しではない。

interactive-pのもっとも一般的な用途は、 情報メッセージを表示するかどうか決めることです。 特別な例外として、キーボードマクロを実行中にはいつでも、 interactive-pnilを返します。 これは情報メッセージを省いてマクロの実行を速くするためです。

つぎのように使います。

(defun foo ()
  (interactive)
  (when (interactive-p)
    (message "foo")))
     => foo

(defun bar ()
  (interactive)
  (setq foobar (list (foo) (interactive-p))))
     => bar

;; M-x fooと打つ
     -| foo

;; M-x barと打つ
;; これはなにも表示しない

foobar
     => (nil t)

この種のことを行う別の方法は、コマンドを 対話的呼び出しではnil以外の値になる引数print-messageを 取るようにし、その引数がnil以外になるようなinteractive指定を 使うことです。 つぎのようにします。

(defun foo (&optional print-message)
  (interactive "p")
  (when print-message
    (message "foo")))

pで与えられる数値前置引数はけっしてnilになりません。


Node:Command Loop Info, Next:, Previous:Interactive Call, Up:Command Loop

コマンドループからの情報

エディタコマンドループは、自身や実行中のコマンドのために 状態記録を数個のLisp変数に設定します。

last-command Variable
この変数は、コマンドループが(現在のコマンドの)まえに実行したコマンドの 名前を記録する。 通常、この値は関数定義を持つシンボルであるが、保証はしない。

コマンドが後続のコマンドに対する前置引数を指定する場合を除いて、 コマンドからコマンドループへ戻るとthis-commandから値をコピーする。

この変数は現在の端末に対してつねにローカルであり、 バッファに対してローカルにはならない。 see Multiple Displays

real-last-command Variable
last-commandと同様にEmacsがこの変数に設定するが、 Lispプログラムではけっして変更しない。

this-command Variable
この変数は、エディタコマンドループが いま実行しているコマンドの名前を記録する。 last-commandと同様に、通常は関数定義を持つシンボルである。

コマンドループは、コマンドを実行する直前にこの変数に設定し、 コマンドが終了すると(コマンドが後続のコマンドに対する 前置引数を指定する場合を除いて) この値をlast-commandにコピーする。

後続のコマンドに対するフラグとして 実行中にこの変数に設定するコマンドもある。 特に、テキストをキルする関数群はthis-commandkill-regionを 設定して、直後に続くキルコマンドでは キルしたテキストをまえのキルに追加するようにする。

特定のコマンドがエラーを起こした場合に 直前のコマンドとは認識されたくない場合には、 読者はそのコマンドがそれを防ぐように書く必要があります。 1つの方法は、以下に示すように、 コマンドの始めでthis-commandtを設定し、 コマンドの終りでthis-commandに正しい値を戻します。

(defun foo (args...)
  (interactive ...)
  (let ((old-this-command this-command))
    (setq this-command t)
    ...do the work...
    (setq this-command old-this-command)))

letthis-commandを束縛しません。 というのは、エラーがあるとletは古い値を復元するからです。 これこそがここでは避けたいletの機能です。

this-command-keys Function
この関数は、現在のコマンドに対して直前のコマンドが生成した前置引数を含めて、 現在のコマンドを起動したキー列を含んだ文字列かベクトルを返す。 すべてのイベントが文字であれば、値は文字列である。 see Input Events
(this-command-keys)
;; C-u C-x C-eを使ってこの式を評価する
     => "^U^X^E"

this-command-keys-vector Function
this-command-keysと同様だが、つねにベクトルでイベントを返すため、 文字列に入力イベントを保持する際の複雑さを扱う必要がない (see Strings of Events)。

last-nonmenu-event Variable
この変数は、マウスメニューによるイベントを考慮せずに、 キー列として読んだ最後の入力イベントを保持する。

この変数の1つの用途は、 メニューをポップアップする位置をx-popup-menuに指示することである。 y-or-n-p(see Yes-or-No Queries)も内部的に使っている。

last-command-event Variable
last-command-char Variable
この変数には、コマンドの一部としてコマンドループが 読んだ最後の入力イベントが設定される。 この変数の主な用途は、どの文字を挿入すべきかを決定するために self-insert-commandが使うことである。
last-command-event
;; C-u C-x C-eを使ってこの式を評価する
     => 5

C-eASCIIコードは5なので、値は5である。

Emacs 18版との互換性のために別名last-command-charがある。

last-event-frame Variable
この変数は、最後の入力イベントを振り向けたフレームを記録する。 通常これは、イベントが生成されたときに選択されていたフレームであるが、 そのフレームが入力フォーカスを別のフレームに振り向けていると、 この値はイベントを振り向けた先のフレームである。 see Input Focus


Node:Input Events, Next:, Previous:Command Loop Info, Up:Command Loop

入力イベント

Emacsのコマンドループは、キーボードやマウスのユーザーの操作を表す 入力イベント(input event)列を読みます。 キーボード操作に対するイベントは、文字かシンボルです。 マウスイベントはつねにリストです。 本節では、入力イベントの表現方法やその意味を詳しく説明します。

eventp object Function
この関数は、objectが入力イベントであるかイベント型であると nil以外を返す。

任意のシンボルがイベントやイベント型として使われることに注意。 eventpは、Lispのプログラムコードがシンボルを イベントとして使うかどうか区別できない。 そのかわりに、シンボルが、Emacsの現在のセッションにおいて入力として読まれた イベントに使われたことがあるかどうかを区別する。 シンボルがそのように使われたことがなければ、 eventpnilを返す。


Node:Keyboard Events, Next:, Up:Input Events

キーボードイベント

キーボードからは2種類の入力があります。 普通のキーとファンクションキーです。 普通のキーは文字に対応します。 それらが生成するイベントは、Lispでは文字として表現されます。 文字イベントのイベント型は文字自身(整数)です。 Classifying Eventsを参照してください。

入力文字イベントは、0から524287までの基本コード(basic code)と 以下の修飾ビット(modifier bit)の任意の組み合わせです。

meta
文字コードのビット は、メタキーを押し下げながら文字を打ったことを表す。
control
文字コードのビット は非ASCII文字のコントロール文字を表す。

C-aなどのASCIIコントロール文字には 独自の特別な基本コードがあるため、 Emacsはそれを表すための特別なビットを必要としない。 つまり、C-aのコードは単に1である。

しかし、コントロールキーを使った%などの ASCIIにないコントロールとの組み合わせを打った場合、 得られる数値は%のコードに を加えたものである (端末で非ASCIIのコントロール文字を扱えるとして)。

shift
文字コードのビット は、シフトキーを押し下げながら ASCIIコントロール文字を打ったことを表す。

英文字では、基本コードそのものが大文字か小文字かを表す。 数字文字と区切り文字では、 シフトキーは異なる基本コードのまったく異なる文字を選ぶ。 可能な限りASCII文字集合ですませるために、 これらの文字に対しては、Emacsはビット を使わない。

しかし、ASCIIではC-AC-aを区別できないため、 Emacsは、C-Aではビット を使うが、C-aではこのビットを使わない。

hyper
文字コードのビット は、ハイパーキーを押し下げながら文字を打ったことを表す。
super
文字コードのビット は、スーパーキーを押し下げながら文字を打ったことを表す。
alt
文字コードのビット は、アルトキーを押し下げながら文字を打ったことを表す。 (<ALT>とラベルされたキーが実際にはメタキーである端末も存在する。)

読者のプログラム内では、 特定の修飾ビットの値を明示することは避けるのが最良です。 文字の修飾ビットを検査するには、 関数event-modifiers(see Classifying Events)を使います。 キーバインディングを作るときには、 (\C-\M-などの)修飾ビットを伴う文字の 入力表現を使います。 define-keyでキーバインディングを作るときには、 文字の指定には(control hyper ?x)のようなリストを使います (see Changing Key Bindings)。 関数event-convert-listは、そのようなリストを イベント型に変換します(see Classifying Events)。


Node:Function Keys, Next:, Previous:Keyboard Events, Up:Input Events

ファンクションキー

ほとんどのキーボードには、ファンクションキー(function key)、 つまり、文字ではない名前や記号のキーがあります。 Emacs Lispでは、ファンクションキーはシンボルで表現されます。 シンボルの(小文字の)名前がファンクションキーのラベルです。 たとえば、<F1>というラベルのキーを押すと、 入力ストリームにはシンボルf1が置かれます。

ファンクションキーイベントのイベント型は、イベントシンボルそれ自身です。 See Classifying Events

ファンクションキーに対するシンボル命名慣習の特例を以下に示します。

backspace, tab, newline, return, delete
これらのキーは、ほとんどのキーボードにある特別なキーを持つ 一般的なASCIIコントロール文字に対応する。

ASCIIでは、C-iと<TAB>は同じ文字である。 これらを区別できる端末では、前者を整数9、後者をシンボルtabと 表現することで、EmacsはLispプログラムに区別を伝える。

ほとんどの場面では、これら2つを区別しても有用ではない。 そのため、通常、function-key-map(see Translating Input)は、 tabを9に対応付けるようには設定してある。 したがって、文字コード9(文字C-i)に対するキーバインディングは tabにも適用される。 この種の他のシンボルについても同様である。 関数read-charも同様にこれらのイベントを文字に変換する。

ASCIIでは、<BS>は実際にはC-hである。 しかし、backspaceは文字コード127(<DEL>)に変換され、 文字コード8(<BS>)には変換されない。 ほとんどのユーザーはこれを好む。

left, up, right, down
カーソル矢印キー
kp-add, kp-decimal, kp-divide, ...
(普通のキーボードの右側にある)キーパッドのキー。
kp-0, kp-1, ...
キーパッドの数字キー。
kp-f1, kp-f2, kp-f3, kp-f4
キーパッドのPFキー
kp-home, kp-left, kp-up, kp-right, kp-down
キーパッドの矢印キー。 Emacsは、通常、これらを対応するキーパッドのものではない homeleft...のキーに変換する。
kp-prior, kp-next, kp-end, kp-begin, kp-insert, kp-delete
普通のキーに対応するキーパッドのキー。 Emacsは、通常、同じ名前のキーパッドのものではないキーに変換する。

ファンクションキーにも<ALT>、<CTRL>、<HYPER>、 <META>、<SHIFT>、<SUPER>の修飾キーを使えます。 それらを表現するには、シンボル名に接頭辞を付けます。

A-
アルト修飾。
C-
コントロール修飾。
H-
ハイパー修飾。
M-
メタ修飾。
S-
シフト修飾。
s-
スーパー修飾。

したがって、<META>を押し下げた<F3>キーのシンボルはM-f3です。 複数の接頭辞を使うときには、アルファベット順に書くことを勧めますが、 キーバインディングの探索関数や修飾関数の引数では関係ありません。


Node:Mouse Events, Next:, Previous:Function Keys, Up:Input Events

マウスイベント

Emacsでは4種類のマウスイベント、つまり、クリックイベント、ドラッグイベント、 ボタン押し下げイベント、モーションイベントを扱えます。 すべてのマウスイベントは、リストで表現します。 リストのCARはイベント型であり、 どの修飾キーとともにどのマウスボタンを使ったかを表します。 イベント型では、ダブル(連続2回)/トリプル(連続3回)の 押し下げも区別できます(see Repeat Events)。 リストの残りの要素は、位置情報と時間情報です。

キーの探索では、イベント型のみが意味を持ちます。 型が同じであれば、異なるイベントでも同じコマンドを実行します。 コマンドでは、対話指定コードeを用いてイベントの完全な値を参照できます。 See Interactive Codes

マウスイベントで始まるキー列は、カレントバッファのキーマップではなく、 マウスが入っているウィンドウのバッファのキーマップを用いて読まれます。 つまり、あるウィンドウ内でクリックしても、 当該ウィンドウやバッファを選択するとは限らず、 その動作はキー列のコマンドバインディングで完全に制御されます。


Node:Click Events, Next:, Previous:Mouse Events, Up:Input Events

クリックイベント

ユーザーがマウスのボタンを同じ場所で押し下げてから離すと、 クリック(click)イベントが生成されます。 マウスクリックイベントはつぎの形式です。

(event-type
 (window buffer-pos (x . y) timestamp)
 click-count)

通常の各要素の意味はつぎのとおりです。

event-type
どのマウスボタンが使われたかを表すシンボル。 ボタンを左から右へ番号を付けて、 シンボルmouse-1mouse-2...の1つである。

ファンクションキーの場合と同様に、 アルト、コントロール、ハイパー、メタ、シフト、スーパーの 修飾キーを表す接頭辞A-C-H-M-S-s-も使える。

このシンボルはイベントのイベント型としての役割も果たす。 キーバインディングはイベント型でイベントを指定する。 したがって、mouse-1に対するキーバインディングは、 イベント型event-typemouse-1であるすべてのイベントに適用される。

window
クリックを行ったウィンドウ。
x, y
ウィンドウwindowの左上端を(0 . 0)とした クリック位置のピクセル単位の座標。
buffer-pos
クリックした文字のバッファ内位置。
timestamp
イベントが発生したときのミリ秒単位の時刻。 (この値は、Emacs Lispの整数の範囲では約5時間で一周するので、 時間的に近傍のイベントを関連付ける場合にのみ有用である。)
click-count
同じマウスボタンを素早く押し下げた繰り返し回数。 see Repeat Events

モード行やスクロールバーなどのスクリーンの特別な部分で発生したイベントでは、 buffer-posxyの意味は少々異なります。

スクロールバーの内側でのクリックでは、 buffer-posはシンボルvertical-scroll-barhorizontal-scroll-barであり、 (x . y)(portion . whole)に 置き換えられます。 ここで、portionはスクロールバーの先頭や左端からのクリック位置、 wholeはスクロールバー全体の長さです。

モード行やウィンドウwindowを右隣のものと区切る 縦方向の区切り行の内側では、 buffer-posはシンボルmode-linevertical-lineです。 モード行では、yは意味のあるデータではありません。 縦方向の区切り行では、xは意味のあるデータではありません。

1つの特別な場面では、 buffer-posは単一のシンボルではなく(上に述べた1つの)シンボルを 含んだリストになります。 イベントに対する仮想的なプレフィックスキーを入力ストリームに挿入すると このようになります。 See Key Sequence Input


Node:Drag Events, Next:, Previous:Click Events, Up:Input Events

ドラッグイベント

Emacsには、ドラッグイベントがあります。 ユーザーがマウスボタンを押し下げてから、 ボタンを離すまえに別の文字位置へマウスを動かすと ドラッグ(drag)イベントが発生します。 マウスのすべてのイベントのように、Lispではドラッグイベントは リストとして表現されます。 つぎのように、リストは開始マウス位置と終了位置を記録しています。

(event-type
 (window1 buffer-pos1 (x1 . y1) timestamp1)
 (window2 buffer-pos2 (x2 . y2) timestamp2)
 click-count)

ドラッグイベントでは、シンボルevent-typeの名前には 接頭辞drag-が付きます。 たとえば、ボタン2を押し下げてマウスをドラッグすると イベントdrag-mouse-2が生成されます。 イベントの2番目と3番目の要素は、ドラッグの開始位置と終了位置を与えます。 なお、データにはクリックイベントと同じ意味があります(see Click Events)。 ドラッグイベントかどうかを区別せずに、 マウスの任意のイベントの2番目の要素は同じ方法で参照できます。

接頭辞drag-は、 C-M-のような修飾キー接頭辞に続きます。

read-key-sequenceが、 キーバインディングを持たないドラッグイベントを受け取り、かつ、 それに対応するクリックイベントにはバインディングがある場合、 ドラッグイベントの開始位置をクリック位置とするクリックイベントに変換します。 つまり、望まなければ、読者はクリックイベントとドラッグイベントを区別する 必要がありません。


Node:Button-Down Events, Next:, Previous:Drag Events, Up:Input Events

ボタン押し下げイベント

クリックイベントとドラッグイベントは、 ユーザーがマウスボタンを離したときに発生します。 ボタンを離すまではクリックとドラッグを区別する方法がないため、 ボタンを離すまで発生しえません。

ボタンを押し下げたらただちに動作を始めたい場合には、 読者はボタン押し下げ(button-down)イベントを処理する必要があります。 8 ボタンを押し下げるとただちに発生します。 それらは、シンボルevent-typeの名前に 接頭辞down-があることを除けば、 クリックイベント(see Click Events)とまったく同じリストで表現されます。 接頭辞down-は、C-M-のような修飾キー接頭辞に続きます。

関数read-key-sequenceは、 コマンドバインディングを持たないボタン押し下げイベントを無視します。 したがって、Emacsのコマンドループもそれらを無視します。 つまり、読者がボタン押し下げイベントでなにかをしたいのでなければ、 読者はボタン押し下げイベントを定義する必要はありません。 ボタン押し下げイベントを定義する理由は、 ボタンが離されるまで(モーションイベントを読んで)マウスの動きを 追跡するためです。 See Motion Events


Node:Repeat Events, Next:, Previous:Button-Down Events, Up:Input Events

繰り返しイベント

マウスを動かさずに同一のマウスボタンを素早く連続して押し下げると、 Emacsは2回目以降の押し下げに対して 特別な繰り返し(repeat)マウスイベントを生成します。

もっとも一般的な繰り返しイベントはダブルクリック(double-click) イベントです。 ボタンを2回クリックすると、Emcasはダブルクリックイベントを生成します。 (他のすべてのクリックイベントのように)読者がボタンを離したときに イベントが生成されます。

ダブルクリックイベントのイベント型には、接頭辞double-が含まれます。 したがって、<meta>を押し下げて2番目のボタンをダブルクリックすると、 LispプログラムにはM-double-mouse-2が送られます。 ダブルクリックイベントにバインディングがなければ、 対応する普通のクリックイベントを用いて実行します。 したがって、実際に利用したくない限りは、 読者はダブルクリック機能に注意する必要はありません。

ユーザーがダブルクリックすると、Emacsはまず普通のクリックイベントを生成し、 つぎにダブルクリックイベントを生成します。 したがって、ダブルクリックイベントのコマンドバインディングでは、 すでに普通のクリックコマンドが動作済みであると仮定して設計する必要があります。 普通のクリックの結果をもとに望みのダブルクリックの結果を得るようにします。

普通のクリックの意味にダブルクリックの意味を 『追加』するようにすると便利です。 ダブルクリックのユーザーインターフェイスはこのようにすることを勧めます。

ボタンをクリックして、ふたたびボタンを押し下げてそのままマウスを動かすと、 最終的にボタンを離した時点で、ダブルドラッグ(double-drag)イベントが 生成されます。 そのイベント型にはdragのかわりにdouble-dragが含まれます。 ダブルドラッグイベントにバインディングがなければ、 Emacsは普通のドラッグイベントとしてバインディングを探します。

ダブルクリックイベントやダブルドラッグイベントを生成するまえに、 ユーザーがボタンを2回目に押し下げたとき、 Emacsはダブルダウン(double-down)イベントを生成します。 このイベント型にはdownのかわりにdouble-downが含まれます。 ダブルダウンイベントにバインディングがなければ、 Emacsは普通のボタン押し下げイベントとしてバインディングを探します。 どちらでもバインディングがみつからなければ、ダブルダウンイベントは無視します。

まとめると、ボタンをクリックしてただちに再度ボタンを押し下げると、 Emacsは、はじめのクリックに対してボタン押し下げイベントと クリックイベントを生成し、 再度ボタンを押し下げるとダブルダウンイベントを生成し、 最後にダブルクリックイベントかダブルドラッグイベントを生成します。

ボタンを2回クリックしてから再度押し下げる操作を素早く行うと、 Emacsは、トリプルダウン(triple-down)イベントに続けて トリプルクリック(triple-click)イベントか トリプルドラッグ(triple-drag)イベントを生成します。 これらのイベント型にはdoubleのかわりにtripleが含まれます。 トリプルのイベントにバインディングがなければ、 Emacsは対応するダブルのイベントを使います。

ボタンを3回以上クリックしてから再度押し下げると、 3回目以降の押し下げに対するイベントはすべてトリプルのイベントです。 Emacsは、クアドラプル(4回)、クインタプル(5回)、…などの イベントは生成しません。 しかし、イベントリストを調べれば、ボタンを何回押したか正確にわかります。

event-click-count event Function
この関数は、イベントeventにおいてボタンが連続して押された回数を返す。 eventが、ダブルダウンイベント、ダブルクリックイベント、 ダブルドラッグイベントであると、値は2である。 eventがトリプルのイベントであると、値は3かそれ以上である。 eventが(繰り返しイベントではない)普通のマウスイベントであると、 値は1である。

double-click-time Variable
繰り返しイベントが生成されるためには、 同じスクリーン位置において連続してマウスボタンを押し下げ、しかも、 各押し下げの間隔はdouble-click-timeの値未満(ミリ秒)である必要がある。 double-click-timenilを設定すると、 連続したクリックの検出を禁止する。 tを設定すると時間制限をなくし、 Emacsは連続したクリックの検出を位置だけで行う。


Node:Motion Events, Next:, Previous:Repeat Events, Up:Input Events

モーションイベント

Emacsは、ボタン操作を伴わないマウスの移動を表す マウスモーション(mouse motion)イベントを生成することがあります。 マウスモーションイベントはつぎのようなリストで表現されます。

(mouse-movement (window buffer-pos (x . y) timestamp))

リストの2番目の要素は、クリックイベント(see Click Events)と同様に、 マウスの現在位置を表します。

スペシャルフォームtrack-mouseにより、 その本体の内側ではモーションイベントの生成を可能にできます。 フォームtrack-mouseの外側では、 Emacsはマウスの移動のみに対するイベントを生成しないので、 それらのイベントは現れません。 See Mouse Tracking


Node:Focus Events, Next:, Previous:Motion Events, Up:Input Events

フォーカスイベント

ウィンドウシステムは、どのウィンドウにキーボード入力を与えるかを ユーザーが制御するための一般的な方法を提供します。 ウィンドウを選ぶことをフォーカス(focus)と呼びます。 ユーザーがEmacsのフレームを切り替える操作を行うと、 フォーカスイベント(focus event)が生成されます。 グローバルキーマップにあるフォーカスイベントの普通の定義は、 Emcasの新たなフレームを選択するようになっていて、 これはユーザーが期待することです。 See Input Focus

Lispでは、フォーカスイベントはつぎのようなリストで表現されます。

(switch-frame new-frame)

ここで、new-frameは切り替え先のフレームです。

Xのほとんどのウィンドウマネージャは、 マウスをウィンドウへ入れるだけで当該ウィンドウにフォーカスが設定される ようになっています。 フレームにマウスが入るとカーソルの形状を変更するので、 Emacsでもそのようにします。 しかし、Lispプログラムにとっては、 なんらかの入力が到着するまではフォーカスの変更について知る必要がありません。 そのため、ユーザーが実際にキーボードのキーを打つか 新たなフレームでマウスボタンを押し下げたときだけ、 Emacsはフォーカスイベントを生成します。 フレーム間でマウスを動かしただけでは、フォーカスイベントは生成されません。

キー列の途中にフォーカスイベントが現れると、キー列を乱します。 そのため、Emacsはキー列の途中にはフォーカスイベントを生成しません。 ユーザーがキー列の途中で、つまり、 プレフィックスキーのあとでフォーカスを変更すると、 複数イベントのキー列のまえかうしろにフォーカスイベントを移動し、 途中には現れないようにEmacsはイベントの順序を並び替えます。


Node:Misc Events, Next:, Previous:Focus Events, Up:Input Events

ウィンドウシステムのその他のイベント

ウィンドウシステム内で起きたことを表す他のイベントもあります。

(delete-frame (frame))
この種のイベントは、 Emacsのフレームであるウィンドウを削除するコマンドを ユーザーがウィンドウマネージャに与えたことを表す。

イベントdelete-frameの標準定義はフレームframeの削除である。

(iconify-frame (frame))
この種のイベントは、 ウィンドウマネージャを用いてユーザーがフレームframeを アイコン化したことを表す。 これに対する標準定義はignoreである。 というのは、フレームはすでにアイコンになっているので、 Emacsが行うことはなにもないからである。 このイベント型の目的は、 必要ならばその種のイベントを読者が追跡できるようにしておくことである。
(make-frame-visible (frame))
この種のイベントは、 ウィンドウマネージャを用いてユーザーがアイコン化したフレームframeを 開いたことを表す。 これに対する標準定義はignoreである。 というのは、フレームはすでに見えるようになっているので、 Emacsが行うことはなにもないからである。
(mouse-wheel position delta)
この種のイベントは、 (MSインテリマウスなどの)マウスのホイールを動かすと生成される。 その典型的な効果はスクロールやズーミングである。

要素deltaはホイールの回転方向と回転量である。 その絶対値はホイールを回すごとに増加する数である。 負のdeltaは、逆転、つまり、ユーザーへ近付く方向への回転を表し、 正のdeltaは、順転、つまり、ユーザーから遠ざかる方向への回転を表す。

要素positionはイベントの発生位置を表し、 マウスクリックイベントで使われる形式と同じである。

この種のイベントは、ある種のシステムでのみ生成される。

(drag-n-drop position files)
この種のイベントは、 Emacsの外側のアプリケーションで一群のファイルを選択し、 それらをEmacsのフレームにドラッグ&ドロップしたときに生成される。

要素positionはイベントの発生位置を表し、 マウスクリックイベントで使われる形式と同じであり、 要素filesはドラッグ&ドロップされたファイル名のリストである。 このイベントを扱う通常の処理は、それらのファイルを訪問することである。

現状では、この種のイベントは、ある種のシステムでのみ生成される。

これらのイベントがキー列の途中、つまり、 プレフィックスキーのうしろに現れると、 複数イベントのキー列のまえかうしろに当該イベントを移動し、 途中には現れないようにEmacsはイベントの順序を並び替えます。


Node:Event Examples, Next:, Previous:Misc Events, Up:Input Events

イベントの例

ユーザーが同じ場所でマウスの左ボタンを押し下げてから離すと、 つぎのようなイベント列が生成されます。

(down-mouse-1 (#<window 18 on NEWS> 2613 (0 . 38) -864320))
(mouse-1      (#<window 18 on NEWS> 2613 (0 . 38) -864180))

コントロールキーを押し下げた状態で、 ユーザーがマウスの2番目のボタンを押し下げ、 マウスをつぎの行へドラッグすると、つぎのような2つのイベントが生成されます。

(C-down-mouse-2 (#<window 18 on NEWS> 3440 (0 . 27) -731219))
(C-drag-mouse-2 (#<window 18 on NEWS> 3440 (0 . 27) -731219)
                (#<window 18 on NEWS> 3510 (0 . 28) -729648))

メタキーとシフトキーを押し下げた状態で、 ユーザーがマウスの2番目のボタンをウィンドウのモード行で押し下げ、 マウスを別のウィンドウへドラッグすると、 つぎのような2つのイベントが生成されます。

(M-S-down-mouse-2 (#<window 18 on NEWS> mode-line (33 . 31) -457844))
(M-S-drag-mouse-2 (#<window 18 on NEWS> mode-line (33 . 31) -457844)
                  (#<window 20 on carlton-sanskrit.tex> 161 (33 . 3)
                   -453816))


Node:Classifying Events, Next:, Previous:Event Examples, Up:Input Events

イベントの分類

各イベントにはイベント型(event type)があって、 キーバインディング処理のためにイベントを分類します。 キーボードイベントでは、イベント型はイベントの値に等しいです。 したがって、文字に対するイベント型は文字であり、 ファンクションキーに対するイベント型はシンボルそのものです。 リストであるイベントでは、イベント型はリストのCARにあるシンボルです。 したがって、イベント型はつねにシンボルか文字です。

イベント型が同じであるイベントは、キーバインディングに関する限り同じです。 つまり、それらは同じコマンドを実行します。 しかし、これは、それらが必ずしも同じことを行うという意味ではありません。 イベント全体を調べてなにを行うかを決定するコマンドもあります。 たとえば、マウスイベントの生起位置を使って、 バッファのどの部分を処理するかを決めるコマンドもあります。

イベントをおおまかに分類すると有用な場合もあります。 たとえば、他の修飾キーやマウスボタンには関係なしに、 <META>キーが使われているイベントかどうか調べたいことがあるでしょう。

関数event-modifiersevent-basic-typeは、 そのような情報を便利に与えるためのものです。

event-modifiers event Function
この関数は、eventにある修飾子のリストを返す。 修飾子はシンボルであり、shiftcontrolmetaalthypersuperである。 さらに、マウスイベントシンボルの修飾子リストには、 必ず、clickdragdownの1つが含まれる。

引数eventは、イベントオブジェクト全体であるか、単なるイベント型である。

例を示す。

(event-modifiers ?a)
     => nil
(event-modifiers ?\C-a)
     => (control)
(event-modifiers ?\C-%)
     => (control)
(event-modifiers ?\C-\S-a)
     => (control shift)
(event-modifiers 'f5)
     => nil
(event-modifiers 's-f5)
     => (super)
(event-modifiers 'M-S-f5)
     => (meta shift)
(event-modifiers 'mouse-1)
     => (click)
(event-modifiers 'down-mouse-1)
     => (down)

クリックイベントに対する修飾子リストにはclickが明示的に含まれるが、 イベントシンボルの名前自体にはclickは含まれない。

event-basic-type event Function
この関数は、eventにあるキーやマウスボタンを返す。 たとえばつぎのとおり。
(event-basic-type ?a)
     => 97
(event-basic-type ?A)
     => 97
(event-basic-type ?\C-a)
     => 97
(event-basic-type ?\C-\S-a)
     => 97
(event-basic-type 'f5)
     => f5
(event-basic-type 's-f5)
     => f5
(event-basic-type 'M-S-f5)
     => f5
(event-basic-type 'down-mouse-1)
     => mouse-1

mouse-movement-p object Function
この関数は、objectがマウス移動のイベントならばnil以外を返す。

event-convert-list list Function
この関数は、修飾子名と基本イベント型のリストを それらが示すイベント型に変換する。 たとえばつぎのとおり。
(event-convert-list '(control ?a))
     => 1
(event-convert-list '(control meta ?a))
     => -134217727
(event-convert-list '(control super f1))
     => C-s-f1


Node:Accessing Events, Next:, Previous:Classifying Events, Up:Input Events

イベントの参照

本節では、マウスボタンイベントやモーションイベント内のデータを 参照するための便利な関数について述べます。

つぎの2つの関数は、以下の形式のリストであるマウスボタンイベントの 開始位置や終了位置を返します。

(window buffer-position (x . y) timestamp)

event-start event Function
イベントeventの開始位置を返す。

eventがクリックイベントやボタン押し下げイベントであると、 イベントの位置を返す。 eventがドラッグイベントであると、ドラッグの開始位置を返す。

event-end event Function
イベントeventの終了位置を返す。

eventがドラッグイベントであると、 ユーザーがマウスボタンを離したときの位置を返す。 eventがクリックイベントかボタン押し下げイベントであると、 実際の値は開始位置であり、 その種のイベントにある唯一の位置情報である。

つぎの5つの関数は、上に述べた位置情報のリストを引数として、 そのさまざまな部分を返す。

posn-window position Function
position内のウィンドウを返す。

posn-point position Function
positionのバッファ内位置を返す。 これは整数である。

posn-x-y position Function
position内のピクセル単位のxy座標を コンスセル(x . y)として返す。

posn-col-row position Function
positionの(文字単位の)行(row)とコラム(col)の座標を コンスセル(col . row)として返す。 これらは実際にはposition内のxyの値から計算される。

posn-timestamp position Function
position内の時刻情報を返す。

つぎの関数はスクロールバーでのイベントを解読するのに便利です。

scroll-bar-event-ratio event Function
スクロールバー内でのイベントから、スクロールバーに対する縦方向の位置を返す。 その値は2つの整数を含むコンスセル(portion . whole)であり、 その比は位置の割合を表す。

scroll-bar-scale ratio total Function
この関数は(実質的には)ratiototalを掛け、 結果を整数に丸める。 引数ratioは数ではなく(num . denom)であり、 典型的にはscroll-bar-event-ratioが返す値である。

この関数はスクロールバー内での位置を バッファ内での位置へ換算するのに便利である。 つぎのように行う。

(+ (point-min)
   (scroll-bar-scale
      (posn-x-y (event-start event))
      (- (point-max) (point-min))))

スクロールバー内でのイベントには、 xy座標のかわりに比を表す2つの整数があることに注意。


Node:Strings of Events, Previous:Accessing Events, Up:Input Events

キーボードイベントを文字列で保持する

文字列が使われるほとんどの場面では、 文字列にはテキスト文字、つまり、 バッファやファイルにある文字と同じ種類のものが入っていると考えています。 文字列にはキーボード文字が入っているとみなして使うLispプログラムもあります。 たとえば、文字列には、キー列やキーボードマクロの定義が入っているのです。 しかし、キーボード文字を文字列に保持するのは複雑であり、 それは歴史的な互換性を保つためにするのであり、 また、つねに可能とは限りません。

新しいプログラムでは、キーボードイベントを文字列に保持しないで、 このような複雑さを避けるように推奨します。 つぎのようにします。

複雑さの原因は、キーボード入力に含まれる修飾ビットにあります。 メタ修飾子以外の修飾ビットを文字列に入れることは不可能であり、 メタ修飾子は特別な場合として唯一許されているのです。

初期のGNU Emacsでは、メタ文字を128から255の範囲のコードで表現していました。 その当時、基本文字コードは0から127でしたから、 キーボード文字のすべてのコードは文字列に収まったのです。 多くのLispプログラムでメタ文字を表すために文字列定数内で\M-を使い、 特に、define-keyや類似の関数に対する引数に使われ、 キー列やイベント列はつねに文字列で表現されていました。

127を超える大きな基本文字コードと追加の修飾ビットを扱えるようにしたとき、 メタ文字の表現方法を変更せざるをえませんでした。 現在、メタ修飾子を表す文字内のビットは であり、そのような数を文字列に入れることはできません。

文字列定数で\M-を使っているプログラムを扱えるように、 文字列にメタ文字を入れるための特別な規則があります。 以下は、文字列を入力文字の列として解釈するための規則です。

キーボード入力文字の文字列を作るread-key-sequenceなどの関数は つぎの規則に従います。 つまり、文字列に収まらないイベントであるときには、 文字列のかわりにベクトルを作ります。

読者が文字列で\M-の入力構文を使うと、 それらは128から255の範囲のコードになります。 対応するキーボードイベントを文字列に保存するように変更したときに得られる コードと同じです。 したがって、文字列内のメタイベントは、それらがどのように文字列に 収められたかに関わらず、整合性のある動作をします。

しかし、本節のはじめに述べた推奨方法に従ってこれらのことがらを避けるほうが、 ほとんどのプログラムはよりよく動作するでしょう。


Node:Reading Input, Next:, Previous:Input Events, Up:Command Loop

入力の読み取り

エディタコマンドループは、 関数read-key-sequenceを使ってキー列を読み取ります。 なお、関数read-key-sequenceは関数read-eventを使います。 これらやイベント入力を扱う他の関数は、Lispプログラムからも使えます。 Temporary Displaysmomentary-string-display、 および、Waitingsit-forを参照してください。 端末の入力モードの制御や端末入力のデバッグに関する関数や変数については、 See Terminal Input。 入力イベントを読むときにそれらを変換したり修正する機能については、 See Translating Input

上位レベルの入力機能については、Minibuffersを参照してください。


Node:Key Sequence Input, Next:, Up:Reading Input

キー列の入力

コマンドループは、read-key-sequenceを呼ぶことで キー列の入力を読み取ります。 Lispプログラムからこの関数を呼び出してもよく、 たとえば、describe-keyは、 説明対象とするキーを読むためにこの関数を使います。

read-key-sequence prompt Function
この関数は、キー列を読み取り文字列かベクトルとして返す。 完全なキー列を収集し終えるまで、 つまり、現在活性なキーマップにおいて、非プレフィックスコマンドを 指定するのに十分になるまで、イベントを読み続ける。

イベントがすべて文字であり、かつ、それらが文字列に収まるならば、 read-key-sequenceは文字列(see Strings of Events)を返す。 さもなければ、ベクトルを返す。 ベクトルならば、任意の種類のイベント、つまり、 文字、シンボル、リストを保持できるからである。 文字列やベクトルの要素は、キー列のイベントである。

引数promptは、プロンプトとしてエコー領域に表示する文字列であるか、 あるいは、プロンプトを表示しないことを意味するnilである。

以下の例では、プロンプト?がエコー領域に表示され、 ユーザーはC-x C-fと打つ。

(read-key-sequence "?")

---------- Echo Area ----------
?C-x C-f
---------- Echo Area ----------

     => "^X^F"

関数read-key-sequenceは中断を抑止する。 この関数が動作中にC-gを打っても、他の文字と同様に扱い、 quit-flagを設定しない。 see Quitting

read-key-sequence-vector prompt Function
これはread-key-sequenceと同様であるが、 つねにベクトルとしてキー列を返し、文字列としてはけっして返さない。 see Strings of Events

入力文字が大文字であって、それらにキーバインディングがないとき、 対応する小文字にキーバインディングがあれば、 read-key-sequenceは文字を小文字に変換します。 lookup-keyはこのような変換を行わないことに注意してください。

関数read-key-sequenceは、ある種のマウスイベントも変換します。 バインディングのないドラッグイベントをクリックイベントに変換したり、 バインディングのないボタン押し下げイベントを完全に無視します。 さらに、フォーカスイベントとその他のウィンドウイベントを並び替えて、 それらが他のイベントのキー列の途中に現れないようにします。

マウスイベントが、モード行やスクロールバーなどのウィンドウの特別な部分で 生起しても、特別なイベント型はなく、マウスボタンや修飾キーの 組み合わせを普通どおりに表したシンボルです。 ウィンドウのどの部分かに関する情報は、 イベント内の別の部分、つまり、座標に入っています。 しかし、read-key-sequenceは、その情報を シンボルmode-linevertical-linehorizontal-scroll-barvertical-scroll-barを用いた仮想的な『プレフィックスキー』に変換します。 ウィンドウの特別な部分におけるマウスクリックの意味は、 これらの仮想的なプレフィックスキーを用いてキー列を定義することで 定義できます。

たとえば、read-key-sequenceを呼び出してから、 ウィンドウのモード行でクリックすると、 つぎのような2つのイベントを得ます。

(read-key-sequence "Click on the mode line: ")
     => [mode-line
         (mouse-1
          (#<window 6 on NEWS> mode-line
           (40 . 63) 5959987))]

num-input-keys Variable
この変数の値は、現在のEmacsセッションにおいて、 これまでに処理されたキー列の個数である。 これには、端末から読み取ったキー列、および、 実行したキーボードマクロから読み取ったキー列が含まれる。

num-nonmacro-input-events Variable
この変数は、端末からこれまでに受け取った入力イベントの総個数を保持する。 キーボードマクロで生成されたものは含まない。


Node:Reading One Event, Next:, Previous:Key Sequence Input, Up:Reading Input

単一イベントの読み取り

コマンド入力用の最低レベルの関数は、単一イベントを読み取る関数です。

read-event &optional prompt suppress-input-method Function
この関数は、必要ならばイベントの到着を待って、 コマンド入力のつぎのイベントを読み取って返す。 イベントは、ユーザーか(実行中の)キーボードマクロから直接得る。

promptnil以外であると、 これはプロンプトとしてエコー領域に表示される文字列であること。 さもなければ、read-eventは 入力待ちであることを示すメッセージを表示せずに、 そのかわりに、現在のコマンドを実行するに至ったイベントや 現在のコマンドが読み取ったイベントをプロンプトとして表示する。 see The Echo Area

suppress-input-methodnil以外であると、 このイベントの読み取りに関しては現在の入力方式を使わない。 入力方式の処理をせずにイベントを読みたいときには、 つねにこのようにすること。 input-method-functionを束縛してはならない(下記参照)。

変数cursor-in-echo-areanil以外であると、 read-eventは、エコー領域に表示されたメッセージの末尾に カーソルを一時的に移動する。 さもなければ、read-eventはカーソルを移動しない。

read-eventがヘルプ文字と定義されたイベントを受け取ると、 それを返さずにread-eventがイベントを直接処理してしまう場合がある。 see Help Functions特殊イベント(special event)と呼ばれる他のイベントも read-eventが直接処理する(see Special Events)。

read-eventを呼んで右矢印のファンクションキーを押すとつぎのようになる。

(read-event)
     => right

read-char Function
この関数はコマンド入力の文字を読み取りそれを返す。 文字を得るまで、文字以外のイベントはすべて破棄する。

最初の例では、ユーザーは文字1ASCIIコード49)を打つ。 2番目の例は、eval-expressionを使って ミニバッファからread-charを呼び出すキーボードマクロの定義である。 read-charはキーボードマクロの直後の文字、つまり、1を読む。 そして、eval-expressionはその戻り値をエコー領域に表示する。

(read-char)
     => 49

;; これを評価するために読者はM-:を使うと仮定する
(symbol-function 'foo)
     => "^[:(read-char)^M1"
(execute-kbd-macro 'foo)
     -| 49
     => nil

read-eventは、あれば現在の入力方式も起動します。 input-method-functionnil以外であれば、 それは関数であるはずです。 read-eventが修飾ビットのない(<SPC>を含む)印字文字を読み取ると、 引数としてイベントを渡してその関数を呼び出します。

input-method-function Variable
これがnil以外であると、その値は現在の入力方式関数を指定する。

注意: この変数をletで束縛しないこと。 この変数はしばしばバッファローカルであり、 入力を読む周囲で束縛すると(読者がこれをもっとも束縛しそうなところ)、 Emacsが入力を待っているときにバッファが非同期に切り替わると、 誤ったバッファに値を復元してしまうことがある。

入力方式関数は、入力として使われるイベントのリストを返すべきです。 (リストがnilであると入力がなかったことを意味し、 read-eventは別のイベントを待つ。) これらのイベントは、 unread-command-events内のイベントよりまえに処理されます。 入力方式関数が返したイベントは、それらが修飾ビットがない印字文字であっても、 入力方式関数に再度渡されることはありません。

入力方式関数がread-eventread-key-sequenceを呼び出すときには、 input-method-functionnilに束縛して 再帰呼び出しを防ぐべきです。

キー列の2番目以降のイベントを読むときには、入力方式関数を呼び出しません。 したがって、それらの文字は、入力方式処理の対象ではありません。 入力方式の処理では、 overriding-local-mapoverriding-terminal-local-mapの値を 検査するのがよいです。 これらの変数のいずれかがnil以外であるときには、 入力方式ではその引数をリストに入れ、 それ以上処理せずにそのリストを返すべきです。


Node:Quoted Character Input, Next:, Previous:Reading One Event, Up:Reading Input

クォートした文字の入力

ユーザーに文字入力を促して、コントロール文字やメタ文字を 文字そのものや文字の8進数コードで手軽に入力できるようにするには、 関数read-quoted-charを使います。 コマンドquoted-insertは、この関数を使っています。

read-quoted-char &optional prompt Function
この関数はread-charに似ているが、 最初に読んだ文字が8進数字文字(0-7)であると、 任意個数の8進数字文字を読み取り(8進数字文字以外が現れると止める)、 その数値の文字コードが表す文字を返す。

最初の文字を読むと中断を抑制するので、 ユーザーはC-gを入力できる。 see Quitting

promptを与えると、それはユーザーへのプロンプトを表す文字列を指定する。 プロンプト文字列はつねにエコー領域に表示され、あとに-が続く。

つぎの例では、ユーザーは8進数177(10進数では127)を打つ。

(read-quoted-char "What character")

---------- Echo Area ----------
What character-177
---------- Echo Area ----------

     => 127


Node:Event Input Misc, Previous:Quoted Character Input, Up:Reading Input

その他のイベント入力機能

本節では、イベントを処理せずに『まえもって覗き見』する方法、 処理待ちの入力の有無の検査方法、処理待ちの入力の破棄方法について述べます。 関数read-passwdも参照してください(see Reading a Password)。

unread-command-events Variable
この変数は、コマンド入力として読まれることを 待っているイベントのリストを保持する。 イベントはリストに現れる順に使われ、使われると1つ1つ取り除かれる。

関数でイベントを読んだあとにそれを使わない場面があるため、 この変数が必要になる。 この変数にイベントを保存すると、 コマンドループやコマンド入力を読む関数によって通常どおり処理される。

たとえば、数値前置引数を実現する関数は、任意個数の数字文字を読み取る。 数字文字でないイベントをみつけたら、そのイベントを読み戻して、 コマンドループが通常どおりに読めるようにする必要がある。 同様に、インクリメンタルサーチでは、この機能を使って 探索においては意味を持たないイベントを読み戻す。 なぜなら、そのようなイベントは探索を終了させ、 通常どおり実行される必要があるからである。

unread-command-eventsに入れられるように キー列からイベントを確実に簡単に取り出す方法は listify-key-sequenceを使うことである(see Strings of Events)。

もっとも最近に読み戻したイベントが最初に再度読まれるように、 普通はこのリストの先頭にイベントを追加する。

listify-key-sequence key Function
この関数は、文字列やベクトルであるkeyを個々のイベントのリストに変換する。 この結果はunread-command-eventsに入れられる。

unread-command-char Variable
この変数は、コマンド入力として読まれる文字を保持する。 値「-1」は、『空』を意味する。

この変数はほとんど廃れており、 かわりにunread-command-eventsを使うべきである。 Emacs 18版以前向けに書かれたプログラムを扱うためだけに存在する。

input-pending-p Function
この関数は、現在、コマンド入力があるかどうかを調べる。 ただちに返るが、入力があれば値tを、 さもなければnilを返す。 入力がないのにtを返すことが稀にある。

last-input-event Variable
last-input-char Variable
この変数は、コマンドの一部として、あるいは、Lispプログラムが明示的に 読み取った最後の端末入力イベントを記録する。

以下の例で、Lispプログラムは文字1ASCIIコード49)を読む。 それがlast-input-eventの値になるが、 (この式を評価するコマンドはC-x C-eと仮定するので) last-command-eventの値はC-eのままである。

(progn (print (read-char))
       (print last-command-event)
       last-input-event)
     -| 49
     -| 5
     => 49

Emacs 18版との互換性のために、別名last-input-charが存在する。

discard-input Function
この関数は端末入力バッファの内容を廃棄し、 定義中のキーボードマクロを取り消す。 これはnilを返す。

以下の例で、フォームを評価しはじめてから、ユーザーは何文字か打つ。 sleep-forが待機を終えると、 discard-inputは待機中に打たれた文字をすべて破棄する。

(progn (sleep-for 2)
       (discard-input))
     => nil


Node:Special Events, Next:, Previous:Reading Input, Up:Command Loop

特殊イベント

特殊イベントは、読まれるとただちに非常に低レベルで処理されます。 関数read-eventはこれらのイベントをそれ自身で処理してしまい、 それらを返すことはありません。

このように処理されるイベントは表示されることはなく、 キー列に組み込まれることもなく、 last-command-event(this-command-keys)の値に 現れることもありません。 特殊イベントが数値引数を破棄することはなく、 unread-command-eventsで読み戻すことはできません。 特殊イベントがキーボードマクロに現れることはなく、 読者がキーボードマクロを定義しているときに、 特殊イベントがキーボードマクロに記録されることはありません。

しかし、それらのイベントは、 読まれた直後にはlast-input-eventに現れますから、 これからイベントの定義で実際のイベントを見ることができます。

iconify-framemake-frame-visibledelete-frameの イベント型は、通常このように処理されます。 特殊イベントをどのように処理するか、 どのイベントが特殊イベントであるかを定義する キーマップは変数special-event-mapにあります(see Active Keymaps)。


Node:Waiting, Next:, Previous:Special Events, Up:Command Loop

時間待ちと入力待ち

待機関数は、指定時間経過するか入力がくるまで待つように設計してあります。 たとえば、ユーザーに表示を眺める時間を与えるために 計算途中で休止したいでしょう。 sit-forは、休止してスクリーンを更新し、 入力がくるとただちに戻ります。 一方、sleep-forはスクリーンを更新せずに休止します。

sit-for seconds &optional millisec nodisp Function
この関数は(処理待ちのユーザーからの入力がなければ)再表示を行い、 seconds秒休止するか、入力がくるまで待つ。 入力がこずに(Event Input Miscinput-pending-pを参照) 指定時間だけ休止した場合は、戻り値はtである。 さもなければ、戻り値はnilである。

引数secondsは整数である必要はない。 それが浮動小数点数であると、sit-forは秒の小数も待つ。 秒単位しか扱えないシステムもあり、 そのようなシステムではsecondsを秒に切り下げる。

省略可能な引数millisecは、ミリ秒単位の追加待ち時間を指定する。 これはsecondsで指定した時間に加えられる。 秒未満を扱えないシステムでは、 millisecに0以外を指定するとエラーになる。

入力がくると再表示をつねに取り止め、 再表示開始まえに入力がくると、いっさい再表示しない。 したがって、処理待ちの入力があると、再表示を強制する方法はない。 しかし、処理待ちの入力がなければ、(sit-for 0)で再表示を強制できる。

nodispnil以外であると、 sit-forは再表示はしないが、 入力がくるとただちに(あるいは指定時間だけ経過すると)戻る。

フレームをアイコンにしたりアイコンにしたフレームを開くと イベントが生成されるため、sit-forは戻る。 see Misc Events

sit-forの普通の目的は、 読者が表示したテキストを読む時間をユーザーに与えることである。

sleep-for seconds &optional millisec Function
この関数は表示を更新せずに単にseconds秒だけ休止する。 入力にはいっさい注意を払わない。 nilを返す。

引数secondsは整数である必要はない。 それが浮動小数点数であると、sleep-forは秒の小数も待つ。 秒単位しか扱えないシステムもあり、 そのようなシステムではsecondsを秒に切り下げる。

省略可能な引数millisecは、ミリ秒単位の追加待ち時間を指定する。 これはsecondsで指定した時間に加えられる。 秒未満を扱えないシステムでは、 millisecに0以外を指定するとエラーになる。

遅延を保証したい場合にsleep-forを使う。

現在時刻を取得する関数についてはSee Time of Day


Node:Quitting, Next:, Previous:Waiting, Up:Command Loop

中断

Lisp関数が動作中にC-gを打つと、 Emacsがなにを行っていても中断を引き起こします。 つまり、もっとも内側の活性なコマンドループに制御が戻ります。

コマンドループがキーボード入力を待っているときにC-gを打っても、 中断を引き起こさずに、普通の入力文字として動作します。 もっとも単純な場合、C-gはコマンドkeyboard-quitを実行しますが、 その効果は中断を引き起こすことですから、読者には区別できないはずです。 しかし、プレフィックスキーに続けてC-gを打つと、 それらは組み合わされて未定義キーになります。 その効果は、前置引数を含めてプレフィックスキーを取り消します。

ミニバッファでは、C-gには別の定義があって、 ミニバッファを強制終了させます。 つまり、ミニバッファから抜け出て中断します。 (単に中断したのでは、ミニバッファ内で コマンドループに戻るだけである。) コマンドループで入力を読んでいるときにC-gで直接中断しない理由は、 このようにミニバッファでその意味を再定義できるようにするためです。 ミニバッファでは、プレフィックスキーに続くC-gは再定義してなく、 プレフィックスキーと前置引数を取り消すという通常の効果を持ちます。 C-gがつねに直接中断するのでは、このようにすることさえ不可能です。

C-gが直接に中断するときには、 変数quit-flagtを設定します。 Emacsはこの変数を適切なときに検査しnilでないと中断します。 したがって、quit-flagnil以外を設定すると 中断を引き起こします。

Cのコードのレベルでは、どこでも中断できるわけではありません。 quit-flagを検査している特別な箇所だけです。 このようにするのは、それ以外の箇所で中断すると Emacsの内部状態に矛盾をきたす可能性があるからです。 中断は安全な場所まで延期されるので、 中断によってEmcasがクラッシュすることはありません。

read-key-sequenceread-quoted-charなどのある種の関数は、 入力を待っている場合であっても中断を完全に抑制します。 中断するかわりに、C-gは入力として働きます。 read-key-sequenceの場合、コマンドループにおいて C-gの特別なふるまいをもたらします。 read-quoted-charの場合、 C-qC-gをクォートできるようになります。

変数inhibit-quitnil以外の値を束縛することで Lisp関数のある部分において中断を抑制できます。 そうすると、C-gはそれでもいつもどおり quit-flagtにしますが、 その通常の結果である中断は抑制されます。 最終的にフォームletの終りで束縛が解除されるなどして inhibit-quitが再度nilになります。 その時点でもquit-flagnil以外であると 要求した中断がただちに起こります。 このふるまいは、プログラムの『臨界領域』では 中断が起こらないことを保証する理想的なものです。

read-quoted-charなどの)ある種の関数では、 C-gは特別に処理され中断を引き起こしません。 inhibit-quittを束縛して入力を読み取り、 inhibit-quitが再度nilになるまえに quit-flagnilにすることでそのようにします。 これをread-quoted-charの定義の以下の抜粋で示しましょう。 最初の入力文字のあとで通常の中断を許す方法も示しています。

(defun read-quoted-char (&optional prompt)
  "...documentation..."
  (let ((message-log-max nil) done (first t) (code 0) char)
    (while (not done)
      (let ((inhibit-quit first)
            ...)
	(and prompt (message "%s-" prompt))
	(setq char (read-event))
	(if inhibit-quit (setq quit-flag nil)))
      ...変数codeに設定する...)
    code))

quit-flag Variable
inhibit-quitnilであれば、 この変数がnil以外であるとEmacsはただちに中断する。 C-gは、inhibit-quitに関わらず、 通常、quit-flagnil以外を設定する。

inhibit-quit Variable
この変数は、quit-flagnil以外の値に設定されたときに Emacsが中断すべきかどうかを決定する。 inhibit-quitnil以外であると、 quit-flagに特別な意味はない。

keyboard-quit コマンド
この関数は(signal 'quit nil)quit条件を通知する。 これは中断と同じことを行う。 (Errorssignalを参照。)

中断として使うC-g以外の特殊文字を使えます。 Terminal Inputの関数set-input-modeを参照してください。


Node:Prefix Command Arguments, Next:, Previous:Quitting, Up:Command Loop

前置コマンド引数

Emacsのほとんどのコマンドは、前置引数(prefix argument)、 つまりコマンド自身のまえに指定された数を利用できます。 (前置引数とプレフィックスキーを混同しないこと。) 前置引数はつねに値で表現され、 nilであると現在は前置引数がないことを表します。 各コマンドは、前置引数を使ってもよいし、無視してもかまいません。

前置引数には2つの表現方法があります。 (raw)と数値(numeric)です。 エディタコマンドループでは、内部的には生の表現を使い、 その情報を保持するLisp変数もそのようにしますが、 コマンドではどちらの表現を要求してもかまいません。

生の前置引数の値にはつぎの可能性があります。

いろいろな前置引数でつぎの関数を呼び出す例を示します。

(defun display-prefix (arg)
  "Display the value of the raw prefix arg."
  (interactive "P")
  (message "%s" arg))

以下は、生の前置引数でdisplay-prefixを呼び出した結果です。

        M-x display-prefix  -| nil

C-u     M-x display-prefix  -| (4)

C-u C-u M-x display-prefix  -| (16)

C-u 3   M-x display-prefix  -| 3

M-3     M-x display-prefix  -| 3      ; (C-u 3と同じ)

C-u -   M-x display-prefix  -| -

M--     M-x display-prefix  -| -      ; (C-u -と同じ)

C-u - 7 M-x display-prefix  -| -7

M-- 7   M-x display-prefix  -| -7     ; (C-u -7と同じ)

Emacsは、前置引数を保持するために2つの変数、 prefix-argcurrent-prefix-argを使います。 他のコマンド向けに前置引数を設定するuniversal-argumentなどの コマンドは、前置引数をprefix-argに保持します。 対照的に、current-prefix-argには 現在のコマンドに対して前置引数を運ぶ役割があり、 この変数に設定しても以後のコマンドに対する前置引数には なんの効果もありません。

通常、コマンドは、interactive宣言により、 「生」か「数値」のいずれの表現の前置引数を使うか指定します。 (See Using Interactive。) あるいは、変数current-prefix-argにある前置引数の値を 関数から直接見てもかまいませんが、 これは見通しのよい方法ではありません。

prefix-numeric-value arg Function
この関数は、有効な生の前置引数の値argからそれに等価な数値を返す。 引数は、シンボル、数、リストのいずれかである。 それがnilであると、戻り値は1である。 -であると、戻り値は-1である。 数であると、その数を返す。 リストであると、リストの(数であるはずの)CARを返す。

current-prefix-arg Variable
この変数は、現在のコマンドに対する生の前置引数を保持する。 コマンドが直接この変数を調べてもよいが、 前置引数を参照する普通の方法は(interactive "P")を使うことである。

prefix-arg Variable
この変数の値は、つぎの編集コマンド向けの生の前置引数である。 後続のコマンド向けの前置引数を指定するuniversal-argumentなどの コマンドは、この変数に設定することで動作する。

last-prefix-arg Variable
まえのコマンドで使われた生の前置引数の値。

つぎのコマンドは、後続のコマンド向けの前置引数を設定するためのものです。 それ以外の目的には呼ばないでください。

universal-argument コマンド
このコマンドは入力を読み取り、後続のコマンド向けの前置引数を指定する。 なにをしているか理解していない限り、読者自身でこのコマンドを呼ばないこと。

digit-argument arg コマンド
このコマンドは、後続のコマンド向けの前置引数に追加する。 引数argは、このコマンドが呼び出されるまえの生の前置引数であり、 前置引数を更新する計算に使われる。 なにをしているか理解していない限り、読者自身でこのコマンドを呼ばないこと。

negative-argument arg コマンド
このコマンドは、後続のコマンド向けの数値前置引数に追加する。 引数argは、このコマンドが呼び出されるまえの生の前置引数であり、 その値の符号を変えて新たな前置引数とする。 なにをしているか理解していない限り、読者自身でこのコマンドを呼ばないこと。


Node:Recursive Editing, Next:, Previous:Prefix Command Arguments, Up:Command Loop

再帰編集

Emacsが動作を始めると、Emacsのコマンドループに自動的に入ります。 このトップレベルのコマンドループからはけっして抜けることはなく、 Emacsが動いている限り動作し続けます。 Lispプログラムからコマンドループを起動することもできます。 そうすると、活性なコマンドループが複数作られることになるので、 それを再帰編集(recursive editing)と呼びます。 再帰編集レベルには、それを起動したコマンドを一時休止させ、 当該コマンドを再開するまでユーザーにどんな編集でも許す効果があります。

再帰編集中に利用可能なコマンドは、トップレベルのコマンドループと 同じものでありキーマップで定義されます。 再帰編集を抜けるための数個の特別なコマンドがあり、 完了すると再帰編集レベルから抜ける別のコマンドもあります。 (再帰編集を抜けるコマンドはつねに利用可能であるが、 再帰編集中でないとなにも行わない。)

再帰編集を含むすべてのコマンドループでは、 コマンドループから実行したコマンドのエラーによって コマンドループから抜け出さないように汎用目的のエラーハンドラを設定します。

ミニバッファでの入力は、特別な種類の再帰編集です。 これには、ミニバッファやミニバッファ用ウィンドウを表示するなどの特別な 処理がありますが、読者が考えるよりは少ないのです。 ミニバッファでは特別なふるまいをするキーもありますが、 それらはミニバッファのローカルマップによるものです。 ウィンドウを切り替えると、Emacsの普通のコマンドを使えます。

再帰編集レベルを起動するには、関数recursive-editを呼び出します。 この関数にはコマンドループが含まれています。 さらに、exitを伴ったcatchの呼び出しもあり、 これにより、exitへ投げることで 再帰編集レベルから抜け出せるようになっています (see Catch and Throw)。 t以外の値を投げると、recursive-editは、 呼び出し側の関数へ普通に戻ります。 コマンドC-M-cexit-recursive-edit)は、これを行います。 値tを投げるとrecursive-editに中断を引き起こし、 1つ上のレベルのコマンドループへ制御を戻します。 これを強制終了(aborting)と呼び、 C-]abort-recursive-edit)で行えます。

ミニバッファを使う場合を除いて、ほとんどのアプリケーションでは 再帰編集を使うべきではありません。 カレントバッファのメジャーモードを 一時的な特別なメジャーモードに変更するほうが、 一般にはユーザーにとってより便利です。 ただし、当該メジャーモードには、 まえのモードに戻るコマンドを用意しておきます。 (rmailのコマンドeは、この方式を使っている。) あるいは、『再帰的に』編集する別のテキストをユーザーに与えたい場合には、 特別なモードの新たなバッファを作成してそれを選択します。 当該モードには、処理を終えてまえのバッファに戻るコマンドを 定義しておきます。 (rmailのコマンドmは、このようにする。)

再帰編集はデバッグに便利です。 ブレークポイントの一種として関数定義に debugの呼び出しを挿入しておくと、 その箇所に達したときにいろいろと調べられます。 debugは再帰編集を起動しますが、デバッガとしての機能も提供します。

query-replaceC-rを打ったり、 C-x qkbd-macro-query)を使ったときにも 再帰編集レベルが使われます。

recursive-edit Function
この関数はエディタコマンドループを起動する。 Emacsの初期化過程で自動的に呼び出され、ユーザーが編集できるようにする。 Lispプログラムから呼ばれると、再帰編集レベルに入る。

以下の例では、関数simple-recは、まず1単語分ポイントを進め、 エコー領域にメッセージを表示して再帰編集に入る。 そうすると、ユーザーは望むことはなんでもできるようになり、 (再帰編集を)抜けるためにC-M-cを打つと、 simple-recの実行を継続する。

(defun simple-rec ()
  (forward-word 1)
  (message "Recursive edit in progress")
  (recursive-edit)
  (forward-word 1))
     => simple-rec
(simple-rec)
     => nil

exit-recursive-edit コマンド
この関数は、(ミニバッファでの入力を含む)もっとも内側の再帰編集から抜ける。 その関数定義は実質的には(throw 'exit nil)である。

abort-recursive-edit コマンド
この関数は、再帰編集から抜けたあとでquitを通知することで、 (ミニバッファでの入力を含む)もっとも内側の再帰編集を 要請したコマンドを強制終了する。 その関数定義は実質的には(throw 'exit t)である。 see Quitting

top-level コマンド
この関数は、すべての再帰編集を抜ける。 すべての計算を抜け出てメインのコマンドループへ直接戻るため、値は返さない。

recursion-depth Function
この関数は再帰編集の現在の深さを返す。 活性な再帰編集がなければ0を返す。


Node:Disabling Commands, Next:, Previous:Recursive Editing, Up:Command Loop

コマンドを禁止する

コマンドを禁止するとは、 コマンドを実行するまえにユーザーの確認を必要とするように コマンドに印を付けることです。 コマンドを禁止するのは、 初心者に混乱をもたらす可能性のあるコマンドに対してや、 コマンドの誤用を防ぐためです。

コマンドを禁止する低レベルの機構は、 コマンドのLispシンボルにnil以外の属性disabledを入れることです。 これらの属性は、通常、ユーザーの.emacsファイルにて つぎのようなLisp式で設定します。

(put 'upcase-region 'disabled t)

数個のコマンドにはデフォルトでこれらの属性がありますから、 .emacsファイルで属性を取り除きます。

属性disabledの値は文字列であり、 コマンドを禁止したことを表すメッセージです。 たとえばつぎのとおりです。

(put 'delete-region 'disabled
     "Text deleted this way cannot be yanked back!\n")

禁止したコマンドを対話的に起動するとどうなるかについて 詳しくはSee Disabling。 コマンドを禁止しても、Lispプログラムから関数として呼び出すことには なんの影響もありません。

enable-command command コマンド
これ以降、特別な確認なしにcommandを実行可能にする。 さらに(ユーザーが了承すれば)ユーザーの.emacsファイルを変更して、 将来のセッションでもそのようにする。

disable-command command コマンド
これ以降、commandの実行には特別な確認を必要とするようにする。 さらに(ユーザーが了承すれば)ユーザーの.emacsファイルを変更して、 将来のセッションでもそのようにする。

disabled-command-hook Variable
禁止したコマンドをユーザーが対話的に起動したとき、 禁止したコマンドのかわりにこのノーマルフックを実行する。 フック関数では、this-command-keysを使って コマンドを実行するためにユーザーがなにを入力したかを調べ、 コマンドそのものを探し出せる。 see Hooks

デフォルトでは、disabled-command-hookには、 ユーザーに処理を進めるかどうかを問い合わせる関数が入っている。


Node:Command History, Next:, Previous:Disabling Commands, Up:Command Loop

コマンド履歴

コマンドループでは、実行した複雑なコマンドの履歴を管理していて、 それらのコマンドを簡単に繰り返せるようにしています。 複雑なコマンドとは、ミニバッファを使って引数を読むコマンドです。 これには、任意のM-xコマンド、任意のM-:コマンド、 ミニバッファから引数を読み取るinteractive指定を持つ任意のコマンドが 含まれます。 コマンド自身の実行中に明示的にミニバッファを使っても、 複雑なコマンドとはみなしません。

command-history Variable
この変数の値は、最近使った複雑なコマンドのリストであり、 各要素は評価すべきフォームを表す。 編集セッション中は、すべての複雑なコマンドを集積するが、 (変数history-lengthで指定される)最大サイズに達すると 新しい要素を追加するたびに古い要素を削除する。
command-history
=> ((switch-to-buffer "chistory.texi")
    (describe-key "^X^[")
    (visit-tags-table "~/emacs/src/")
    (find-tag "repeat-complex-command"))

この履歴リストは、実際にはミニバッファ履歴(see Minibuffer History) の特別な場合です。 要素は文字列ではなく式なのです。

まえのコマンドを編集したり取り出すための専用コマンドがたくさんあります。 コマンドrepeat-complex-commandlist-command-historyは、 ユーザーマニュアル (see Repetition)に説明してあります。 ミニバッファ内では、通常のミニバッファ履歴コマンドを使えます。


Node:Keyboard Macros, Previous:Command History, Up:Command Loop

キーボードマクロ

キーボードマクロは、 コマンドとみなせる入力イベントのまとまった列であり、 キーの定義から構成されます。 Lispにおけるキーボードマクロの表現は、 イベントを含んだ文字列やベクトルです。 キーボードマクロとLispマクロ(see Macros)を混同しないでください。

execute-kbd-macro kbdmacro &optional count Function
この関数はキーボードマクロkbdmacroをイベント列として実行する。 kbdmacroが文字列かベクトルであると、 その中のイベントをユーザーが入力した場合とまったく同様に実行する。 列は単一のキーイベントである必要はない。 通常、キーボードマクロの定義は、複数のキー列を連結したものである。

kbdmacroがシンボルであると、 kbdmacroのかわりにその関数定義を用いる。 それがさらに別のシンボルであると、この処理を繰り返す。 最終的な結果は、文字列かベクトルであること。 結果がシンボルでも文字列でもベクトルでもないと、 エラーを通知する。

引数countは繰り返し回数であり、 kbdmacroをその回数だけ実行する。 countを省略するかnilであると、kbdmacroを1回実行する。 countが0であると、 kbdmacroの実行をエラーに出会うか探索に失敗するまで繰り返す。

execute-kbd-macroを使った例についてはsee Reading One Event

executing-macro Variable
この変数は、現在実行中のキーボードマクロの定義である 文字列やベクトルを保持する。 これがnilであると、現在実行中のマクロはない。 コマンドでこの変数を検査することで、 マクロ実行で起動されたときのふるまいを変更できる。 読者自身はこの変数に設定しないこと。

defining-kbd-macro Variable
この変数は、キーボードマクロを定義中かどうかを表す。 コマンドでこの変数を検査することで、マクロ定義中のふるまいを変更できる。 コマンドstart-kbd-macroend-kbd-macroがこの変数に設定する。 読者自身は設定しないこと。

この変数は現在の端末に対してつねにローカルであり、 バッファに対してローカルにはならない。 see Multiple Displays

last-kbd-macro Variable
この変数は、もっとも最近に定義されたキーボードマクロの定義である。 その値は、文字列かベクトル、あるいは、nilである。

この変数は現在の端末に対してつねにローカルであり、 バッファに対してローカルにはならない。 see Multiple Displays


Node:Keymaps, Next:, Previous:Command Loop, Up:Top

キーマップ

入力イベントとコマンドとのバインディング(対応)は、 キーマップ(keymap)と呼ばれるデータ構造に記録されています。 キーマップの各バインディング(あるいはバインド(bind))は、 個々のイベント型を別のキーマップかコマンドに対応付けます。 イベント型のバインディングがキーマップであると、 後続の入力イベントを探すためにそのキーマップを使います。 コマンドがみつかるまで、これを繰り返します。 この処理全体をキー探索(key lookup)と呼びます。


Node:Keymap Terminology, Next:, Up:Keymaps

キーマップの用語

キーマップ(keymap)は、イベント型を定義に対応させる表です。 (この定義は任意のLispオブジェクトであるが、 コマンドループによる実行においては、特定の型のみが意味を持つ)。 与えられたイベント(あるいはイベント型)とキーマップから、 Emacsはイベントの定義を得ることができます。 イベントは、文字、ファンクションキー、マウス操作です (see Input Events)。

ある単位を構成する入力イベントの列をキー列(key sequence)、 あるいは、略してキー(key)と呼びます。 単一イベントから成る列はつねにキー列であり、複数イベント列もキー列です。

キーマップは、任意のキー列に対するバインディング、 つまり、定義を決定します。 キー列が単一イベントから成るとき、 そのバインディングはキーマップ内の当該イベントの定義です。 複数のイベントから成るキー列のバインディングは、 繰り返し処理で探します。 つまり、最初のイベントのバインディングを探すと、 それはキーマップであるはずです。 続いて、そのキーマップから2番目のイベントのバインディングを探します。 これをキー列のすべてのイベントを使い尽くすまで行います

キー列のバインディングがキーマップであると、 そのキー列をプレフィックスキー(prefix key)と呼びます。 さもなければ、(追加できるイベントがないので) 完全なキー(complete key)と呼びます。 バインディングがnilであると、キーは未定義であるといいます。 プレフィックスキーの例は、C-cC-xC-x 4です。 定義されている完全なキーの例は、X、<RET>、C-x 4 C-fです。 未定義な完全なキーの例は、C-x C-gC-c 3です。 詳しくは、See Prefix Keys

キー列のバインディングを探す際の規則では、 (最後のイベントのまえまでにみつかる)途中のバインディングは すべてキーマップであると仮定します。 これが満たされないと、イベントの列があるまとまりを構成せず、 1つのキー列になりません。 いいかえれば、有効なキー列の末尾からいくつかのイベントを取りさると、 つねにプレフィックスキーになる必要があります。 たとえば、C-f C-nはキー列ではありません。 C-fはプレフィックスキーではないので、 C-fで始まる列はキー列ではありません。

複数イベントから成るキー列の候補は、 プレフィックスキーのバインディングに依存します。 したがって、キーマップが異なればそれらは異なり、 バインディングを変更するとそれらは変わります。 しかし、単一イベントから成る列は、プレフィックスに依存しないので、 つねにキー列です。

ある時点には、複数個の主キーマップが活性です。 つまり、キーバインディングの探索に使われます。 それらは、 すべてのバッファが共有するグローバルマップ(global map)、 特定のメジャーモードに関連付けられたローカルマップ(local keymap)、 現在オンにしてあるマイナモードに属する マイナモードキーマップ(minor mode keymaps)です。 (すべてのマイナモードにキーマップがあるわけではない。) ローカルキーマップのバインディングは、 対応するグローバルなバインディングを隠します(つまり優先する)。 マイナモードキーマップは、ローカルとグローバルの両方のキーマップを隠します。 詳しくはSee Active Keymaps


Node:Format of Keymaps, Next:, Previous:Keymap Terminology, Up:Keymaps

キーマップの形式

キーマップは、そのCARがシンボルkeymapであるリストです。 リストの残りの要素がキーマップのキーバインディングを定義します。 オブジェクトがキーマップであるかどうか検査するには、 関数keymapp(下記参照)を使います。

キーマップでは、シンボルkeymapのうしろに、 さまざまな種類の要素が現れます。

(type . binding)
イベント型typeに対する1つのバインディングを指定する。 普通の各バインディングは、文字やシンボルである特定のイベント型に 適用される。 see Classifying Events
(t . binding)
デフォルトのキーバインディングを指定する。 キーマップの他の要素に一致しない任意のイベントには、 そのバインディングとして指定したbindingを与える。 デフォルトのバインディングにより、 すべてを列挙せずに可能なすべてのイベントにバインドできる。 デフォルトのバインディングを有するキーマップは、 任意の低優先順位のキーマップを隠してしまう。
vector
キーマップの要素がベクトルであると、 当該ベクトルをASCII文字全体、つまり、コード0から127に対する バインディングとみなす。 ベクトルのn番目の要素は、コードnの文字に対する バインディングである。 これは、多くのバインディングを記録するコンパクトな方法である。 このようなベクトルのキーマップを完全なキーマップ(full keymap)と呼ぶ。 それ以外のキーマップを疎なキーマップ(sparse keymaps)と呼ぶ。

キーマップにベクトルがあると、ベクトルの要素がnilであっても ベクトルが各ASCII文字のバインディングをつねに定義する。 そのようなnilのバインディングは、 ASCII文字に対しては キーマップのデフォルトのキーバインディングを無効にする。 しかし、ASCII文字以外のイベントに対しては、 デフォルトのバインディングが意味を持つ。 nilのバインディングが 低優先順位のキーマップを隠すことはない。 つまり、ローカルマップがnilのバインディングを与えると、 Emacsはグローバルマップのバインディングを使う。

string
バインディングに加えて、 キーマップでは、要素として文字列を持つこともできる。 これを全面プロンプト文字列(overall prompt string)と呼び、 キーマップをメニューとして使うことを可能にする。 see Menu Keymaps

キーマップは、メタ文字に対するバインディングを直接には記録していません。 そのかわりに、キー探索においては、メタ文字は2文字から成る列とみなし、 先頭文字は<ESC>(あるいは、meta-prefix-charの現在値)です。 つまり、キーM-aは実際には<ESC> aと表現され、 そのグローバルなバインディングは esc-mapaでみつかります(see Prefix Keys)。

Lispモードに対するローカルキーマップの例を示します。 これは疎なキーマップです。 <DEL>、<TAB>、C-c C-lM-C-qM-C-xに対する バインディングを定義しています。

lisp-mode-map
=>
(keymap
 ;; <TAB>
 (9 . lisp-indent-line)
 ;; <DEL>
 (127 . backward-delete-char-untabify)
 (3 keymap
    ;; C-c C-l
    (12 . run-lisp))
 (27 keymap
     ;; M-C-q<ESC> C-qとみなされる
     (17 . indent-sexp)
     ;; M-C-x<ESC> C-xとみなされる
     (24 . lisp-send-defun)))

keymapp object Function
この関数は、objectがキーマップであればtを返し、 さもなければnilを返す。 より正確には、この関数は、 そのCARkeymapであるリストかどうかを検査する。
(keymapp '(keymap))
    => t
(keymapp (current-global-map))
    => t


Node:Creating Keymaps, Next:, Previous:Format of Keymaps, Up:Keymaps

キーマップの作成

ここでは、キーマップを作成するための関数について述べます。

make-keymap &optional prompt Function
この関数は新たに完全なキーマップ (つまり、すべてのASCII文字に対する定義を収めた 長さ128のベクトル)を作成しそれを返す。 新たなキーマップでは、すべてのASCII文字に対するバインディングは nilであり、それ以外の種類のイベントに対するバインディングはない。
(make-keymap)
    => (keymap [nil nil nil ... nil nil])

promptを指定すると、 それはキーマップに対する全面プロンプト文字列になる。 全面プロンプト文字列はメニューキーマップ (see Menu Keymaps)に有用である。

make-sparse-keymap &optional prompt Function
この関数は、新たに空の疎なキーマップを作成しそれを返す。 新たなキーマップにはイベントに対するバインディングはいっさいない。 引数promptは、make-keymapの場合同様、 プロンプト文字列を指定する。
(make-sparse-keymap)
    => (keymap)

copy-keymap keymap Function
この関数はkeymapのコピーを返す。 keymapにバインディングとして直接現れる任意のキーマップも 任意のレベルまで再帰的にコピーされる。 しかし、文字に対する定義が、その関数定義がキーマップであるような シンボルに出会うと再帰的なコピーを行わないため、 同じシンボルが新たなコピーにも現れる。
(setq map (copy-keymap (current-local-map)))
=> (keymap
     ;; (これはメタ文字を意味する)
     (27 keymap
         (83 . center-paragraph)
         (115 . center-line))
     (9 . tab-to-tab-stop))

(eq map (current-local-map))
    => nil
(equal map (current-local-map))
    => t


Node:Inheritance and Keymaps, Next:, Previous:Creating Keymaps, Up:Keymaps

継承とキーマップ

キーマップでは、親キーマップ(parent keymap)と呼ぶ別のキーマップの バインディングを継承できます。 そのようなキーマップはつぎのようになります。

(keymap bindings... . parent-keymap)

このキーマップは、キーを探索する時点において parent-keymapが有するすべてのバインディングを継承しますが、 それらにはbindingsが追加されたり優先します。

define-keyや他のキーバインディング関数でparent-keymapの バインディングを変更すると、それらの変更は、 bindingsで隠されない限り継承側のキーマップからも見えます。 その逆は真ではありません。 define-keyで継承側のキーマップを修正すると、 それはbindingsに影響するだけでparent-keymapには影響しません。

親キーマップを用いたキーマップを作成する正しい方法は、 set-keymap-parentを使うことです。 親キーマップを用いたキーマップを直接作成するようなコードがある場合には、 set-keymap-parentを用いるようにプログラムを変更してください。

keymap-parent keymap Function
この関数は、キーマップkeymapの親キーマップを返す。 keymapに親がなければkeymap-parentnilを返す。

set-keymap-parent keymap parent Function
キーマップkeymapの親キーマップとしてparentを設定し、 parentを返す。 parentnilであると、 この関数はkeymapに親キーマップをいっさい与えない。

keymapに(プレフィックスキー用のバインディングである) サブマップがあれば、それらもparentが指定するプレフィックスキーを 反映する新たな親マップを受け取る。

text-mode-mapからキーマップを継承する方法を示します。

(let ((map (make-sparse-keymap)))
  (set-keymap-parent map text-mode-map)
  map)


Node:Prefix Keys, Next:, Previous:Inheritance and Keymaps, Up:Keymaps

プレフィックスキー

プレフィックス(prefix key)とは、 そのバインディングがキーマップであるキー列のことです。 そのキーマップが、プレフィックスキー以降のキーでなにをするかを定義します。 たとえば、C-xはプレフィックスキーであり、 変数ctl-x-mapに保持されたキーマップを使います。 このキーマップは、C-xで始まるキー列に対するバインディングを定義します。

Emacsの標準プレフィックスキーのなかには、 Lisp変数にも保持されたキーマップを使うものがあります。

プレフィックスキーのキーマップバインディングは、 当該プレフィックスキーに続くイベントを探すために使われます。 (その関数定義がキーマップであるシンボルでもよい。 効果は同じであるが、シンボルはプレフィックスキーに対する名前として働く。) したがって、C-xのバインディングは シンボルControl-X-prefixであり、 その関数セルがコマンドC-x用のキーマップを保持している。 (ctl-x-mapの値も同じキーマップである。)

プレフィックスキーの定義は、任意の活性なキーマップにあってかまいません。 プレフィックスキーとしてのC-cC-xC-h、<ESC>の 定義はグローバルマップにあるので、これらのプレフィックスキーは つねに利用できます。 メジャーモードやマイナモードでは、 プレフィックスキーの定義をローカルキーマップや マイナモードキーマップに入れることで、 キーをプレフィックスとして再定義できます。 See Active Keymaps

複数の活性なキーマップにおいて、キーがプレフィックスと定義されていると、 さまざまな定義は実質的には併合されます。 マイナモードキーマップで定義されたコマンドが最優先で、 つぎにローカルマップのプレフィックス定義、 そしてグローバルマップのプレフィックス定義が続きます。

以下の例では、ローカルキーマップにおいて、 C-pC-xに等価なプレフィックスキーにします。 続いてC-p C-fのバインディングを C-x C-fのように関数find-fileにします。 キー列C-p 6はどの活性なキーマップでもみつかりません。

(use-local-map (make-sparse-keymap))
    => nil
(local-set-key "\C-p" ctl-x-map)
    => nil
(key-binding "\C-p\C-f")
    => find-file

(key-binding "\C-p6")
    => nil

define-prefix-command symbol Function
この関数は、symbolをプレフィックスキーの バインディングとして使えるように準備する。 つまり、完全なキーマップを作成し、 symbolの関数定義にそのキーマップを保存する。 以後、symbolにキー列をバインドすると、 当該キー列をプレフィックスキーに入る。

この関数は、変数としてのsymbolにも値としてキーマップを設定する。 symbolを返す。


Node:Active Keymaps, Next:, Previous:Prefix Keys, Up:Keymaps

活性なキーマップ

Emacsには、通常、たくさんのキーマップがあります。 ある時点では、それらの数個が活性になっていて、 ユーザー入力の解釈に関与します。 それらは、グローバルキーマップ、カレントバッファのローカルキーマップ、 オンになっているマイナモードのキーマップです。

グローバルキーマップ(global keymap)は、 C-fのようなカレントバッファに依存せずに 定義されたキーのバインディングを保持します。 変数global-mapはこのキーマップを保持していて、 このキーマップはつねに活性です。

各バッファには別のキーマップ、つまり、 バッファのローカルキーマップ(local keymap)があり、 キーに対する新しい定義や無効にする定義を保持しています。 カレントバッファのローカルキーマップは、 overriding-local-mapで無効にしない限り、つねに活性です。 テキスト属性により、バッファの特定部分に対する 代替ローカルマップを指定できます。 Special Propertiesを参照してください。

各マイナモードもキーマップを持てます。 その場合、マイナモードがオンであると当該キーマップは活性です。

変数overriding-local-mapnil以外であると、 バッファのローカルキーマップとそのすべてのマイナモードキーマップに 取ってかわるローカルキーマップを指定します。

キーが入力されるとどのコマンドを実行するかを決定するために、 すべての活性なキーマップを一緒に使います。 Emacsは、キーマップの1つでバインディングがみつかるまで、 優先順位が高いほうからこれらのキーマップを1つ1つ探索します。 1つのキーマップで探索する処理のことを キー探索(key lookup)といいます。 Key Lookupを参照してください。

通常、Emacsはまずminor-mode-map-alistで指定される順に マイナモードキーマップでキーを探します。 キーに対するバインディングがなければ、 Emacsはローカルキーマップで探します。 そこにもバインディングがなければ、 Emacsはグローバルキーマップで探します。 しかし、overriding-local-mapnil以外であれば、 Emacsはまずそのキーマップで探してから、 グローバルキーマップで探します。

同じメジャーモードを使う各バッファは、通常、同じローカルキーマップを 使うので、キーマップはモードにローカルであると考えることができます。 (たとえばlocal-set-keyを使って)バッファのローカルキーマップを 修正すると、当該キーマップを共有している別のバッファでも その修正が見えます。

Lispモードや他の数個のメジャーモードで使われるローカルキーマップは、 それらのモードがまだ使われていなくても存在します。 そのようなローカルキーマップは、lisp-mode-mapなどの変数の値です。 使用頻度の低いほとんどのメジャーモードでは、 セッションで始めてそのモードを使ったときに ローカルキーマップを作成します。

ミニバッファにもローカルキーマップがあります。 それにはさまざまな補完コマンドや脱出コマンドが含まれます。 See Intro to Minibuffers

Emacsには、別の用途のキーマップもあります。 read-key-sequenceでイベントを変換するためのものです。 See Translating Input

標準的なキーマップの一覧についてはSee Standard Keymaps

global-map Variable
この変数は、Emacsがキーボード入力をコマンドに対応させるための デフォルトのグローバルキーマップを保持する。 グローバルキーマップは、通常、このキーマップである。 デフォルトのグローバルキーマップは、 すべての印字文字にself-insert-commandをバインドする 完全なキーマップである。

グローバルマップのバインディングを修正することは実用的ですが、 この変数には、動作開始時のキーマップ以外の値は設定しないこと。

current-global-map Function
この関数は、現在のグローバルキーマップを返す。 global-mapを変更していなければ、 これはglobal-mapの値と同じである。
(current-global-map)
=> (keymap [set-mark-command beginning-of-line ...
            delete-backward-char])

current-local-map Function
この関数は、カレントバッファのローカルキーマップを返す。 なければnilを返す。 つぎの例では、(lisp対話モードを使っている)バッファ*scratch*の キーマップは疎なキーマップであり、 ASCIIコード27の<ESC>に対する指定も別の疎なキーマップである。
(current-local-map)
=> (keymap
    (10 . eval-print-last-sexp)
    (9 . lisp-indent-line)
    (127 . backward-delete-char-untabify)
    (27 keymap
        (24 . eval-defun)
        (17 . indent-sexp)))

current-minor-mode-maps Function
この関数は、現在オンになっているマイナモードのキーマップのリストを返す。

use-global-map keymap Function
この関数は、キーマップkeymapを新たな現在のグローバルキーマップとする。 これはnilを返す。

グローバルキーマップを変更することは、とうてい普通のことではない。

use-local-map keymap Function
この関数は、キーマップkeymapをカレントバッファの 新たなローカルキーマップとする。 keymapnilであると、 バッファにはローカルキーマップがなくなる。 use-local-mapnilを返す。 ほとんどのメジャーモードコマンドは、この関数を使う。

minor-mode-map-alist Variable
この変数は、変数の値に応じて活性になっている/いないキーマップを 記述する連想リストである。 その要素はつぎの形である。
(variable . keymap)

変数variableの値がnil以外であれば、 キーマップkeymapは活性である。 典型的には、variableはマイナモードをオン/オフする変数である。 see Keymaps and Minor Modes

minor-mode-map-alistの要素とminor-mode-alistの要素とは、 異なる構造であることに注意してほしい。 キーマップは要素のCDRである必要があり、 要素のCADRがキーマップであるようなリストではだめである。 CADRは、(リストの)キーマップであるか、 関数定義がキーマップであるシンボルである。

複数のマイナモードキーマップが活性な場合、 それらの優先順位は、minor-mode-map-alistでの順番である。 読者は、互いに干渉しないようにマイナモードを設計する必要がある。 正しくできていれば、順序は関係ないはずである。

マイナモードについて詳しくはKeymaps and Minor Modesを参照。 minor-mode-key-binding(see Functions for Key Lookup)も参照のこと。

minor-mode-overriding-map-alist Variable
この変数は、メジャーモードから特定のマイナモード向けのキーバインディングを 無効にするためのものである。 この連想リストの要素は、minor-mode-map-alistの要素と同じ形で、 (variable . keymap)である。

minor-mode-overriding-map-alistの要素として変数が現れると、 当該要素が指定するキーマップで、 minor-mode-map-alist内の同じ変数で指定したキーマップを 完全に置き換える。

minor-mode-overriding-map-alistは、すべてのバッファにおいて、 自動的にバッファにローカルになる。

overriding-local-map Variable
nil以外の値であると、この変数は、 バッファのローカルキーマップ、ならびに、すべてのマイナモードキーマップの かわりに用いるキーマップを保持する。 このキーマップは、現在のグローバルキーマップを除く、 他のすべての活性なキーマップを無効にする。

overriding-terminal-local-map Variable
nil以外であると、この変数は、 overriding-local-map、および、バッファのローカルキーマップと すべてのマイナモードキーマップのかわりに用いるキーマップを保持する。

この変数はつねに現在の端末に対してローカルであり、 バッファに対してローカルにはならない。 see Multiple Displays。 これはインクリメンタルサーチモードの実装に使われている。

overriding-local-map-menu-flag Variable
この変数がnil以外であれば、 overriding-local-mapoverriding-terminal-local-mapの値は、 メニューバーの表示に影響する。 デフォルト値はnilであり、 そのため、それらのマップはメニューバーには影響しない。

これら2つのキーマップ変数は、メニューバーの表示に影響しないときであっても、 メニューバーを用いて入力したキー列の実行には影響することに注意してほしい。 そのため、メニューバーのキー列が到着したら、 そのキー列を探索し実行するまえに、これらの変数をクリアすべきである。 これらの変数を使うモードでは、典型的にはつぎのようにする。 つまり、モードで処理できないイベントは『読み戻し』てモードから抜ける。

special-event-map Variable
この変数は特殊イベント用のキーマップを保持する。 イベント型のバインディングがこのキーマップにあれば、 そのイベントは特殊イベントであり、 read-eventが当該イベントのバインディングを直接実行する。 see Special Events


Node:Key Lookup, Next:, Previous:Active Keymaps, Up:Keymaps

キー探索

キー探索(key lookup)とは、 与えられたキーマップからキー列のバインディングを捜し出す処理です。 バインディングを実際に実行することは、キー探索ではありません。

キー探索では、キー列の各イベントのイベント型のみを使い、 イベントの他の部分は無視します。 実際、キー探索に使われるキー列では、 マウスイベント全体(リスト)ではなく そのイベント型(シンボル)のみを指定します。 See Input Events。 そのような『キー列』は、command-executeの動作には不十分ですが、 キーの探索や再バインディングには十分です。

キー列が複数のイベントから構成される場合、 キー探索ではイベントを順番に処理します。 先頭のイベントのバインディングを探しますが、 それはキーマップであるはずです。 続いて、そのキーマップから2番目のイベントのバインディングを探します。 これをキー列のすべてのイベントを使い尽くすまで行います。 (このように探した最後のイベントに対するバインディングは、 キーマップであたっりそうでないかもしれない。) つまり、キー探索処理は、 キーマップから単一イベントを探索するという単純な処理として定義できます。 これがどのように行われるかは、 キーマップ内のイベントに対応付けられたオブジェクトの型に依存します。

キーマップでイベント型を探してみつかった値のことを キーマップ項目(keymap entry)という単語で表します。 (これには、メニューキーバインディングにある 項目文字列や他の追加要素を含まない。 というのは、lookup-keyや他のキー探索関数は、 それらを戻り値として返さないからである。) キーマップ項目として任意のLispオブジェクトをキーマップに保存できますが、 キー探索においてそのすべてが意味を持つとは限りません。 意味のある種類のキー項目をつぎに示します。

nil
nilは、探索に使ったここまでのイベントが 未定義キーを構成することを意味する。 キーマップにイベント型が記載されてなく、かつ、 デフォルトのバインディングもない場合には、 そのイベント型に対しては、バインディングがnilであるのと等価。
command
探索に使ったここまでのイベントは完全なキーを構成し、 そのバインディングはコマンドcommandである。 see What Is a Function
array
配列(文字列やベクトル)は、キーボードマクロである。 探索に使ったここまでのイベントは完全なキーを構成し、 そのバインディングは配列arrayである。 詳しくはKeyboard Macrosを参照。
keymap
探索に使ったここまでのイベントはプレフィックスキーを構成する。 キー列のつぎのイベントはこのキーマップkeymapで探す。
list
リストの意味は、リストの要素の型に依存する。
symbol
シンボルsymbolのかわりにその関数定義を使う。 それがまたシンボルであると、この処理を何回でも繰り返す。 最終的にこれは、キーマップ、コマンド、キーボードマクロの いずれかのオブジェクトになるはずである。 キーマップやコマンドであるリストは許されるが、 シンボルを介しては間接項目は使えない。

キーマップやキーボードマクロ(文字列やベクトル)は正しい関数ではないので、 関数定義としてキーマップ、文字列、ベクトルを持つシンボルは、 正しい関数ではない。 しかし、キーバインディングとしては正しい。 定義がキーボードマクロである場合には、そのシンボルは command-executeの引数としても正しい (see Interactive Call)。

シンボルundefinedについて特記しておく。 これは、キーを未定義として扱うことを意味する。 正確には、キーは定義されており、 そのバインディングはコマンドundefinedである。 しかし、そのコマンドは、未定義キーに対して自動的に行われることと 同じことを行う。 つまり、(dingを呼び出して)ベルを鳴らすが、 エラーは通知しない。

undefinedは、グローバルキーバインディングを無効にして キーをローカルに『未定義』にするためにローカルキーマップで使われる。 nilのローカルバインディングでは、 グローバルバインディングを無効にしないため、こうはならない。

その他
その他の型のオブジェクトであると、 探索に使ったここまでのイベントは完全なキーを構成し、 当該オブジェクトがそのバインディングであるが、 当該バインディングはコマンドとしては実行できない。

まとめると、キー項目は、キーマップ、コマンド、キーボードマクロ、 これら3つのいずれかになるシンボル、間接項目、nilです。 2つの文字をコマンドに、1つを別のキーマップに対応付ける 疎なキーマップの例を示します。 このキーマップは、emacs-lisp-mode-mapの通常の値です。 ここで、それぞれ、9は<TAB>、 127は<DEL>、27は<ESC>、17はC-q、 24はC-xの文字コードであることに注意してください。

(keymap (9 . lisp-indent-line)
        (127 . backward-delete-char-untabify)
        (27 keymap (17 . indent-sexp) (24 . eval-defun)))


Node:Functions for Key Lookup, Next:, Previous:Key Lookup, Up:Keymaps

キー探索関数

ここでは、キー探索に関わる関数や変数について述べます。

lookup-key keymap key &optional accept-defaults Function
この関数はキーマップkeymapにおけるkeyの定義を返す。 本章で述べる他の関数は、lookup-keyを用いてキーを探す。 例を示す。
(lookup-key (current-global-map) "\C-x\C-f")
    => find-file
(lookup-key (current-global-map) "\C-x\C-f12345")
    => 2

文字列やベクトルであるkeyが、 keymapで指定されたプレフィックスキーに対して正しいキー列でなければ、 keyは『長すぎる』のであって、 1つのキー列に収まらない余分なイベントが末尾にある。 その場合、戻り値は数であり、 完全なキーを構成するkeyの先頭からのイベント数を表す。

accept-defaultsnil以外であると、 lookup-keyは、keyの特定のイベントに 対するバインディングだけでなく、 デフォルトのバインディングも考慮する。 さもなければ、lookup-keyは、 keyの特定のイベントに対するバインディングだけを報告し、 特に指定しない限りデフォルトのバインディングは無視する。 (それには、keyの要素としてtを与える。 Format of Keymapsを参照。)

keyにメタ文字が含まれる場合、 当該文字は暗黙のうちに2文字の列、 つまり、meta-prefix-charの値と対応する非メタ文字 に置き換えられる。 したがって、つぎの最初の例は、2番目の例に変換して処理される。

(lookup-key (current-global-map) "\M-f")
    => forward-word
(lookup-key (current-global-map) "\ef")
    => forward-word

read-key-sequenceと異なり、 この関数は、情報を欠落するようには指定されたイベントを修正しない (see Key Sequence Input)。 特に、文字を小文字に変換したり、 ドラッグイベントをクリックイベントに変換したりはしない。

undefined コマンド
キーを未定義にするためにキーマップで使われる。 dingを呼び出すが、エラーにはならない。

key-binding key &optional accept-defaults Function
この関数は、すべての活性なキーマップを試して keyに対するバインディングを返す。 キーマップでkeyが未定義であると結果はnil

引数accept-defaultsは、lookup-key(上記)と同様に、 デフォルトのバインディングを調べるかどうか制御する。

keyが文字列でもベクトルでもないとエラーを通知する。

(key-binding "\C-x\C-f")
    => find-file

local-key-binding key &optional accept-defaults Function
この関数は、現在のローカルキーマップから keyに対するバインディングを返す。 未定義ならばnilを返す。

引数accept-defaultsは、lookup-key(上記)と同様に、 デフォルトのバインディングを調べるかどうか制御する。

global-key-binding key &optional accept-defaults Function
この関数は、現在のグローバルキーマップから keyに対するバインディングを返す。 未定義ならばnilを返す。

引数accept-defaultsは、lookup-key(上記)と同様に、 デフォルトのバインディングを調べるかどうか制御する。

minor-mode-key-binding key &optional accept-defaults Function
この関数は、すべてのオンになっているマイナモードにおける keyのバインディングのリストを返す。 より正確には、対(modename . binding)を要素とする 連想リストを返す。 ここで、modenameはマイナモードをオンにする変数であり、 bindingは当該モードにおけるkeyのバインディングである。 keyにマイナモードでのバインディングがなければ、 値はnilである。

最初にみつかったバインディングがプレフィックスの定義 (キーマップかキーマップとしてのシンボル)でなければ、 残りのマイナモードからのバインディングは完全に隠されてしまうので それらは省略する。 同様に、プレフィックスバインディングに 続く非プレフィックスバインディングも省略する。

引数accept-defaultsは、lookup-key(上記)と同様に、 デフォルトのバインディングを調べるかどうか制御する。

meta-prefix-char Variable
この変数は、メタプレフィックス文字の文字コードである。 メタ文字をキーマップで探索するために2文字列に変換するときに使われる。 結果が有用であるためには、 この値はプレフィックスイベント(see Prefix Keys)であるべきである。 デフォルト値は27、<ESC>のASCIIコードである。

meta-prefix-charの値が27である限り、 キー探索ではM-b<ESC> bに変換し、 通常、これはコマンドbackward-wordと定義されている。 しかし、meta-prefix-charC-xのコードである24を設定すると、 EmacsはM-bC-x bに変換し、 その標準のバインディングはコマンドswitch-to-bufferである。 これを以下に示す。

meta-prefix-char                    ; デフォルト値
     => 27
(key-binding "\M-b")
     => backward-word
?\C-x                               ; 文字の表示表現
     => 24
(setq meta-prefix-char 24)
     => 24
(key-binding "\M-b")
    => switch-to-buffer            ; ここでM-bと打つと
                                    ; C-x bと打つのと同じ

(setq meta-prefix-char 27)          ; 混乱を避けるために
     => 27                         ; デフォルト値に戻す!


Node:Changing Key Bindings, Next:, Previous:Functions for Key Lookup, Up:Keymaps

キーバインディングの変更

キーを再バインドするには、キーマップにおける当該項目を変更します。 グローバルキーマップでバインディングを変更すると、 その変更はすべてのバッファで効果を発揮します (ただし、ローカルキーマップでグローバルバインディングを 隠しているバッファでは直接の効果はない)。 カレントバッファのローカルキーマップで変更すると、 通常、同じメジャーモードを使っているすべてのバッファに影響します。 関数global-set-keylocal-set-keyは、 これらの操作を行うための便利なインターフェイスです (see Key Binding Commands)。 より汎用の関数define-keyを使うこともできますが、 変更対象のキーマップを明示する必要があります。

キー列の再バインドを書くときには、 コントロール文字やメタ文字向けの 特別なエスケープシーケンスを使うのがよいです(see String Type)。 構文\C-は後続の文字がコントロール文字であること、 構文\M-は後続の文字がメタ文字であることを意味します。 したがって、文字列"\M-x"は単一のM-xを含むと読まれ、 "\C-f"は単一のC-fを含むと読まれ、 "\M-\C-x""\C-\M-x"はいずれも単一のC-M-xを 含むと読まれます。 同じエスケープシーケンスは、 ベクトルでも使え、文字列が許されない他の場面でも使えます。 たとえば、[?\C-\H-x home]です。 See Character Type

キーを定義したり探索する関数では、 ベクトルで表したキー列内のイベント型に対して別の構文、 つまり、修飾子名と1つの基本イベント(文字やファンクションキー名) から成るリストを受け付けます。 たとえば、(control ?a)?\C-aに等価であり、 (hyper control left)C-H-leftに等価です。 このようなリストの利点の1つは、 コンパイル済みのファイルに修飾ビットの数値が現れないことです。

以下の関数では、keymapがキーマップでなかったり、 keyがキー列を表す文字列やベクトルでないと、エラーを通知します。 リストであるイベントの省略形としてイベント型(シンボル)を使えます。

define-key keymap key binding Function
この関数は、キーマップkeymapにおいて キーkeyに対するバインディングを設定する。 (keyが複数イベントの場合、 keymapから辿った別のキーマップが実際には変更される。) 引数bindingは任意のLispオブジェクトであるが、 ある種の型のものだけが意味を持つ。 (意味のある型の一覧については、Key Lookupを参照。) define-keyが返す値はbindingである。

keyのおのおののプレフィックスはプレフィックスキーである (キーマップにある)か未定義であること。 さもなければ、エラーを通知する。 keyのプレフィックスに未定義なものがあると、 define-keyは当該プレフィックスをプレフィックスキーと定義し、 keyの残りの部分を指定どおりに定義できるようにする。

keymapkeyのバインディングがなければ、 新たなバインディングをkeymapの先頭に追加する。 キーマップ内のバインディングの順序は多くの場合関係ないが、 メニューキーマップでは意味を持つ(see Menu Keymaps)。

疎なキーマップを作成し、そこにバインディングを作る例を示します。

(setq map (make-sparse-keymap))
    => (keymap)
(define-key map "\C-f" 'forward-char)
    => forward-char
map
    => (keymap (6 . forward-char))

;; C-x用の疎なサブマップを作り、
;; そこにfのバインディングを入れる
(define-key map "\C-xf" 'forward-word)
    => forward-word
map
=> (keymap
    (24 keymap                ; C-x
        (102 . forward-word)) ;      f
    (6 . forward-char))       ; C-f

;; C-pctl-x-mapにバインドする
(define-key map "\C-p" ctl-x-map)
;; ctl-x-map
=> [nil ... find-file ... backward-kill-sentence]

;; ctl-x-mapで、C-ffooにバインドする
(define-key map "\C-p\C-f" 'foo)
=> 'foo
map
=> (keymap     ; fooctl-x-mapの中にある
    (16 keymap [nil ... foo ... backward-kill-sentence])
    (24 keymap
        (102 . forward-word))
    (6 . forward-char))

C-p C-fに対する新しいバインディングは、 実際にはctl-x-mapの項目を変更していて、 これには、C-p C-fとデフォルトのグローバルキーマップ内の C-x C-fの両方のバインディングを変更する効果がある ことに注意してください。

substitute-key-definition olddef newdef keymap &optional oldmap Function
この関数は、keymap内のolddefにバインドされたキーの olddefnewdefに置き換える。 いいかえると、olddefに出会うたびにそれをnewdefに置き換える。 関数はnilを返す。

たとえば、Emacsの標準のバインディングであると、 つぎの例はC-x C-fを再定義する。

(substitute-key-definition
 'find-file 'find-file-read-only (current-global-map))

oldmapnil以外であると、 そのバインディングによってどのキーを再バインドするかを決定する。 再バインディングはkeymapで行い、oldmapではない。 つまり、別のキーマップ内のバインディングの制御のもとに、 キーマップを変更できる。 たとえば、

(substitute-key-definition
  'delete-backward-char 'my-funny-delete
  my-map global-map)

では、グローバルには標準の削除コマンドにバインドされているキーに対しては、 my-mapでは特別な削除コマンドにする。

変更前後のキーマップを以下に示す。

(setq map '(keymap
            (?1 . olddef-1)
            (?2 . olddef-2)
            (?3 . olddef-1)))
=> (keymap (49 . olddef-1) (50 . olddef-2) (51 . olddef-1))

(substitute-key-definition 'olddef-1 'newdef map)
=> nil
map
=> (keymap (49 . newdef) (50 . olddef-2) (51 . newdef))

suppress-keymap keymap &optional nodigits Function
この関数は、完全なキーマップkeymapの内容を変更し、 すべての印字文字を未定義にする。 より正確には、それらにコマンドundefinedをバインドする。 これにより、通常のテキストの挿入を不可能にする。 suppress-keymapnilを返す。

nodigitsnilであると、 suppress-keymapは、 数字文字ではdigit-argumentを実行し、 -ではnegative-argumentを実行するように定義する。 さもなければ、それらも他の印字文字と同様に未定義にする。

関数suppress-keymapは、 yankquoted-insertなどのコマンドを抑制しないので、 バッファを変更不可能にするわけではない。 バッファの変更を禁止するには、バッファを読み出し専用にする (see Read Only Buffers)。

この関数はkeymapを変更するため、 読者は、通常、新たに作成したキーマップに対して使うであろう。 ある目的で使用中の既存のキーマップを操作すると、 問題を引き起こすことがある。 たとえば、global-mapに適用するとEmacsをほとんど使用不能にしてしまう。

多くの場合、テキストの挿入が必要なくバッファを読み出し専用で使う rmailやdiredなどのモードのローカルキーマップの初期化に suppress-keymapを使う。 ファイルemacs/lisp/dired.elから持ってきた例を示す。 これは、diredモード用のローカルキーマップの設定方法である。

(setq dired-mode-map (make-keymap))
(suppress-keymap dired-mode-map)
(define-key dired-mode-map "r" 'dired-rename-file)
(define-key dired-mode-map "\C-d" 'dired-flag-file-deleted)
(define-key dired-mode-map "d" 'dired-flag-file-deleted)
(define-key dired-mode-map "v" 'dired-view-file)
(define-key dired-mode-map "e" 'dired-find-file)
(define-key dired-mode-map "f" 'dired-find-file)
...


Node:Key Binding Commands, Next:, Previous:Changing Key Bindings, Up:Keymaps

キーをバインドするためのコマンド

本節では、キーのバインディングを変更する 便利で対話的なインターフェイスについて述べます。 これらは、define-keyを呼び出して動作します。

単純なカスタマイズのために ファイル.emacsglobal-set-keyをしばしば使います。 たとえば、

(global-set-key "\C-x\C-\\" 'next-line)

(global-set-key [?\C-x ?\C-\\] 'next-line)

(global-set-key [(control ?x) (control ?\\)] 'next-line)

は、1行下がるようにC-x C-\を再定義します。

(global-set-key [M-mouse-1] 'mouse-set-point)

は、メタキーを押し下げながらマウスの第1ボタン(左端)をクリックすると クリック位置にポイントを設定するように再定義します。

global-set-key key definition コマンド
この関数は、現在のグローバルキーマップにおいて keyのバインディングをdefinitionと設定する。
(global-set-key key definition)
==
(define-key (current-global-map) key definition)

global-unset-key key コマンド
この関数は、現在のグローバルキーマップから keyのバインディングを削除する。

この関数の1つの用途は、 keyに非プレフィックスのバインディングがあると再定義できないため、 keyをプレフィックスとして使う長いキーを定義する前準備である。 たとえば、つぎのとおり。

(global-unset-key "\C-l")
    => nil
(global-set-key "\C-l\C-l" 'redraw-display)
    => nil

この関数は単にdefine-keyを使って実装してある。

(global-unset-key key)
==
(define-key (current-global-map) key nil)

local-set-key key definition コマンド
この関数は、現在のローカルキーマップにおいて keyのバインディングをdefinitionと設定する。
(local-set-key key definition)
==
(define-key (current-local-map) key definition)

local-unset-key key コマンド
この関数は、現在のローカルキーマップから keyのバインディングを削除する。
(local-unset-key key)
==
(define-key (current-local-map) key nil)


Node:Scanning Keymaps, Next:, Previous:Key Binding Commands, Up:Keymaps

キーマップの走査

本節では、ヘルプ情報を表示するために 現在のキーマップをすべて走査する関数について述べます。

accessible-keymaps keymap &optional prefix Function
この関数は、keymapから(0個以上のプレフィックスキーにより)辿れる すべてのキーマップのリストを返す。 その値は、(key . map)の形の要素から成る 連想リストである。 ここで、keyはプレフィックスキーであり、 keymap内でのその定義はmapである。

連想リスト内での要素の順番は、keyの長さが増える順である。 指定したキーマップkeymapはプレフィックスのイベントなしに参照できるので、 最初の要素はつねに("" . keymap)である。

prefixを与える場合、それはプレフィックスキー列であること。 すると、accessible-keymapsは、 prefixで始まるプレフィックスに対応したサブマップのみを含める。 それらの要素は、(accessible-keymaps)の値と同じに見えるが、 違いは、いくつかの要素が省略されることである。

つぎの例では、返された連想リストにおいては、 ^[と表示されたキー<ESC>はプレフィックスキーであり、 その定義は疎なキーマップ (keymap (83 . center-paragraph) (115 . foo))であることを表す。

(accessible-keymaps (current-local-map))
=>(("" keymap
      (27 keymap   ; Note this keymap for <ESC> is repeated below.
          (83 . center-paragraph)
          (115 . center-line))
      (9 . tab-to-tab-stop))

   ("^[" keymap
    (83 . center-paragraph)
    (115 . foo)))

つぎの例では、C-hは、 疎なキーマップ(keymap (118 . describe-variable)...)を 使うプレフィックスキーである。 別のプレフィックスC-x 4は、 変数ctl-x-4-mapの値でもあるキーマップを使う。 イベントmode-lineは、 ウィンドウの特別な箇所におけるマウス操作を表すための 疑似イベントの1つである。

(accessible-keymaps (current-global-map))
=> (("" keymap [set-mark-command beginning-of-line ...
                   delete-backward-char])
    ("^H" keymap (118 . describe-variable) ...
     (8 . help-for-help))
    ("^X" keymap [x-flush-mouse-queue ...
     backward-kill-sentence])
    ("^[" keymap [mark-sexp backward-sexp ...
     backward-kill-word])
    ("^X4" keymap (15 . display-buffer) ...)
    ([mode-line] keymap
     (S-mouse-2 . mouse-split-window-horizontally) ...))

実際に表示されるキーマップはこれらだけとは限らない。

where-is-internal command &optional keymap firstonly noindirect Function
この関数は、コマンドwhere-is (see Help)が使う サブルーティンである。 キーマップにおいてcommandにバインドされた (任意長の)キー列のリストを返す。

引数commandは任意のオブジェクトであり、 キーマップ項目とはeqで比較する。

keymapnilであると、 overriding-local-mapを無視 (つまり、その値はnilとみな)して、 現在活性なキーマップを使う。 keymapnil以外であると、 keymapとグローバルキーマップから辿れるキーマップを使う。

通常、keymapに対する式にはoverriding-local-mapを使うのが 最良である。 そうすると、where-is-internalは正確に活性なキーマップを走査する。 グローバルキーマップのみを走査するには、 keymapとして(keymap)(空のキーマップ)を渡す。

firstonlynon-asciiであると、 戻り値は、可能なキー列のリストではなく、 最初にみつかったキー列を表す1つの文字列である。 firstonlytであると、 値は最初のキー列であるが、 ASCII文字(あるいはASCII文字のメタ変種)のみから成るキー列が 他のキー列より優先される。

noindirectnil以外であると、 where-is-internalは間接項目を辿らない。 これにより、間接項目そのものを探すことができる。

(where-is-internal 'describe-function)
    => ("\^hf" "\^hd")

describe-bindings &optional prefix コマンド
この関数は、現在のすべてのキーバインディングの一覧を作成し、 *Help*という名前のバッファに表示する。 テキストはモードごとにまとめられ、 マイナモード、メジャーモード、グローバルバインディングの順である。

prefixnil以外であると、それはプレフィックスキーであること。 そうすると、prefixで始まるキーのみの一覧を作る。

一覧では、メタ文字は、<ESC>に続けて対応する非メタ文字で表す。

連続したASCIIコードの一連の文字が同じ定義である場合には、 それらをまとめてfirstchar..lastcharと表示する。 この場合、どの文字であるか理解するには、 ASCIIコードを知っている必要がある。 たとえば、デフォルトのグローバルキーマップでは、 <SPC>.. ~の文字が1行に表示される。 <SPC>はASCIIコード32、~ASCIIコード126であり、 そのあいだには普通の印字文字(英文字、数字文字、句読点文字など)が すべて含まれる。 これらの文字はすべてself-insert-commandにバインドされている。


Node:Menu Keymaps, Previous:Scanning Keymaps, Up:Keymaps

メニューキーマップ

キーマップは、キーボードのキーやマウスボタンに対するバインディングに加えて メニューも定義できます。


Node:Defining Menus, Next:, Up:Menu Keymaps

メニューの定義

キーマップに全面プロンプト文字列(overall prompt string)、 つまり、キーマップの要素として文字列が現れれば、 メニューとして使えます。 その文字列でメニューの目的を記述します。 プロンプト文字列を持ったキーマップを作成するもっとも簡単な方法は、 make-keymapmake-sparse-keymap(see Creating Keymaps)を 呼ぶときに、引数として文字列を指定します。

メニュー上での項目の順番は、 キーマップ内のバインディングの順番と同じです。 define-keyは、新たなバインディングを先頭に追加するので、 順番を気にするのならば、メニューの底の項目から始めて 上の項目へ向かってメニュー項目の定義を入れます。 既存のメニューに項目を追加する場合には、 define-key-after(see Modifying Menus)を使って メニュー内での位置を指定できます。


Node:Simple Menu Items, Next:, Up:Defining Menus

単純なメニュー項目

メニューキーマップのバインディングを定義する単純で旧式の方法は つぎのとおりです。

(item-string . real-binding)

CARitem-stringは、メニューに表示される文字列です。 3単語までの短いものにし、対応するコマンドの動作を記述します。

つぎのように、ヘルプ文字列となる2つめの文字列も指定できます。

(item-string help-string . real-binding)

現状では、Emacsは実際にはhelp-stringを使いません。 real-bindingを取り出すためにhelp-stringを無視する方法を 知っているだけです。 将来、ユーザーの要望に応じてメニュー項目に対する追加説明として help-stringを使うかもしれません。

define-keyに関する限り、 item-stringhelp-stringは イベントのバインディングの一部分です。 しかし、lookup-keyreal-bindingのみを返し、 キーの実行にはreal-bindingのみが使われます。

real-bindingnilであると、 item-stringはメニューに現れますが、それは選択できません。

real-bindingがシンボルであり、 その属性menu-enablenil以外であると、 当該属性は、メニュー項目を活性にするかどうかを制御する式です。 Emacsは、メニューを表示するためにキーマップを使うたびに、 その式を評価し、式の値がnil以外である場合に限り、 当該メニュー項目をオンにします。 メニュー項目がオフであると、『薄く』表示し、それは選択できません。

メニューバーでは、読者がメニューを見るたびにどの項目がオンであるかを 再計算しません。 Xツールキットがあらかじめメニューの木構造全体を必要とするからです。 メニューバーの再計算を強制するには、 force-mode-line-updateを呼び出します。 (see Mode Line Format)。

メニュー項目には、同じコマンドを起動する等価なキーボードのキー列が (あれば)表示されていることに気づいたと思います。 再計算の時間を節約するために、 メニューの表示では、この情報をつぎのように バインディングの部分リストに隠し持っています。

(item-string [help-string] (key-binding-data) . real-binding)

読者は、メニュー項目にこれらの部分リストを入れないでください。 それらはメニューの表示で自動的に計算されます。 冗長になるので、項目の文字列には、等価なキーボード入力を 含めないでください。


Node:Extended Menu Items, Previous:Alias Menu Items, Up:Defining Menus

拡張メニュー項目

拡張形式のメニュー項目は、より柔軟性があり、 単純な形式より見通しがよい代替方法です。 それらは、シンボルmenu-itemで始まるリストから成ります。 選択不可の文字列を定義するには、項目をつぎのようにします。

(menu-item item-name)

ここで、文字列item-nameは区切り行を表す複数個のダッシュから成ります。

選択可能な実際のメニュー項目を定義するには、 拡張形式の項目はつぎのようになります。

(menu-item item-name real-binding
    . item-property-list)

ここで、item-nameは、メニュー項目の文字列に評価される式です。 つまり、(項目の)文字列は定数である必要はありません。 3番目の要素item-property-listは実行すべきコマンドです。 リストの残りitem-property-listは、 他の情報を含んだ属性リストの形式です。 指定できる属性はつぎのとおりです。

:enable FORM
formの評価結果で、項目をオンにするかどうか決定する (nil以外だとオン)。
:visible FORM
formの評価結果で、項目をメニューに含めるかどうか決定する。 (nil以外だと含める)。 項目を含めない場合、当該項目が定義されていないかのようにメニューを表示する。
:help help
この属性の値helpは、拡張ヘルプ文字列 (現状ではEmacsは使わない)。
:button (type . selected)
この属性は、ラジオボタンとトグルボタンを定義する方法を提供する。 CARtypeは、:toggle:radioであり、 どちらであるかを指定する。 CDRselectedはフォームであること。 その評価結果が、現在ボタンが選択されているかどうかを決定する。

トグル(toggle)は、selectedの値に応じて 『on』か『off』と書かれるメニュー項目である。 コマンド自身では、selectednilならば selectedtを設定し、 tならばnilを設定すること。 以下は、debug-on-errorが定義されていれば debug-on-errorをオン/オフするメニュー項目の書き方である。

(menu-item "Debug on Error" toggle-debug-on-error
           :button (:toggle
                    . (and (boundp 'debug-on-error)
                           debug-on-error))

これは、変数debug-on-errorをオン/オフするコマンドとして toggle-debug-on-errorが定義されているので動作する。

ラジオボタン(radio button)はメニュー項目のグループであり、 ある時点ではそれらのうちの1つだけを『選択』できる。 どれを選択しているかを表す変数が必要である。 グループ内の各ラジオボタンに対するフォームselectedは、 当該変数の値が当該ボタンを選択している値かどうかを検査する。 ボタンをクリックすると、クリックしたボタンが選択されるように 当該変数に設定すること。

:key-sequence key-sequence
この属性は、このメニュー項目が起動するコマンドにバインド される可能性があるキー列を指定する。 正しいキー列を指定すると、メニュー表示の準備が素早くなる。

まちがったキー列を指定しても、その効果はない。 メニューにkey-sequenceを表示するまえに、 Emacsはkey-sequenceがこのメニュー項目に実際に等価かどうか調べる。

:key-sequence nil
この属性は、このメニュー項目に等価なキーバインディングが 普通はないことを示す。 この属性を使うとメニュー表示の準備時間を節約できる。 Emacsはこのメニュー項目に等価なキーボード入力をキーマップで 探す必要がないからである。

しかし、ユーザーがこの項目の定義に対してキー列を再バインドすると、 Emacsは属性:keysを無視して等価なキーボード入力を探す。

:keys string
この属性は、このメニュー項目に対する等価なキーボード入力として 表示する文字列stringを指定する。 stringでは説明文の\\[...]の書き方を使える。
:filter filter-fn
この属性は、動的にメニュー項目を計算する方法を与える。 属性値filter-fnは1引数の関数であること。 それが呼ばれるとき、引数はreal-bindingになる。 関数はかわりに使用するバインディングを返すこと。


Node:Alias Menu Items, Next:, Previous:Simple Menu Items, Up:Defining Menus

メニュー項目の別名

『同じ』コマンドを使いながらオン条件が異なるメニュー項目を 作れると便利なことがあります。 現状のEmacsでこれを行う最良の方法は、拡張メニュー項目を使うことです。 この機能がなかった頃には、コマンドの別名を定義し、 それをメニュー項目で使うことで可能でした。 異なるオン条件でtoggle-read-onlyを 使う2つの別名の作り方を以下に示します。

(defalias 'make-read-only 'toggle-read-only)
(put 'make-read-only 'menu-enable '(not buffer-read-only))
(defalias 'make-writable 'toggle-read-only)
(put 'make-writable 'menu-enable 'buffer-read-only)

メニューに別名を使うときには、 (典型的にはメニュー以外にはキーバインディングがない)別名ではなく 『本物の』コマンド名に対する等価なキーバインディングを 表示しするのがしばしば有用です。 これを行うには、別名のシンボルには nil以外の属性menu-aliasを与えます。

(put 'make-read-only 'menu-alias t)
(put 'make-writable 'menu-alias t)

こうすると、make-read-onlymake-writableのメニュー項目には toggle-read-onlyに対するキーバインディングが表示されます。


Node:Mouse Menus, Next:, Previous:Defining Menus, Up:Menu Keymaps

メニューとマウス

メニューキーマップがメニューを表示するようにする普通の方法は、 メニューキーマップをプレフィックスキーの定義にすることです。 (Lispプログラムから明示的にメニューをポップアップして、 ユーザーの選択を受け取れる。 Pop-Up Menusを参照。)

プレフィックスキーがマウスイベントで終っていると、 Emacsはメニューをポップアップすることでメニューキーマップを扱います。 これで、ユーザーはマウスで選択できるようになります。 ユーザーがメニュー項目をクリックすると、 当該メニュー項目をバインディングとする文字やシンボルが イベントとして生成されます。 (メニューが複数レベルになっていたりメニューバーから開いたときには、 メニュー項目は一連のイベントを生成する。)

メニューの開始にはボタン押し下げイベントを使うのがしばしば最良です。 そうすると、ユーザーはボタンを離すことでメニュー項目を選べます。

明示的に配置すれば、1つのキーマップをメニューペインとして表示できます。 それには、各ペインに対するキーマップを作成し、 つぎに、メニューのメインのキーマップにおいて、 (各ペインの)各キーマップに対するバインディングを作ります。 なお、これらのバインディングには、 @で始まる項目文字列を指定します。 項目文字列の残りの部分がペインの名前になります。 この例についてはファイルlisp/mouse.elを参照してください。 @で始まらない項目文字列の他の普通のバインディングは 1つのペインにまとめられ、サブマップに対して明示的に作られた 他のペインとともに表示されます。

Xツールキットのメニューにはペインはありませんが、 そのかわりに、サブメニューがあります。 項目文字列が@で始まるかどうかに関わらず、 入れ子になった各キーマップがサブメニューになります。 Emacsのツールキット版では、項目文字列の先頭の@に関して特別なことは、 @がメニュー項目に表示されないことです。

個別のキーマップからも複数ペインやサブメニューを作成できます。 プレフィックスキーの完全な定義は、 さまざまな活性のキーマップ(マイナモード、ローカル、グローバル)が与える 定義を併合することで得られます。 これらのキーマップのうち複数個がメニューであるとき、 そのおのおのが別々のペイン(Xツールキットを使わないEmacs)や 別々のサブメニュー(Xツールキットを使ったEmacs)になります。 See Active Keymaps


Node:Keyboard Menus, Next:, Previous:Mouse Menus, Up:Menu Keymaps

メニューとキーボード

キーボードイベント(文字や関数)で終るプレフィックスキーに、 メニューキーマップであるような定義があると、 ユーザーはメニュー項目を選ぶためにキーボードを使えます。

Emacsはメニューの選択項目(バインディングの項目文字列)を エコー領域に表示します。 それらが1行に収まらなければ、 ユーザーは<SPC>を打つことで選択項目のつぎの行を見ることができます。 <SPC>を連続して使うと最終的にはメニューの最後に達し、 そうするとメニューの先頭に戻ります。 (変数menu-prompt-more-charに、このために用いる文字を指定する。 デフォルトは<SPC>。)

ユーザーは、メニューから望みの項目をみつけたら、 対応する文字、つまり、その項目のバインディングを持つ文字を打ちます。

Emacs類似エディタにおけるこのようなメニューの使い方は、 システムHierarkeyに触発されたからです。

menu-prompt-more-char Variable
この変数は、メニューのつぎの行を見るために使う文字を指定する。 初期値は、<SPC>の文字コードの32である。


Node:Menu Example, Next:, Previous:Keyboard Menus, Up:Menu Keymaps

メニューの例

以下に、メニューキーマップの完全な定義の例を示します。 これは、メニューバーのメニューToolsの サブメニューPrintの定義であり、 単純なメニュー項目を使います (see Simple Menu Items)。 まず、キーマップを作成し名前を与えます。

(defvar menu-bar-print-menu (make-sparse-keymap "Print"))

つぎに、メニュー項目を定義します。

(define-key menu-bar-print-menu [ps-print-region]
  '("Postscript Print Region" . ps-print-region-with-faces))
(define-key menu-bar-print-menu [ps-print-buffer]
  '("Postscript Print Buffer" . ps-print-buffer-with-faces))
(define-key menu-bar-print-menu [separator-ps-print]
  '("--"))
(define-key menu-bar-print-menu [print-region]
  '("Print Region" . print-region))
(define-key menu-bar-print-menu [print-buffer]
  '("Print Buffer" . print-buffer))

バインディングが『作られる対象』のシンボルに注意してください。 定義されるキー列の角括弧の内側に現れています。 そのシンボルはコマンド名に等しい場合もあればそうでない場合もあります。 これらのシンボルは『ファンクションキー』として扱われますが、 キーボード上の本物のファンクションキーではありません。 それらはメニュー項目の機能には影響ありませんが、 ユーザーがメニューから選ぶとそれらはエコー領域に『表示』され、 where-isaproposの出力にも現れます。

定義が("--")であるようなバインディングは区切り行です。 実際のメニュー項目のように、区切りにもキーシンボルがあり、 例ではseparator-ps-printです。 1つのメニューに複数の区切りがある場合、 それらはすべて異なるキーシンボルでなければなりません。

つぎには、メニュー内の2つのコマンドのオン条件を定義するコードです。

(put 'print-region 'menu-enable 'mark-active)
(put 'ps-print-region-with-faces 'menu-enable 'mark-active)

つぎは、このメニューを親メニューの項目に現れるようにする方法です。

(define-key menu-bar-tools-menu [print]
  (cons "Print" menu-bar-print-menu))

ここで使っているのは、サブメニューのキーマップ、つまり、 変数menu-bar-print-menuの値であって、 変数そのものではないことに注意してください。 menu-bar-print-menuはコマンドではないので、 このシンボルを親メニューの項目に使っても意味がありません。

同じ印刷メニューをマウスクリックに対応付けたければ、 つぎのようにしてできます。

(define-key global-map [C-S-down-mouse-1]
   menu-bar-print-menu)

つぎのようにして、print-regionに対して拡張メニュー項目 (see Extended Menu Items)を使うこともできます。

(define-key menu-bar-print-menu [print-region]
  '(menu-item "Print Region" print-region
              :enable (mark-active)))

拡張メニュー項目では、オン条件はメニュー項目自体の内側に指定します。 マークがないときにはメニューからこの項目が消えるようにするには つぎのようにします。

(define-key menu-bar-print-menu [print-region]
  '(menu-item "Print Region" print-region
              :visible (mark-active)))


Node:Menu Bar, Next:, Previous:Menu Example, Up:Menu Keymaps

メニューバー

ほとんどのウィンドウシステムでは、 各フレームにメニューバー(menu bar)、 つまり、フレームの先頭に水平方向に延びているメニューを恒久的に表示できます。 メニューバーの項目は、すべての活性なキーマップで定義された 疑似『ファンクションキー』menu-barのサブコマンドです。

メニューバーに項目を追加するには、 読者独自の疑似『ファンクションキー』を考え(これをkeyとする)、 キー列[menu-bar key]に対するバインディングを作ります。 多くの場合、バインディングはメニューキーマップであって、 メニューバーの項目上でボタンを押すと別のメニューへ至るようにします。

メニューバーに対する同じ疑似ファンクションキーを 複数の活性なキーマップで定義していても、1つの項目だけが表示されます。 ユーザーがメニューバーの当該項目をクリックすると、 当該項目のすべてのサブコマンド、つまり、 グローバルのサブコマンド、ローカルのサブコマンド、 マイナモードのサブコマンドを含む1つの複合メニューが表示されます。

メニューバーの内容を決定する際には、 通常、変数overriding-local-mapは無視されます。 つまり、overriding-local-mapnilであるときに 活性になるキーマップからメニューバーを計算します。 See Active Keymaps

フレームにメニューバーを表示するには、 フレームのパラメータmenu-bar-linesが0より大きい必要があります。 Emacsはメニューバーそのものには1行だけ使います。 読者が2行以上を指定すると、 残りの行はフレームのウィンドウとメニューバーを区切る行になります。 menu-bar-linesの値には1か2を勧めます。 See Window Frame Parameters

メニューバーの項目の設定例を示します。

(modify-frame-parameters (selected-frame)
                         '((menu-bar-lines . 2)))

;; (プロンプト文字列を持つ)メニューキーマップを作り
;; それをメニューバーの項目の定義にする
(define-key global-map [menu-bar words]
  (cons "Words" (make-sparse-keymap "Words")))

;; このメニュー内のサブコマンドを定義する
(define-key global-map
  [menu-bar words forward]
  '("Forward word" . forward-word))
(define-key global-map
  [menu-bar words backward]
  '("Backward word" . backward-word))

グローバルキーマップに作ったメニューバー項目を ローカルキーマップで取り消すには、 ローカルキーマップの当該疑似ファンクションキーのバインディングを undefinedで再バインドします。 たとえば、つぎのようにしてdiredはメニューバーの項目Editを抑制します。

(define-key dired-mode-map [menu-bar edit] 'undefined)

editは、メニューバー項目Editに対して グローバルキーマップで使う疑似ファンクションキーです。 グローバルなメニューバー項目を抑制する主な理由は、 モード固有の項目向けに場所を確保するためです。

menu-bar-final-items Variable
通常、メニューバーは、グローバルな項目に ローカルキーマップで定義された項目を続けて表示する。

この変数は、通常の順ではなくメニューバーの底に表示する項目に 対する疑似ファンクションキーのリストを保持する。 デフォルト値は(help-menu)であり、 したがって、ローカルのメニュー項目に続いて、 メニュー項目Helpはメニューバーの最後に通常表示される。

menu-bar-update-hook Variable
このノーマルフックは、 ユーザーがメニューバーをクリックするたびに、 サブメニューを表示するまえに実行される。 これを用いて、内容が変化するサブメニューを更新できる。


Node:Modifying Menus, Previous:Menu Bar, Up:Menu Keymaps

メニューの修正

既存のメニューに新たな項目を挿入するとき、 メニューの既存の項目の特定の場所に挿入したいでしょう。 define-keyで項目を追加すると、通常、メニューの先頭に入ります。 メニューのそれ以外の場所に挿入するには、 define-key-afterを使います。

define-key-after map key binding after Function
keyに対するバインディングbindingmap内に作る。 ただし、map内でのバインディングの位置は、 イベントafterに対するバインディングのあとにする。 引数keyは長さ1、つまり、1要素のみのベクトルか文字列であること。 しかし、afterは1つのイベント型、つまり、 シンボルか文字であり列ではないこと。 新たなバインディングはafterに対するバインディングのうしろに入る。 aftertであると、新たなバインディングは最後、 つまり、キーマップの末尾に入る。

例を示す。

(define-key-after my-menu [drink]
                  '("Drink" . drink-command) 'eat)

これは、疑似ファンクションキー<DRINK>に対するバインディングを作り、 <EAT>に対するバインディングのあとに入れる。

shellモードのメニューSignalsにおいて、 項目breakのあとに項目Workを入れる方法はつぎのとおりである。

(define-key-after
  (lookup-key shell-mode-map [menu-bar signals])
  [work] '("Work" . work-command) 'break)


Node:Modes, Next:, Previous:Keymaps, Up:Top

メジャーモードとマイナモード

モード(mode)とは、Emacsをカスタマイズする定義の集まりであり、 読者は編集中にそれをオン/オフできます。 モードには2種類あります。 メジャーモード(major mode)は、互いに排他的で、 特定種類のテキストの編集に使います。 マイナモード(minor mode)は、 ユーザーがそれぞれを独立にオンにできる機能を提供します。

本章では、メジャーモードやマイナモードの書き方、 それらをモード行に表示する方法、 ユーザーが指定したフックをモードがどのように実行するかについて述べます。 キーマップや構文テーブルなどの関連事項については、 KeymapsSyntax Tablesを参照してください。


Node:Major Modes, Next:, Up:Modes

メジャーモード

メジャーモードは、特定種類のテキストの編集向けにEmacsを特化します。 各バッファには、ある時点では1つのメジャーモードしかありません。

もっとも特化されていないメジャーモードは、 基本(fundamental)モードです。 このモードには、モードに固有な定義や変数の設定がありません。 そのため、Emacsの各コマンドはデフォルトのふるまいをし、 各オプションもデフォルトの状態です。 他のすべてのメジャーモードでは、さまざまなキーやオプションを再定義します。 たとえば、lisp対話モードでは、 C-jeval-print-last-sexp)や <TAB>(lisp-indent-line)など他のキーに対しても 特別なキーバインディングがあります。

読者の特別な編集作業を補佐するために一群の編集コマンドを書く必要がある場合、 新たなメジャーモードを作ることは一般にはよいことです。 実際、メジャーモードを書くことは (マイナモードを書くことはしばしば難しくなるが、 それに対比すれば)簡単です。

新たなモードが既存のモードに類似していても、 既存のモードを2つの目的を果たすように修正するのは 賢いことではありません。 そのようにすると、使い難く保守し難くなるからです。 そのかわりに、既存のメジャーモードの定義をコピーし名前変えてから、 コピーを変更します。 あるいは、派生モード (derived mode) (see Derived Modes)を定義します。 たとえば、emacs/lisp/rmailedit.elにあるrmail編集モードは、 テキスト(text)モードに非常によく似たメジャーモードですが、 追加コマンドが3つあります。 そのような定義がテキスト(text)モードとの違いになるのですが、 rmail編集モードはテキスト(text)モードから派生したものです。

rmail編集モードは、バッファのメジャーモードを一時的に変更して バッファを別の方法(rmailのコマンドではなく Emacsの普通のコマンド)で編集できるようにする例題です。 そのような場合、一時的なメジャーモードには、普通、 バッファの通常のモード(この場合にはrmailモード)に戻る コマンドがあります。 読者は、再帰編集の中で一時的に再定義し、 ユーザーが再帰編集を抜けるともとに戻す方法に魅了されるかもしれません。 しかし、これを複数のバッファで行うと、 再帰編集はもっとも最近に入った再帰からまず抜けるので、 ユーザーの選択に制約を課すことになり悪い方法です。 別のメジャーモードを使えばこのような制約を回避できます。 See Recursive Editing

標準のGNU Emacs Lispのライブラリのディレクトリには、 text-mode.eltexinfo.ellisp-mode.elc-mode.elrmail.elなどのファイルに いくつかのメジャーモードのコードが収めてあります。 モードの書き方を理解するためにこれらのライブラリを調べられます。 テキスト(text)モードは、基本(fundamental)モードについで、 もっとも単純なメジャーモードです。 rmailモードは複雑な特化されたモードです。


Node:Major Mode Conventions, Next:, Up:Major Modes

メジャーモードの慣習

既存のメジャーモードのコードでは、 ローカルキーマップや構文テーブルの初期化、グローバルな名前、フックなどの さまざまなコーディング上の慣習を踏襲しています。 読者が新たなメジャーモードを定義するときには、 これらの慣習に従ってください。


Node:Example Major Modes, Next:, Previous:Major Mode Conventions, Up:Major Modes

メジャーモードの例

基本(fundamental)モードを除くと、 テキスト(text)モードはもっとも単純なモードです。 上に述べた慣習の例示として、text-mode.elの抜粋をあげておきます。

;; モード固有の構文テーブルを作る
(defvar text-mode-syntax-table nil
  "Syntax table used while in text mode.")

(if text-mode-syntax-table
    ()              ; 構文テーブルが既存ならば変更しない
  (setq text-mode-syntax-table (make-syntax-table))
  (modify-syntax-entry ?\" ".   " text-mode-syntax-table)
  (modify-syntax-entry ?\\ ".   " text-mode-syntax-table)
  (modify-syntax-entry ?' "w   " text-mode-syntax-table))

(defvar text-mode-abbrev-table nil
  "Abbrev table used while in text mode.")
(define-abbrev-table 'text-mode-abbrev-table ())

(defvar text-mode-map nil)   ; モード固有のキーマップを作る

(if text-mode-map
    ()              ; キーマップが既存ならば変更しない
  (setq text-mode-map (make-sparse-keymap))
  (define-key text-mode-map "\t" 'indent-relative)
  (define-key text-mode-map "\es" 'center-line)
  (define-key text-mode-map "\eS" 'center-paragraph))

つぎは、テキスト(text)モードのメジャーモード関数の完全な定義です。

(defun text-mode ()
  "Major mode for editing text intended for humans to read....
 Special commands: \\{text-mode-map}
Turning on text-mode runs the hook `text-mode-hook'."
  (interactive)
  (kill-all-local-variables)
  (use-local-map text-mode-map)
  (setq local-abbrev-table text-mode-abbrev-table)
  (set-syntax-table text-mode-syntax-table)
  (make-local-variable 'paragraph-start)
  (setq paragraph-start (concat "[ \t]*$\\|" page-delimiter))
  (make-local-variable 'paragraph-separate)
  (setq paragraph-separate paragraph-start)
  (setq mode-name "Text")
  (setq major-mode 'text-mode)
  (run-hooks 'text-mode-hook))      ; 最後に、フックによるモードの
                                    ;   カスタマイズをユーザーに許す

3つのlispモード(lispモード、emacs-lispモード、lisp対話モード)には、 テキスト(text)モードより多くの機能があり、 それに応じてコードもより複雑です。 これらのモードの書き方を例示する lisp-mode.elからの抜粋をあげておきます。

;; モード固有の構文テーブルを作成する
(defvar lisp-mode-syntax-table nil "")
(defvar emacs-lisp-mode-syntax-table nil "")
(defvar lisp-mode-abbrev-table nil "")

(if (not emacs-lisp-mode-syntax-table) ; 構文テーブルが既存ならば
                                       ;   変更しない
    (let ((i 0))
      (setq emacs-lisp-mode-syntax-table (make-syntax-table))

      ;; 0までの文字に、単語構成文字ではないが
      ;; シンボル名構成文字であるクラスを設定する
      ;; (文字0は、ASCII文字集合では48)
      (while (< i ?0)
        (modify-syntax-entry i "_   " emacs-lisp-mode-syntax-table)
        (setq i (1+ i)))
      ...
      ;; 他の文字の構文を設定する
      (modify-syntax-entry ?  "    " emacs-lisp-mode-syntax-table)
      (modify-syntax-entry ?\t "    " emacs-lisp-mode-syntax-table)
      ...
      (modify-syntax-entry ?\( "()  " emacs-lisp-mode-syntax-table)
      (modify-syntax-entry ?\) ")(  " emacs-lisp-mode-syntax-table)
      ...))
;; lispモード向けの略語表を作る
(define-abbrev-table 'lisp-mode-abbrev-table ())

3つのlispモードは多くのコードを共有しています。 つぎの関数はさまざまな変数に設定します。 lispモードの各メジャーモード関数が呼び出します。

(defun lisp-mode-variables (lisp-syntax)
  (cond (lisp-syntax
	  (set-syntax-table lisp-mode-syntax-table)))
  (setq local-abbrev-table lisp-mode-abbrev-table)
  ...

forward-paragraphなどの関数は、 変数paragraph-startの値を使います。 Lispのコードは普通のテキストとは異なるので、 Lispを扱えるように変数paragraph-startを特別に設定する必要があります。 また、Lispではコメントの字下げは特殊な形なので、 各lispモードには独自のモード固有のcomment-indent-functionが必要です。 これらの変数に設定するコードが、 lisp-mode-variablesの残りの部分です。

  (make-local-variable 'paragraph-start)
  (setq paragraph-start (concat page-delimiter "\\|$" ))
  (make-local-variable 'paragraph-separate)
  (setq paragraph-separate paragraph-start)
  ...
  (make-local-variable 'comment-indent-function)
  (setq comment-indent-function 'lisp-comment-indent))

各lispモードでは、キーマップが多少異なります。 たとえば、lispモードではC-c C-zrun-lispにバインドしますが、 他のlispモードではそうしません。 つぎのコードは、共通するコマンドを設定します。

(defvar shared-lisp-mode-map ()
  "Keymap for commands shared by all sorts of Lisp modes.")

(if shared-lisp-mode-map
    ()
   (setq shared-lisp-mode-map (make-sparse-keymap))
   (define-key shared-lisp-mode-map "\e\C-q" 'indent-sexp)
   (define-key shared-lisp-mode-map "\177"
               'backward-delete-char-untabify))

つぎはlispモード向けのキーマップを設定するコードです。

(defvar lisp-mode-map ()
  "Keymap for ordinary Lisp mode....")

(if lisp-mode-map
    ()
  (setq lisp-mode-map (make-sparse-keymap))
  (set-keymap-parent lisp-mode-map shared-lisp-mode-map)
  (define-key lisp-mode-map "\e\C-x" 'lisp-eval-defun)
  (define-key lisp-mode-map "\C-c\C-z" 'run-lisp))

最後に、emacs-lispモードのメジャーモード関数の完全な定義を示します。

(defun lisp-mode ()
  "Major mode for editing Lisp code for Lisps other than GNU Emacs Lisp.
Commands:
Delete converts tabs to spaces as it moves back.
Blank lines separate paragraphs.  Semicolons start comments.
\\{lisp-mode-map}
Note that `run-lisp' may be used either to start an inferior Lisp job
or to switch back to an existing one.

Entry to this mode calls the value of `lisp-mode-hook'
if that value is non-nil."
  (interactive)
  (kill-all-local-variables)
  (use-local-map lisp-mode-map)          ; モードのキーマップを選択する
  (setq major-mode 'lisp-mode)           ; これによりdescribe-modeは
                                         ; 説明文を探し出せる
  (setq mode-name "Lisp")                ; モード行に表示される
  (lisp-mode-variables t)                ; さまざまな変数を定義する
  (setq imenu-case-fold-search t)
  (set-syntax-table lisp-mode-syntax-table)
  (run-hooks 'lisp-mode-hook))           ; フックによるモードの
                                         ; カスタマイズをユーザーに許す


Node:Auto Major Mode, Next:, Previous:Example Major Modes, Up:Major Modes

メジャーモードの選択方法

Emacsは、ファイル名やファイル自体の情報をもとに、 当該ファイルを訪問するときの新しいバッファに対する メジャーモードを自動的に選択します。 また、ファイル内のテキストで指定されたローカル変数も処理します。

fundamental-mode コマンド
基本(fundamental)モードは、特化してないメジャーモードである。 他のメジャーモードは、実質的には、このモードとの対比で定義されている。 つまり、基本(fundamental)モードから始めて、 それらのメジャーモードではなにを変更するかを定義している。 関数fundamental-modeはフックを実行しないため、 読者はカスタマイズできない。 (Emacsの基本(fundamental)モードのふるまいを変えたければ、 Emacsの大局的な状態を変える必要がある。)

normal-mode &optional find-file コマンド
この関数は、カレントバッファに対して 適切なメジャーモードとバッファローカルな変数を確立する。 この関数はまずset-auto-modeを呼び出し、 続いて、ファイルのローカル変数を必要に応じて解析、束縛、評価するために hack-local-variablesを実行する。

normal-modeに対する引数find-filenil以外であると、 normal-modefind-fileから呼び出されたと仮定する。 その場合、ファイルの末尾や-*-の形式の行にある ローカル変数リストを処理することもある。 変数enable-local-variablesは、この処理を行うかどうかを制御する。 ファイル内でのローカル変数リストの構文については、 See File Variables

読者が対話的にnormal-modeを実行すると 引数find-fileは通常nilである。 その場合、normal-modeは、ローカル変数リストを無条件に処理する。

normal-modeは、メジャーモード関数を呼び出す周りでは condition-caseを使うので、エラーを補足して File mode specification errorにもとのエラーメッセージを続けて エラーを報告する。

enable-local-variables User Option
この変数は、訪問したファイル内のローカル変数リストを処理するかどうかを 制御する。 値tは、ローカル変数リストを無条件に処理することを意味する。 nilは、それらを無視することを意味する。 それ以外の値であると、各ファイルごとにユーザーに問い合わせる。 デフォルト値はtである。

ignored-local-variables Variable
この変数は、ファイルのローカル変数リストで設定してはならない 変数のリストを保持する。 それらの変数に対して指定した値は無視される。

このリストに加えて、 属性risky-local-variablenil以外の値である変数も無視されます。

enable-local-eval User Option
この変数は、訪問したファイル内のローカル変数リストのEval:を 処理するかどうかを制御する。 値tは、それらを無条件に処理することを意味する。 nilは、それらを無視することを意味する。 それ以外の値であると、各ファイルごとにユーザーに問い合わせる。 デフォルト値はmaybeである。

set-auto-mode Function
この関数は、カレントバッファに対して適切なメジャーモードを選択する。 -*-行の値、 (auto-mode-alistを使って)訪問したファイルの名前、 (interpreter-mode-alistを使って)#!行、 ファイルのローカル変数リストをもとに決定する。 しかし、この関数はファイルの末尾付近にある ローカル変数mode:は調べないが、 関数hack-local-variablesは調べる。 See Choosing Modes

default-major-mode User Option
この変数は、新たなバッファに対するデフォルトのメジャーモードを保持する。 標準値はfundamental-modeである。

default-major-modeの値がnilであると、 Emacsは(以前の)カレントバッファのメジャーモードを 新たなバッファのメジャーモードとする。 しかし、メジャーモードコマンドのシンボルの属性mode-classの 値がspecialであると、新たなバッファのメジャーモードにはせず、 かわりに基本(fundamental)モードを使う。 この属性を持つモードは、 特別に準備したテキストに対してのみ有用であるdiredやrmailなどである。

set-buffer-major-mode buffer Function
この関数はバッファbufferのメジャーモードを default-major-modeの値とする。 この変数がnilであると、 (適切ならば)カレントバッファのメジャーモードを使う。

バッファを作成する低レベルの基本関数ではこの関数を使わないが、 switch-to-bufferfind-file-noselectなどの 中レベルのコマンドではバッファを作成するときにこのコマンドを使う。

initial-major-mode Variable
この変数の値は、最初のバッファ*scratch*のメジャーモードを決定する。 値は、メジャーモードコマンドのシンボルであること。 デフォルト値は、lisp-interaction-modeである。

auto-mode-alist Variable
この変数は、ファイル名のパターン(正規表現、see Regular Expressions)と 対応するメジャーモードの連想リストを保持する。 通常、ファイル名パターンでは.el.cなどの接尾辞を調べるが、 そうでなくてもよい。 連想リストの通常の要素は (regexp . mode-function)の形である。

たとえばつぎのとおり。

(("\\`/tmp/fol/" . text-mode)
 ("\\.texinfo\\'" . texinfo-mode)
 ("\\.texi\\'" . texinfo-mode)
 ("\\.el\\'" . emacs-lisp-mode)
 ("\\.c\\'" . c-mode)
 ("\\.h\\'" . c-mode)
 ...)

展開したファイル名(see File Name Expansion)がregexpに一致する ファイルを訪問すると、 set-auto-modeは対応するmode-functionを呼び出す。 この機能により、Emacsはほとんどのファイルに対して 適切なメジャーモードを選択する。

auto-mode-alistの要素が(regexp function t)の 形であると、functionを呼び出したあとで、 Emacsはファイル名のそれまで一致しなかった部分についてauto-mode-alistを 再度探索する。 この機能は解凍パッケージには有用である。 ("\\.gz\\'" function t)の形の要素で、 ファイルを解凍し、.gzを除いたファイル名に従って 解凍済みファイルを適切なモードにできる。

auto-mode-alistにいくつかのパターン対を追加する方法を示す。 (この種の式を読者のファイル.emacsに使える。)

(setq auto-mode-alist
  (append
   ;; ドットで始まる(ディレクトリ名付きの)ファイル名
   '(("/\\.[^/]*\\'" . fundamental-mode)
     ;; ドットのないファイル名
     ("[^\\./]*\\'" . fundamental-mode)
     ;; .Cで終るファイル名
     ("\\.C\\'" . c++-mode))
   auto-mode-alist))

interpreter-mode-alist Variable
この変数は、#!行でコマンドインタープリタを指定している スクリプトに対して用いるメジャーモードを指定する。 この値は、(interpreter . mode)の形の要素から成る リストであること。 たとえば、デフォルトには("perl" . perl-mode)の要素がある。 各要素は、ファイルが指定するインタープリタがinterpreterに 一致したらモードmodeを使うことを意味する。 interpreterの値は、実際には正規表現である。

auto-mode-alistが使用すべきメジャーモードが 指定しなかった場合にのみこの変数を使う。

hack-local-variables &optional force Function
この関数は、カレントバッファの内容に指定されたローカル変数を 必要に応じて、解析、束縛、評価する。

normal-modeで述べたenable-local-variablesの処理は、 実際にはここで行う。 引数forceは、通常、 normal-modeに与えられた引数find-fileからくる。


Node:Mode Help, Next:, Previous:Auto Major Mode, Up:Major Modes

メジャーモードに関するヘルプ

関数describe-modeは、メジャーモードに関する情報を 得るために使います。 通常、C-h mで呼び出されます。 関数describe-modemajor-modeの値を使いますが、 そのために各メジャーモード関数が 変数major-modeに設定する必要があるのです。

describe-mode コマンド
この関数は、現在のメジャーモードの説明文を表示する。

関数describe-modeは、major-modeの値を引数として 関数documentationを呼び出す。 そうして、メジャーモード関数の説明文字列を表示する。 (see Accessing Documentation。)

major-mode Variable
この変数は、カレントバッファのメジャーモードに対するシンボルを保持する。 このシンボルは、当該メジャーモードに切り替えるためのコマンドを 関数定義として持つこと。 関数describe-modeは、 メジャーモードの説明文として当該関数の説明文字列を使う。


Node:Derived Modes, Previous:Mode Help, Up:Major Modes

派生モードの定義

既存のメジャーモードを用いて新たなメジャーモードを定義できると便利です。 これを行う簡単な方法はdefine-derived-modeを使うことです。

define-derived-mode variant parent name docstring body... Macro
これは、nameをモード名を表す文字列として使って variantをメジャーモードコマンドとして定義する。

新たなコマンドvariantは、関数parentを呼び出してから 親モードの特定の機能を無効にするように定義される。

  • 新たなモードは、variant-mapという名前の 独自のキーマップを持つ。 define-derived-modeは、 このキーマップが定義済みでなければ、 parent-mapから継承するようにこのキーマップを初期化する。
  • 新たなモードでは、変数にvariant-syntax-tableに 独自の構文テーブルを保持する。 この変数が定義済みでなければ、 parent-syntax-tableをコピーしてこの変数を初期化する。
  • 新たなモードでは、変数にvariant-abbrev-tableに 独自の略語表を保持する。 この変数が定義済みでなければ、 parent-abbrev-tableをコピーしてこの変数を初期化する。
  • 新たなモードには独自のモードフックvariant-hookがあり、 通常どおり最後にこれを実行する。 (新たなモードでは、parentを呼び出すことの一部として parentのモードフックも実行する。)

さらに、bodyparentの他の部分を無効にする方法を指定できる。 コマンドvariantは、variant-hookを呼び出す直前、 通常の無効化処理を終えてからbodyのフォームを評価する。

引数docstringは、新たなモードに対する説明文字列を指定する。 docstringを省略すると、 define-derived-modeは説明文字列を生成する。

仮想的な例を示す。

(define-derived-mode hypertext-mode
  text-mode "Hypertext"
  "Major mode for hypertext.
\\{hypertext-mode-map}"
  (setq case-fold-search nil))

(define-key hypertext-mode-map
  [down-mouse-3] 'do-hyper-link)


Node:Minor Modes, Next:, Previous:Major Modes, Up:Modes

マイナモード

マイナモード(minor mode)は、メジャーモードの選択とは独立に ユーザーがオン/オフできる機能を提供します。 マイナモードは、個別にも組み合わせてもオンにできます。 マイナモードは、長すぎますが『汎用的に使えるオプション機能のモード』と 命名したようがよいかもしれません。

マイナモードは、普通、1つのメジャーモードを変更するだけではありません。 たとえば、自動詰め込みモード(auto-fillモード)は、 テキスト挿入を許す任意のメジャーモードで使えます。 汎用的であるためには、マイナモードは メジャーモードが行うこととは実質的に独立である必要があります。

マイナモードは、メジャーモードに比べて、実装するのがしばしば困難です。 1つの理由は、任意の順でマイナモードをオン/オフできるようにする 必要があるからです。 マイナモードは、メジャーモードや他のオンになっているマイナモードとは 無関係にその望みの効果を発揮できる必要があります。

しばしば、マイナモードを実装するうえでもっとも大きな問題は、 Emacsの残りの部分に対して必要なフックを探すことです。 マイナモードキーマップにより、従来に比べて簡単になります。


Node:Minor Mode Conventions, Next:, Up:Minor Modes

マイナモードを書くための慣習

メジャーモードに対するのと同じように、 マイナモードを書くうえでの慣習があります。 メジャーモードの慣習には、マイナモードにも適用されるものがあります。 つまり、モードを初期化する関数の名前、 グローバルシンボルの名前、キーマップやその他のテーブルや表の使い方です。

それらに加えて、マイナモードに固有な慣習もあります。

このリストに要素を1回だけ追加するならばadd-to-listも使えます (see Setting Variables)。


Node:Keymaps and Minor Modes, Next:, Previous:Minor Mode Conventions, Up:Minor Modes

キーマップとマイナモード

各マイナモードは、モードがオンのときに活性になる独自のキーマップを持てます。 マイナモード向けのキーマップを設定するには、 minor-mode-map-alistに要素を追加します。 See Active Keymaps

マイナモードキーマップの1つの用途は、 ある種の自己挿入文字のふるまいを変更して、 自己挿入に加えてなにかを行わせるようにすることです。 一般に、self-insert-commandをカスタマイズする機構は (略語モードや自動詰め込みモード向けに設計された)特別な場合に限られるので、 このようなことを行う唯一の方法です。 (標準のself-insert-commandの定義を読者独自の定義で置き換えないこと。 エディタコマンドループはこの関数を特別扱いしている。)

マイナモードでバインドしているキー列は、C-cで始まり、 {}<>:;以外の 句読点文字の1つが続くようにします。 (除外した句読点文字はメジャーモード向けに予約されている。)


Node:Easy-Mmode, Previous:Keymaps and Minor Modes, Up:Minor Modes

Easy-Mmode

パッケージeasy-mmodeは、マイナモードを実装する便利な方法を提供します。 これを使うと、単純なマイナモードを1つの自己完結した定義に指定できます。

easy-mmode-define-minor-mode mode doc &optional init-value mode-indicator keymap Macro
このマクロは、mode(シンボル)という名前の新しいマイナモードを定義する。

このマクロは、マイナモードをトグルする modeという名前のコマンドを定義し、 その説明文字列をdocとする。

また、modeという名前の変数も定義する。 この変数はモードのオン/オフにしたがってt/nilに設定される。 この変数はinit-valueに初期化される。

文字列mode-indicatorは、モードがオンのときにモード行に 表示される文字列である。 それがnilであるとモード行にはモードを表示しない。

省略可能な引数keymapは、マイナモードのキーマップを指定する。 これは、値がキーマップであるような変数の名前か、 つぎの形のバインディングを指定した連想リストであること。

(key-sequence . definition)

easy-mmode-define-minor-modeを使った例を示します。

(easy-mmode-define-minor-mode hungry-mode
  "Toggle Hungry mode.
With no argument, this command toggles the mode.
Non-null prefix argument turns on the mode.
Null prefix argument turns off the mode.

When Hungry mode is enabled, the control delete key
gobbles all preceding whitespace except the last.
See the command \\[hungry-electric-delete]."
 ;; 初期値
 nil
 ;; モード行への表示
 " Hungry"
 ;; マイナモードのバインディング
 '(("\C-\^?" . hungry-electric-delete)
   ("\C-\M-\^?"
    . (lambda ()
        (interactive)
        (hungry-electric-delete t)))))

これは、『hungryモード』という名前のマイナモードを定義します。 モードをトグルするコマンドの名前はhungry-mode、 モードのオン/オフを表す変数の名前はhungry-mode、 モードがオンのときに活性なキーマップを保持する 変数の名前はhungry-mode-mapです。 C-<DEL>C-M-<DEL>に対するキーバインディングで キーマップを初期化します。


Node:Mode Line Format, Next:, Previous:Minor Modes, Up:Modes

モード行の書式

Emacsの(ミニバッファ専用ウィンドウを除く)各ウィンドウにはモード行があって、 ウィンドウに表示しているバッファに関する状態情報を表示しています。 モード行には、バッファ名、対応するファイル、再帰編集の深さ、 メジャーモードとマイナモードなどのバッファに関する情報が含まれます。

本節では、モード行の内容の制御方法について述べます。 モード行に表示される情報のほとんどは オンになっているメジャーモードとマイナモードに関係するので、 本章に含めます。

mode-line-formatは、カレントバッファのモード行に表示する 雛型を保持しているバッファローカルな変数です。 同一バッファに対するすべてのウィンドウは同じmode-line-formatを使い、 それらのモード行は(スクロールの割合や行やコラム位置を除いて) 同じように表示されます。

ウィンドウのモード行は、通常、ウィンドウに別のバッファを表示したときや、 バッファの変更状態がnilからtへあるいはその逆の変化をしたときに 更新されます。 mode-line-format(see Mode Line Variables)が参照する 変数を修正したり、テキストの表示方法に影響するその他の変数やデータ構造 (see Display)を変更したときには、新しい情報を表示したり 新たな方法で表示するためにモード行の更新を強制できます。

force-mode-line-update Function
カレントバッファのモード行の更新を強制する。

モード行は、通常、反転表示されます。 Inverse Videomode-line-inverse-videoを参照してください。


Node:Mode Line Data, Next:, Up:Mode Line Format

モード行のデータ構造

モード行の内容は、バッファローカルな変数mode-line-formatに 保持されたリスト、文字列、シンボル、数から成るデータ構造で制御されます。 このデータ構造をモード行構成(mode line construct)と呼びます。 これは単純なモード行構成から再帰的に構築します。 同じデータ構造はフレームタイトル(see Frame Titles)を 構築するためにも使われます。

mode-line-format Variable
この変数の値は、モード行全体の書式に責任を持つモード行構成である。 この変数の値は、モード行のテキストを作るためにどの変数を使うか、 それらはモード行のどこに現れるかを制御する。

モード行構成は、定まったテキストの文字列のように単純でもかまいませんが、 普通は、テキストを作るための別の変数の使い方を指定します。 それらの変数の多くはそれ自身、それらの値として モード行構成を持つように定義されています。

mode-line-formatのデフォルト値は、 mode-nameminor-mode-alistなどの変数の値を使います。 多くの目的には、mode-line-formatが参照するいくつかの変数を 変えるだけで十分です。

モード行構成は、リスト、シンボル、文字列のいずれかです。 その値がリストであれば、その各要素はリスト、シンボル、文字列のいずれかです。

string
モード行構成としての文字列は、 %記法を除いて、モード行にそのまま表示される。 %のうしろの10進数は、右側に空白を埋める (つまりデータは左端に揃えられる)ときのフィールド幅を指定する。 see %-Constructs
symbol
モード行構成としてのシンボルは、その値を表す。 symbolの値は、symbolのかわりにモード行構成として使われる。 しかし、tnilのシンボル、および、シンボルの値が空のものは 無視する。

例外が1つある: symbolの値が文字列であると、%記法を処理せずに 文字列をそのまま表示する。

(string rest...) or (list rest...)
最初の要素が文字列かリストであるリストは、 すべての要素を再帰的に処理し、結果を連結することを意味する。 これはもっとも多用されるモード行構成の形である。
(symbol then else)
最初の要素がシンボルであるリストは条件節であり、 その意味はsymbolの値に依存する。 その値がnil以外であると、 2番目の要素thenをモード行構成として再帰的に処理する。 symbolの値がnilであると、 3番目の要素elseをモード行構成として再帰的に処理する。 elseは省略してもよいが、その場合、 symbolの値がnilであるところの要素はモード行に表示されない。
(width rest...)
最初の要素が整数であるリストは、 restの結果の切り詰めや引き伸しを指定する。 残りの要素restはモード行構成として再帰的に処理され連結される。 (widthが正であれば)結果の右端に空白を追加したり、 (widthが負であれば)結果を(-width幅に) 右端から切り詰める。

たとえば、ウィンドウの上端より上にバッファの何割があるかを表示するには、 (-3 "%p")のようなリストを使う。

読者がmode-line-format自体を変更するときには、 新しい値では、デフォルト値(see Mode Line Variables)に現れる ものと同じ変数を使い、それらの値をコピーして使ったり、 別の書式で情報を表示したりしないでください。 こうしておけば、それらの変数に対する変更を介した ユーザーや(display-timeやメジャーモードなどの)Lispプログラムが行った カスタマイズが効果を発揮できます。

ホスト名やデフォルトディレクトリを含んだ shell-modeに有用なmode-line-formatの例を示します。

(setq mode-line-format
  (list "-"
   'mode-line-mule-info
   'mode-line-modified
   'mode-line-frame-identification
   "%b--"
   ;; リストを作るときに評価されることに注意
   ;; 単なる文字列のモード行構成を作る
   (getenv "HOST")
   ":"
   'default-directory
   "   "
   'global-mode-string
   "   %[("
   'mode-name
   'mode-line-process
   'minor-mode-alist
   "%n"
   ")%]--"
   '(which-func-mode ("" which-func-format "--"))
   '(line-number-mode "L%l--")
   '(column-number-mode "C%c--")
   '(-3 . "%p")
   "-%-"))

(変数line-number-modecolumn-number-modewhich-func-modeは特定のマイナモードをオンにする。 通常どおり、これらの変数の名前はマイナモードコマンドの名前でもある。)


Node:Mode Line Variables, Next:, Previous:Mode Line Data, Up:Mode Line Format

モード行に使われる変数

本節では、mode-line-formatの標準値でモード行のテキストに 含められる変数について述べます。 これらの変数に関しては、本来特別なことはありません。 別の変数を使うようにmode-line-formatを変更すれば、 別の変数でもモード行において同じ効果を発揮します。

mode-line-mule-info Variable
この変数は、言語環境、バッファのコーディングシステム、 現在の入力方式に関する情報を表示するモード行構成の値を保持する。 see Non-ASCII Characters

mode-line-modified Variable
この変数は、カレントバッファが変更されたかどうかを表示する モード行構成の値を保持する。

mode-line-modifiedのデフォルト値は("%1*%1+")である。 これは、バッファが変更されていると**を、 未変更ならば--を、読み出し専用ならば%%を、 読み出し専用でしかも変更されていれば%*を モード行に表示することを意味する。

この変数を変更してもモード行の更新を強制しない。

mode-line-frame-identification Variable
この変数はカレントフレームを識別する。 複数のフレームを表示できるウィンドウシステムを使用している場合には デフォルト値は" "であり、 ある時点で1つのフレームしか表示できない普通の端末を使用している場合には "-%F "である。

mode-line-buffer-identification Variable
この変数はウィンドウに表示しているバッファを識別する。 デフォルト値は("%12b")であり、 空白で埋めて最低12コラムでバッファ名を表示する。

global-mode-string Variable
この変数は、デフォルトでモード行のバッファ名の直後に現れる モード行指定を保持する。 コマンドdisplay-timeは、 global-mode-stringが時刻と負荷情報を含んだ 変数display-time-stringを参照するように設定する。

%M記法はglobal-mode-stringの値を使うが、 この変数はmode-line-formatでモード行に含まれるため %Mは廃れた記法である。

mode-name Variable
このバッファローカルな変数は、 カレントバッファのメジャーモードの『愛称』を保持する。 各メジャーモードは、モード行にモード名が現れるようにこの変数に設定すること。

minor-mode-alist Variable
この変数は、モード行にマイナモードがオンであることを表示する方法を 指定する要素からなる連想リストを保持する。 minor-mode-alistの各要素は、2要素リストであること。
(minor-mode-variable mode-line-string)

より一般的には、mode-line-stringはどのようなモード行指定でもよい。 それは、minor-mode-variableの値がnil以外のときに モード行に現れ、さもなければ現れない。 これらの文字列は、繋がらないように空白で始まること。 慣習的には、特定モードに対するminor-mode-variableは、 当該マイナモードがオンであるとnil以外に設定される。

minor-mode-alistのデフォルト値はつぎのとおり。

minor-mode-alist
=> ((vc-mode vc-mode)
    (abbrev-mode " Abbrev")
    (overwrite-mode overwrite-mode)
    (auto-fill-function " Fill")
    (defining-kbd-macro " Def")
    (isearch-mode isearch-mode))

minor-mode-alist自体はバッファローカルではない。 マイナモードが各バッファごとにオンにできる場合には、 連想リストに指定した対応する各変数はバッファローカルであること。

mode-line-process Variable
このバッファローカルな変数は、 サブプロセスとの通信用に使われているモードの処理状態に関する モード行の情報を保持する。 メジャーモード名の直後に空白で区切らずに表示される。 たとえば、バッファ*shell*におけるこの変数の値は(":%s")であり、 シェルがその状態をメジャーモードとともに(Shell: run)のように 表示できる。 通常、この変数はnilである。

default-mode-line-format Variable
この変数は、mode-line-formatを変更していないバッファの デフォルトのmode-line-formatの値を保持する。 これは(default-value 'mode-line-format)と同じである。

default-mode-line-formatのデフォルト値はつぎのリストである。

("-"
 mode-line-mule-info
 mode-line-modified
 mode-line-frame-identification
 mode-line-buffer-identification
 "   "
 global-mode-string
 "   %[("
 mode-name
 mode-line-process
 minor-mode-alist
 "%n"
 ")%]--"
 (which-func-mode ("" which-func-format "--"))
 (line-number-mode "L%l--")
 (column-number-mode "C%c--")
 (-3 . "%p")
 "-%-")

vc-mode Variable
各バッファにおいてバッファローカルな変数vc-modeは、 バッファで訪問したファイルが版管理されているか、 そうならばその方式を記録している。 版管理されていない場合はその値はnil、 さもなければモード行に表示される文字列である。


Node:%-Constructs, Previous:Mode Line Variables, Up:Mode Line Format

モード行の%記法

以下は、認識される%記法とその意味の表です。 %%以外の記法では、 最大表示文字数を指定する10進数を%のあとに追加できます。

%b
関数buffer-nameで得られたカレントバッファ名。 see Buffer Names
%f
関数buffer-file-nameで得られた訪問したファイルの名前。 see Buffer File Name
%F
選択しているフレームのタイトル(ウィンドウシステム上のみ)か名前。 see Window Frame Parameters
%c
ポイントの現在のコラム番号。
%l
ポイントの現在の行番号。
%*
バッファが読み出し専用であれば%buffer-read-onlyを参照)、
バッファが変更されていれば*buffer-modified-pを参照)、
さもなければ-。 see Buffer Modification
%+
バッファが変更されていれば*buffer-modified-pを参照)、
バッファが読み出し専用であれば%buffer-read-onlyを参照)、
さもなければ-%*との違いは、変更された読み出し専用バッファに対してのみである。 see Buffer Modification
%&
バッファが変更されていれば*、さもなければ-である。
%s
process-statusで得たカレントバッファに属するサブプロセスの状態。 see Process Information
%t
訪問したファイルがテキストファイルであるかバイナリファイルであるかを表す。 (特定のオペレーティングシステムでのみ意味を持つ。)
%p
ウィンドウの上端の上にあるバッファのテキストの割合、 あるいは、TopBottomAllのいずれかである。
%P
ウィンドウの下端の上にあるバッファのテキスト (ウィンドウに見えてるテキストと上端の上にあるテキスト)の割合に バッファの先頭が見えていればTopを加えたもの、 あるいは、BottomAllのいずれかである。
%n
ナロイングしているとNarrow、さもなければなにもなし。 (Narrowingnarrow-to-regionを参照)。
%[
(ミニバッファのレベルを除く)再帰編集レベルの深さを表す。 各編集レベルごとに1つの[。 see Recursive Editing
%]
(ミニバッファのレベルを除く)各再帰編集レベルごとに1つの]
%%
文字%%記法を許す文字列に%をそのまま含めるための方法である。
%-
モード行の残り部分を埋めるに十分な個数のダッシュ。

つぎの2つの%記法はまだ使えますが、 変数mode-nameglobal-mode-stringを 使って同じ効果を得られるのでこれらは廃れた記法です。

%m
mode-nameの値。
%M
global-mode-stringの値。 現在、display-timeglobal-mode-stringの値を変更する。


Node:Imenu, Next:, Previous:Mode Line Format, Up:Modes

iメニュー

iメニュー(Imenu)とは、ユーザーが バッファ内の定義や節の一覧からその1つを選ぶと バッファ内の当該箇所へ直接移動できる機能です。 iメニューは、 バッファ内の定義や部分の名前や位置を表すバッファインデックスを 構築しておくことで動作し、 当該箇所へ移動するためにユーザーがそれらの1つを選べるようにします。 本節ではメジャーモードに対するiメニューをカスタマイズする方法を説明します。

普通のもっとも単純な方法は、 変数imenu-generic-expressionに設定することです。

imenu-generic-expression Variable
この変数がnil以外であると、 iメニュー向けの定義を探すための正規表現を指定する。 もっとも単純な場合、要素はつぎのような形である。
(menu-title regexp subexp)

ここで、menu-titlenil以外であると、 この要素に一致したものはバッファインデックスのサブメニューに置くことを 意味する。 menu-title自体はサブメニューの名前を指定する。 menu-titlenilであると、 この要素に一致したものはバッファインデックスのメニューに直接置かれる。

リストの2番目の要素regexpは正規表現 (see Regular Expressions)であり、 これに一致した箇所がバッファインデックスに現れる定義になる。 3番目の要素subexpは、 定義の名前に一致するregexpの部分式である。

要素はつぎの形でもよい。

(menu-title regexp index function arguments...)

この要素に一致するものは、バッファインデックスの特別な項目になり、 ユーザーが当該項目を選ぶと、 item-name、バッファ位置、argumentsを引数として functionを呼び出す。

emacs-lispモード向けには、patternはつぎのようになる。

((nil "^\\s-*(def\\(un\\|subst\\|macro\\|advice\\)\
\\s-+\\([-A-Za-z0-9+]+\\)" 2)
 ("*Vars*" "^\\s-*(def\\(var\\|const\\)\
\\s-+\\([-A-Za-z0-9+]+\\)" 2)
 ("*Types*"
  "^\\s-*\
(def\\(type\\|struct\\|class\\|ine-condition\\)\
\\s-+\\([-A-Za-z0-9+]+\\)" 2))

この変数に設定すると、 カレントバッファにおいてバッファローカルな変数になる。

imenu-case-fold-search Variable
この変数は、imenu-generic-expressionとの一致に際して 大文字小文字を区別するかどうかを制御する。 デフォルトはtであり、大文字小文字を区別せずに一致をとる。

この変数に設定すると、 カレントバッファにおいてバッファローカルな変数になる。

imenu-syntax-alist Variable
この変数は、imenu-generic-expressionを処理中に カレントバッファの構文テーブルに優先する 構文テーブルの変更部分の連想リストである。 各要素はつぎの形であること。
(characters . syntax-description)

CARcharactersは、文字か文字列である。 それらの文字は、指定した構文syntax-descriptionであることを意味する。 これはmodify-syntax-entry(see Syntax Table Functions)に 渡される。

この機能は典型的には、 通常のシンボル構成文字を単語構成文字として扱い、 imenu-generic-expressionを単純化し一致処理を速くする。 たとえば、fortranモードではつぎのように使っている。

  (setq imenu-syntax-alist '(("_$" . "w")))

こうすると、imenu-generic-expressionのパターンでは、 \\(\\sw\\|\\s_\\)+のかわりに\\sw+を使える。 この技法は、名前の先頭文字の集合を名前の残りの文字の集合よりも 小さく制限する必要があるモードで使うには不便であることに注意してほしい。

この変数に設定すると、 カレントバッファにおいてバッファローカルな変数になる。

メジャーモードのiメニューをカスタマイズする別の方法は、 変数imenu-prev-index-position-functionimenu-extract-index-name-functionに設定することです。

imenu-prev-index-position-function Variable
この変数がnil以外であると、その値は、 バッファインデックスに置くつぎの定義を ファイルで後向きに探すための関数であること。

その関数は、バッファインデックスの項目に対応する箇所にポイントを置くこと。 項目がみつからなければnilを返すこと。

この変数に設定すると、 カレントバッファにおいてバッファローカルな変数になる。

imenu-extract-index-name-function Variable
この関数がnil以外であると、その値は、 ポイントが変数imenu-prev-index-position-functionが返した 定義の部分にあると仮定して、当該定義の名前を返す関数であること。

この変数に設定すると、 カレントバッファにおいてバッファローカルな変数になる。

メジャーモードのiメニューをカスタマイズする最後の方法は、 変数imenu-create-index-functionに設定することです。

imenu-create-index-function Variable
この関数は、バッファインデックスの作成に使う関数を指定する。 その関数は引数なしで、カレントバッファに対するインデックスを返すこと。 save-excursionの内側から呼ばれるので、 その関数がポイントをどこに置こうと関係ない。

デフォルト値は、インデックスの連想リストを生成するために imenu-generic-expressionを使う関数である。 読者が別の関数を指定すれば、imenu-generic-expressionは使われない。

この変数に設定すると、 カレントバッファにおいてバッファローカルな変数になる。

imenu-index-alist Variable
この変数は、カレントバッファに対するインデックスの連想リストを保持する。 この変数に設定すると、 カレントバッファにおいてバッファローカルな変数になる。

連想リストの単純な要素は(index-name . index-position) のような形である。 このような単純な要素を選ぶと、 バッファ内でindex-positionへ移動する効果がある。

特別な要素は(index-name position function arguments...)のような形である。 このような特別な要素を選ぶと、 つぎのようなフォームを実行する。

(funcall function index-name position arguments...)

入れ子になった部分連想リストの要素は (index-name sub-alist)のような形である。


Node:Font Lock Mode, Next:, Previous:Imenu, Up:Modes

フォントロック(font-lock)モード

フォントロック(font-lock)モードとは、 バッファ内の特定部分に対して、それらの構文上の役割に応じた 属性faceを自動的に付加する機能のことです。 バッファを解析する方法はメジャーモードに依存しますが、 ほとんどのメジャーモードでは、 どの文脈でどのフェイスを使うかを指示する条件を定義します。 本節では、特定の言語向けに、いいかえれば、 特定のメジャーモード向けに フォントロックをカスタマイズする方法を説明します。

フォントロック(font-lock)モードは、強調表示すべきテキストを 2つの方法で、つまり、構文テーブルに基づいた構文解析、あるいは、 (通常、正規表現による)探索で探します。 構文解析による処理を最初に行ってコメントや文字列定数を探し、 font-lock-comment-facefont-lock-string-face (see Faces for Font Lock)を使ってそれらを強調表示します。 探索による処理がこれに続きます。


Node:Font Lock Basics, Next:, Up:Font Lock Mode

フォントロック(font-lock)の基本

フォントロック(font-lock)モードがテキストを強調表示する方法を 制御する変数がいくつかあります。 しかし、メジャーモードでこれらの変数を直接に設定するべきではありません。 そのかわりに、バッファローカルな 変数font-lock-defaultsに設定すべきです。 フォントロック(font-lock)モードがオンになると、 この変数に設定された値を使って他のすべての変数に設定します。

font-lock-defaults Variable
この変数はメジャーモードがバッファローカルな変数として設定し、 当該モードにおいてテキストをどのように表示するかを指定する。 値はつぎの形であること。
(keywords keywords-only case-fold
 syntax-alist syntax-begin other-vars...)

最初の要素keywordsは、 間接的にfont-lock-keywordsの値を指定する。 要素keywordsがシンボルであると、 その変数としての値がfont-lock-keywordsに使われる。 あるいは、要素keywordsがそのようなシンボルのリストであると、 各シンボルが1つのレベルの表示方法を指定する。 最初のシンボルはレベル1の表示方法、 2番目のシンボルはレベル2の表示方法といった具合である。

2番目の要素keywords-onlyは、 変数font-lock-keywords-onlyの値を指定する。 これがnil以外であると(文字列やコメントの)構文による処理を行わない。

3番目の要素case-foldは、 font-lock-case-fold-searchの値を指定する。 これがnil以外であると、フォントロック(font-lock)モードは font-lock-keywordsで指定された探索で 大文字小文字を区別しない。

4番目の要素syntax-alistnil以外である場合、 それは(char-or-string . string)の形の コンスセルのリストであること。 これらは表示方法を選ぶための構文テーブルの設定に使われる (see Syntax Table Functions)。 得られた構文テーブルはfont-lock-syntax-tableに保持される。

5番目の要素syntax-beginは、 font-lock-beginning-of-syntax-functionの値を指定する (下記参照)。

other-vars以降の要素は、 (variable . value)という形である。 この種の要素は、表示方法の選択に影響する その他の変数に設定するために使われる。


Node:Search-based Fontification, Next:, Previous:Font Lock Basics, Up:Font Lock Mode

探索に基づくフォント選択

フォントロック(font-lock)モードのカスタマイズにおいて もっとも重要な変数はfont-lock-keywordsです。 探索に基づく表示方法の選択における探索条件を指定します。

font-lock-keywords Variable
この変数の値は、強調表示するべきキーワードのリストである。 このリストに正規表現を書く場合には注意すること。 貧弱な書き方をしたパターンであると、動作を劇的に遅くする!

font-lock-keywordsの各要素は、 特定のテキストの探し方と 当該テキストをどのように強調表示するか指定します。 フォントロック(font-lock)モードは、 font-lock-keywordsの要素を1つ1つ処理し、 各要素において、それに一致するものすべてを探して処理します。 通常、すでに表示方法を選択済みのテキスト部分については、 それ以降の要素に一致しても表示方法を変えません。 しかし、highlighterの要素overrideを使って、 異なるふるまいを指定できます。

font-lock-keywordsの各要素はつぎのいずれかの形です。

regexp
正規表現regexpに一致したものはすべて font-lock-keyword-faceを使って強調表示する。
;; 孤立したfooの出現は
;; font-lock-keyword-faceで強調表示する。
"\\<foo\\>"

関数regexp-opt(see Syntax of Regexps)は、 異なる複数個のキーワードに一致する最適な正規表現を 計算するのに有用である。

function
関数functionを呼び出してテキストを探し、 それが探し出したものをfont-lock-keyword-faceを使って強調表示する。

functionは、探索限界を引数として呼び出される。 みつかればnil以外を返すとともに みつけた部分を表すマッチデータを設定する。

(matcher . match)
この種の要素では、matcherは、上に述べた正規表現か関数を表す。 CDRmatchは、(matcherに一致した部分全体のかわりに) 強調表示すべきmatcherの部分式を指定する。
;; fubarの各出現のbarを
;; font-lock-keyword-faceで強調表示
("fu\\(bar\\)" . 1)

正規表現matcherを作るためにregexp-optを使った場合、 matchの値を計算するには regexp-opt-depth(see Syntax of Regexps)を使える。

(matcher . facename)
この種の要素では、facenameは、 強調表示に使うフェイス名を指定する値を表す式である。
;; fubarの出現は、fubar-faceの値で
;; 表されたフェイスを使って強調表示
("fubar" . fubar-face)

(matcher . highlighter)
この種の要素では、highlighterは、 matcherに一致した部分の強調表示方法を指定するリストである。 つぎの形であること。
(subexp facename override laxmatch)

CARsubexpは、 強調表示すべき一致部分の部分式を指定する整数 (0は一致部分全体を意味する)である。 2番目の要素facenameは、上に述べたようにフェイスを指定する。

highlighterの最後の2つの要素、 overridelaxmatchはフラグである。 overridetであると、当該要素は、 font-lock-keywordsのまえの要素で決定済みの 表示方法に優先することを表す。 keepであると、他の要素では表示方法が決定していない 各文字の表示方法を表す。 prependであると、 属性faceの先頭にフェイスfacenameを追加する。 appendであると、 属性faceの末尾にフェイスfacenameを追加する。

laxmatchnil以外であると、 matcherで一致したものの中にsubexp番目の部分式が なくてもエラーとしないことを意味する。

この種の要素とその動作の例を示す。

;; foobarの出現の表示方法がすでに決まっていても
;; foo-bar-faceで強調表示する
;; foo-bar-faceの値はフェイスであること
("foo\\|bar" 0 foo-bar-face t)

;; 関数fubar-matchがみつけた各出現内の最初の部分式を
;; fubar-faceの値が表すフェイスで強調表示する
(fubar-match 1 fubar-face)

(matcher highlighters...)
この種の要素は、1つのmatcherに対して 複数のリストhighlighterを指定する。 これが有用であるためには、 各highlightersubexpの値が異なること。 つまり、それぞれをmatcherの異なる部分式に適用できること。
(eval . form)
formは、バッファにおいてfont-lock-keywordsのこの値が 始めて使われたときに評価すべき式である。 その値は、この表にあげた形の1つであること。

警告: font-lock-keywordsの要素は、 行をまたがって一致するように設計しないこと。 そのような処理は信頼性がない。 font-lock-fontify-bufferは、行にまたがるパターンを正しく扱えるが、 読者がバッファを編集したときの更新処理では、 一度に1行ずつ処理するために正しく扱えない。


Node:Other Font Lock Variables, Next:, Previous:Search-based Fontification, Up:Font Lock Mode

その他のフォントロック変数

本節では、font-lock-defaultsを用いてメジャーモードで 設定できる他の変数について述べます。

font-lock-keywords-only Variable
nil以外であると、フォントロック(font-lock)モードは、 構文に基づいてコメントや文字列を強調表示すべきでないことを意味する。 font-lock-keywordsに基づく強調表示のみを行う。

font-lock-keywords-case-fold-search Variable
nil以外であると、font-lock-keywordsの 正規表現探索では大文字小文字を区別しないことを意味する。

font-lock-syntax-table Variable
この変数は、コメントや文字列の表示方法に用いる 構文テーブルを指定する。

font-lock-beginning-of-syntax-function Variable
この変数がnil以外であると、 ポイントを構文上の『トップレベル』で文字列やコメントの外側に 後方移動する関数であること。 フォントロック(font-lock)モードは、 構文に基づく処理において正しい結果を得るために 必要に応じてこの関数を使う。

関数は引数なしで呼び出される。 ポイントを構文ブロックの先頭に置くこと。 典型的な値は、 beginning-of-line(行頭は構文ブロックの外側である)、 あるいは、 プログラム向けのモードではbeginning-of-defun、 テキスト向けのモードではbackward-paragraph (モード固有の関数は構文ブロックの外側にポイントを移動する)である。

値がnilであると、バッファの先頭を構文ブロックの外側の位置として使う。 これは誤りではないが、動作を遅くする。

font-lock-mark-block-function Variable
この変数がnil以外であると、 コマンドM-g M-gfont-lock-fontify-block)による 再表示のためにテキストの括られた範囲を選ぶために 引数なしで呼ばれ関数であること。

関数は、選んだ範囲にリージョンを設定すること。 正しい結果を得られるように大きめのテキスト範囲を選ぶのがよいが、 再表示処理が遅くならないように大きすぎないこと。 典型的な値は、プログラム向けモードではmark-defun、 テキスト向けモードではmark-paragraphである。


Node:Levels of Font Lock, Next:, Previous:Other Font Lock Variables, Up:Font Lock Mode

フォントロックのレベル

多くのメジャーモードでは、3段階の表示方法を提供します。 font-lock-defaultskeywordsに シンボルのリストを使って複数レベルを定義できます。 各シンボルは1つのレベルの表示方法を指定します。 どのレベルを選ぶかはユーザーの責任です。 指定したレベルのシンボルの値はfont-lock-keywordsの初期化に使われます。

表示方法のレベルを定義する際の慣習をあげておきます。


Node:Faces for Font Lock, Next:, Previous:Levels of Font Lock, Up:Font Lock Mode

フォントロックのフェイス

フォントロック(font-lock)モードでは任意のフェイスを使えますが、 フォントロック(font-lock)モード向けに特別に定義さたフェイスがあります。 これらのシンボルのおのおのは、フェイス名でもあり、 シンボル自身をデフォルト値とする変数でもあります。 つまり、font-lock-comment-faceのデフォルト値は、 font-lock-comment-faceです。 これは、 フェイス名を値に持つような式を書くfont-lock-keywordsなどの場面で、 font-lock-comment-faceと書けることを意味します。

font-lock-comment-face
(典型的には)コメントに使われる。
font-lock-string-face
(典型的には)文字列に使われる。
font-lock-keyword-face
(典型的には)キーワード、つまり、 Cのforifのように構文的に重要な名前に使われる。
font-lock-builtin-face
(典型的には)組み込み関数の名前に使われる。
font-lock-function-name-face
(典型的には)関数定義/宣言内において、 定義/宣言されている関数の名前に使われる。
font-lock-variable-name-face
(典型的には)変数定義/宣言内において、 定義/宣言されている変数の名前に使われる。
font-lock-type-face
(典型的には)ユーザー定義のデータ型の名前が定義/参照される場所において、 それらの名前に使われる。
font-lock-constant-face
(典型的には)定数の名前に使われる。
font-lock-warning-face
(典型的には)独特な構文や別のテキストの意味を大きく変えるようなものに 使われる。 たとえば、Emacs Lispの;;;###autoloadや Cの#error指定に使われる。


Node:Syntactic Font Lock, Previous:Faces for Font Lock, Up:Font Lock Mode

構文的なフォントロック

フォントロック(font-lock)モードは、 属性syntax-tableを自動更新するためにも使えます。 1つの構文テーブルだけでは十分でないような言語において有用です。

font-lock-syntactic-keywords Variable
この変数は構文的なフォントロックをオンにし制御する。 その値はつぎの形の要素からなるリストであること。
(matcher subexp syntax override laxmatch)

この要素の各部分には、つぎのfont-lock-keywordsの対応する種類の要素と 同じ意味がある。

(matcher subexp facename override laxmatch)

しかし、属性faceに使う値facenameを指定するかわりに、 属性syntax-tableに使う値syntaxを指定する。 ここで、syntaxは、構文テーブルを値とする変数、 (syntax-code . matching-char)の形の構文テーブルの項目、 あるいは、この2種類のどちらかを値とする式である。


Node:Hooks, Previous:Font Lock Mode, Up:Modes

フック

フック(hook)とは、既存のプログラムから特定の場面で 呼び出される(1つか一連の)関数を収めた変数です。 Emacsは、カスタマイズのためにフックを用意しています。 ほとんどの場合、フックはファイル.emacsで設定しますが、 Lispプログラムが行ってもかまいません。 標準のフック関数一覧については、See Standard Hooks

Emacsの多くのフックはノーマルフック(normal hook)です。 これらの変数は、引数なしで呼び出される関数のリストを保持しています。 フック名が-hookで終っていると、ノーマルフックを意味します。 読者がそれらを単一の方法で使えるように、 可能な限りノーマルフックにするように心掛けています。

各メジャーモード関数は、 その初期化の最終段階でモードフック(mode hook)と呼ばれる ノーマルフックを実行すると期待されます。 これにより、モードがすでに設定したバッファローカルな変数を上書きすることで、 ユーザーがモードのふるまいをカスタマイズしやすくしています。 しかし、フックは別の場面でも使われています。 たとえば、フックsuspend-hookは、 Emacsが自身を一時休止する直前に実行されます。 (see Suspending Emacs)。

ノーマルフックにフック関数を追加する推奨方法は、 add-hook(下記参照)を呼ぶことです。 フック関数は、funcall(see What Is a Function)が 受け付けるならばどんな種類の関数でもかまいません。 ほとんどのノーマルフック変数は最初は空ですが、 add-hookはその扱い方を知っています。

フック変数の名前が-hookで終らない場合、 それがアブノーマルフック(abnormal hook)であることを表します。 読者は、そのようなフックの正しい使い方を説明書で調べるべきです。

変数名が-functions-hooksで終っていると、 その値は関数のリストですが、 それらの関数を引数ありで呼び出したり、 関数の戻り値をどこかで使うという意味でアブノーマル(異常)なのです。 リストに関数を追加するにはadd-hookを使えますが、 関数を書くときには注意する必要があります。 (これらの変数のうち、実際にはノーマルフックであるものもある。 ノーマルフックには-hookを使うという慣習を 確立するまえに命名したものである。)

変数名が-functionで終っていると、 その値は、関数のリストではなく、1つの関数です。

lisp対話モードで自動詰め込み(auto-fill)モードをオンにするために モードフックを使った例を示します。

(add-hook 'lisp-interaction-mode-hook 'turn-on-auto-fill)

適当な時期に、Emacsは関数run-hooksを使って 特定のフックを実行します。 この関数は、add-hookで追加されたフック関数を呼び出します。

run-hooks &rest hookvar Function
この関数は複数個のフック変数名を引数にとり、各フックを順に実行する。 各引数hookvarは、フック変数のシンボルであること。 これらの引数は、指定された順に処理される。

フック変数がnil以外の値であると、 その値は、関数か関数のリストである。 値が関数(ラムダ式や関数定義を持つシンボル)であると、それを呼び出す。 値がリストであると、順番にその要素を呼び出す。 フック関数は、引数なしで呼び出される。 現在、フック変数に1つの関数を入れることは廃れかけている。 つねに関数のリストを使うべきである。

例として、emacs-lisp-modeがそのモードフックをどのように 実行するかを示す。

(run-hooks 'emacs-lisp-mode-hook)

run-hook-with-args hook &rest args Function
この関数は、フック関数に引数を渡すアブノーマルフックを実行する方法である。 各フック関数に引数argsを渡して呼び出す。

run-hook-with-args-until-failure hook &rest args Function
この関数は、フック関数に引数を渡すアブノーマルフックを実行するが、 フック関数が失敗するとただちに止める方法である。 フック関数がnilを返すまで、 各フック関数に引数argsを渡して呼び出す。 nilが返ってくるとnilで戻る。 さもなければ、nil以外の値を返す。

run-hook-with-args-until-success hook &rest args Function
この関数は、フック関数に引数を渡すアブノーマルフックを実行するが、 フック関数が成功するとただちに止める方法である。 フック関数がnil以外を返すまで、 各フック関数に引数argsを渡して呼び出す。 nil以外が返ってくると 最後に呼び出したフック関数の戻り値を返す。

add-hook hook function &optional append local Function
この関数はフック変数hookに関数functionを追加する 手軽な方法である。 引数functionは、正しい個数の引数をとる任意の正しいLisp関数であること。 たとえば、
(add-hook 'text-mode-hook 'my-text-hook-function)

は、text-mode-hookというフックに my-text-hook-functionを追加する。

add-hookは、ノーマルフックに加えてアブノーマルフックにも使える。

フック関数は実行順序に依存しないように設計するのが最良である。 実行順序に依存すると『トラブルを呼び込む』ようなものである。 しかし、順序は予測できる。 通常、functionはフックリストの先頭に置かれるので、 (ほかにadd-hookの呼び出しがなければ)最初に実行される。 省略可能な引数appendnil以外であると、 新たなフック関数はフックリストの末尾に置かれ、 最後に実行される。

localnil以外であると、 新たなフック関数をカレントバッファにバッファローカルにすることを意味する。 これを行うまえに、(make-local-variableではなくmake-local-hookを呼んで フック自身をバッファローカルにしておく必要がある。 フック自身がバッファローカルでないと、localの値は意味を持たない。 フック関数はつねにグローバルである。

remove-hook hook function &optional local Function
この関数は、フック変数hookからfunctionを取り除く。

localnil以外であると、 グローバルなフックリストではなくバッファローカルなフックリストから functionを削除することを指定する。 フック変数自身がバッファローカルでないと、localの値は意味を持たない。

make-local-hook hook Function
この関数は、フック変数hookをカレントバッファにバッファローカルにする。 フック変数がバッファローカルであると、 バッファローカルなフック関数とグローバルなフック関数を持つことができ、 run-hooksはそれらすべてを実行する。

この関数は、バッファローカルな値の要素をtにすることで動作する。 これは、バッファローカルな値に加えてフック変数のデフォルト値にある フック関数を使うことを表すフラグである。 run-hooksはこのフラグを理解し、 make-local-hookはすべてのノーマルフックを処理できる。 アブノーマルフックに関しては、 tの意味を理解するように更新したものだけが処理できる。

フック変数に対してmake-local-variableを直接使わないこと。 それだけでは不十分である。


Node:Documentation, Next:, Previous:Modes, Up:Top

説明文

GNU Emacs Lispには、便利なオンラインのヘルプ機能があります。 そのほとんどは、関数や変数に付随した説明文字列から取り出したものです。 本章では、説明文を参照するプログラムの書き方に加えて、 読者のLispプログラムに適切な説明文字列を書く方法を説明します。

Emacsの説明文字列は、Emacsマニュアルと同じものではないことに注意願います。 マニュアルには言語texinfoで書いた独自のソースファイルがありますが、 説明文字列は関数や変数の定義の中で指定されています。 説明文字列を集めても、よいマニュアルとは構成が違いますので、 マニュアルとしては十分ではありません。


Node:Documentation Basics, Next:, Up:Documentation

説明文の基本

説明文字列は、文字列に対するLisp構文、 つまり、文字列のテキストをダブルクォートで囲って書きます。 これは、説明文字列が実際にはLispの文字列オブジェクトだからです。 関数や変数の定義の正しい箇所に文字列を書くと、 説明文としての役割を果たします。 関数定義においては、説明文字列は引数のつぎにあります。 変数定義においては、変数の初期値のつぎにあります。

説明文字列を書くときには、 最初の1行は1つの(あるいは2つの)完全な文にしてください。 aproposなどのある種のコマンドは、 複数行にまたがる説明文字列の最初の1行だけを表示するからです。 また、説明文字列の2行目以降を字下げしないでください。 字下げがあると、 C-h fdescribe-function)や C-h vdescribe-variable)で説明文字列を表示すると 不恰好になります。 See Documentation Tips

説明文字列には、特別な部分文字列、つまり、 説明文を表示するときに現在のキーマップからキーバインディングを探す ことを表すものがあります。 これにより、ユーザーがキーバインディングを変更していても 説明文字列から関連するコマンドのキーを参照できます。 (see Accessing Documentation)。

Emacs Lispでは、説明文字列はその説明対象である関数や変数を介して参照します。

場所を節約するために、あらかじめロード済みの関数や変数 (基本関数や自動ロード対象の関数を含む)に対する説明文は、 Emacs本体にではなく、ファイルemacs/etc/DOC-versionに 収めてあります。 Emacsセッションの最中にバイトコンパイル済みのファイルから ロードされる関数や変数の説明文字列は、当該ファイルに収めてあります (see Docs and Compilation)。

Emacs内部のデータ構造では、説明文字列のかわりに、 ファイル内の位置を表す整数かファイル名と整数を含むリストで表します。 関数documentationdocumentation-propertyは、 この情報を用いて適切なファイルから説明文字列を取り出します。 この処理はユーザーには見えません。

説明文字列の利用に関する情報は、 Helpを参照してください。

ディレクトリemacs/lib-srcには、 ファイルemacs/etc/DOC-versionを美しく印刷するための コマンドが2つあります。 sorted-docdigest-docです。


Node:Accessing Documentation, Next:, Previous:Documentation Basics, Up:Documentation

説明文字列の参照

documentation-property symbol property &optional verbatim Function
この関数は、シンボルsymbolの属性リストに 属性propertyで記録されている説明文字列を返す。 必要ならばファイルからテキストを取り出し、 実際のキーバインディングに置き換えるために substitute-command-keysを実行する。 (verbatimnil以外であると、置換を行わない。)
(documentation-property 'command-line-processed
   'variable-documentation)
     => "Non-nil once command line has been processed"
(symbol-plist 'command-line-processed)
     => (variable-documentation 188902)

documentation function &optional verbatim Function
この関数は、関数functionの説明文字列を返す。 必要ならばファイルからテキストを取り出す。 続いて、(verbatimnilならば) 実際の(現在の)キーバインディングを含んだ値を返すために substitute-command-keysを実行する。

関数documentationは、functionに関数定義がないと エラーvoid-functionを通知する。 しかし、関数定義に説明文字列がなくてもエラーではない。 その場合、documentationnilを返す。

2つの関数documentationdocumentation-propertyを用いて、 数個のシンボルの説明文字列をバッファ*Help*に表示する例を示します。

(defun describe-symbols (pattern)
  "Describe the Emacs Lisp symbols matching PATTERN.
All symbols that have PATTERN in their name are described
in the `*Help*' buffer."
  (interactive "sDescribe symbols matching: ")
  (let ((describe-func
         (function
          (lambda (s)
            ;; Print description of symbol.
            (if (fboundp s)             ; これは関数
                (princ
                 (format "%s\t%s\n%s\n\n" s
                   (if (commandp s)
                       (let ((keys (where-is-internal s)))
                         (if keys
                             (concat
                              "Keys: "
                              (mapconcat 'key-description
                                         keys " "))
                           "Keys: none"))
                     "Function")
                   (or (documentation s)
                       "not documented"))))

            (if (boundp s)              ; これは変数
                (princ
                 (format "%s\t%s\n%s\n\n" s
                   (if (user-variable-p s)
                       "Option " "Variable")
                   (or (documentation-property
                         s 'variable-documentation)
                       "not documented")))))))
        sym-list)

    ;; パターンに一致するシンボルのリストを作る
    (mapatoms (function
               (lambda (sym)
                 (if (string-match pattern (symbol-name sym))
                     (setq sym-list (cons sym sym-list))))))

    ;; データを表示する
    (with-output-to-temp-buffer "*Help*"
      (mapcar describe-func (sort sym-list 'string<))
      (print-help-return-message))))

関数describe-symbolsaproposのように動作しますが、 より多くの情報を提供します。

(describe-symbols "goal")

---------- Buffer: *Help* ----------
goal-column     Option
*Semipermanent goal column for vertical motion, as set by ...

set-goal-column Keys: C-x C-n
Set the current horizontal position as a goal for C-n and C-p.
Those commands will move to this position in the line moved to
rather than trying to keep the same horizontal position.
With a non-nil argument, clears out the goal column
so that C-n and C-p resume vertical motion.
The goal column is stored in the variable `goal-column'.

temporary-goal-column   Variable
Current goal column for vertical motion.
It is the column where point was
at the start of current run of vertical motion commands.
When the `track-eol' feature is doing its job, the value is 9999.
---------- Buffer: *Help* ----------

Snarf-documentation filename Function
この関数は、実行可能なEmacsをダンプする直前の Emacsの初期化処理中にのみ使われる。 ファイルfilenameに格納された説明文字列のファイル内位置を探し出し、 それらの情報を実際の文字列のかわりに メモリ内の関数定義や変数の属性リストに記録する。 see Building Emacs

Emacsはファイルfilenameをディレクトリemacs/etcから読む。 ダンプしたEmacsをのちに実行すると、 同じファイルをディレクトリdoc-directoryで探す。 通常、filename"DOC-version"である。

doc-directory Variable
この変数は、組み込みであったりあらかじめロード済みの関数や変数の 説明文字列を収めたファイル"DOC-version"を置いた ディレクトリの名前を保持する。

ほとんどの場合、これはdata-directoryと同じである。 Emacsをインストールせずに構築したディレクトリから起動すると、 それらは異なることがある。 Help Functionsdata-directoryを参照。

Emacsの古い版では、この目的にはexec-directoryを用いていた。


Node:Keys in Documentation, Next:, Previous:Accessing Documentation, Up:Documentation

説明文内のキーバインディングの置換

説明文字列からキー列を参照するときには、 現在の活性なキーバインディングを使うべきです。 これは以下に述べる特別なテキスト列でできます。 普通の方法で説明文字列を参照すると、 これらの特別な列は現在のキーバインディング情報で置き換えられます。 置き換えはsubstitute-command-keysを呼び出して行います。 読者自身がこの関数を使うこともできます。

特別な列とその意味を以下にあげます。

\[command]
コマンドcommandを起動するキー列を表す。 commandにキーバインディングがなければ、 M-x commandを表す。
\{mapvar}
変数mapvarの値であるキーマップの概要を表す。 この概要はdescribe-bindingsを使って作成する。
\<mapvar>
空テキストを表す。 副作用のためだけに使う。 つまり、この説明文字列内のこれ以降にある列\[command]に 対するキーマップとしてmapvarの値を指定する。
\=
後続の文字をクォートし\=は破棄する。 したがって、\=\[\[という出力になり、 \=\=\=という出力になる。

注意: Emacs Lispでは、文字列内の\は、2つ続けて書くこと。

substitute-command-keys string Function
この関数は、stringから上記の特別な列を探し、 それらをそれらが意味するものに置き換え、結果を文字列で返す。 これにより、説明文の表示では、 ユーザー独自のカスタマイズしたキーバインディングを実際に参照できる。

特別な列の例を示します。

(substitute-command-keys
   "To abort recursive edit, type: \\[abort-recursive-edit]")
=> "To abort recursive edit, type: C-]"

(substitute-command-keys
   "The keys that are defined for the minibuffer here are:
  \\{minibuffer-local-must-match-map}")
=> "The keys that are defined for the minibuffer here are:

?               minibuffer-completion-help
SPC             minibuffer-complete-word
TAB             minibuffer-complete
C-j             minibuffer-complete-and-exit
RET             minibuffer-complete-and-exit
C-g             abort-recursive-edit
"

(substitute-command-keys
   "To abort a recursive edit from the minibuffer, type\
\\<minibuffer-local-must-match-map>\\[abort-recursive-edit].")
=> "To abort a recursive edit from the minibuffer, type C-g."


Node:Describing Characters, Next:, Previous:Keys in Documentation, Up:Documentation

ヘルプメッセージ用の文字変換

これらの関数は、イベント、キー列、文字をテキスト表記に変換します。 これらの表記は、メッセージに文字やキー列をテキストとして含めるのに有用です。 というのは、非印字文字や白文字を印字文字の列に変換するからです。 白文字でない印字文字は文字そのもので表記します。

key-description sequence Function
この関数は、sequenceの入力イベントに対する Emacsの標準表記を含んだ文字列を返す。 引数sequenceは、文字列、ベクトル、リストである。 正しいイベントについて詳しくはsee Input Events。 下記のsingle-key-descriptionの例を参照。

single-key-description event Function
この関数は、eventをキーボード入力向けのEmacsの標準表記で 表した文字列を返す。 普通の印字文字はそのまま現れるが、 コントロール文字はC-で始まる文字列に、 メタ文字はM-で始まる文字列に、 空白、タブなどは、SPCTABなどとなる。 ファンクションキーのシンボルはそれ自身が現れる。 リストであるイベントはリストのCARのシンボルの名前が現れる。
(single-key-description ?\C-x)
     => "C-x"
(key-description "\C-x \M-y \n \t \r \f123")
     => "C-x SPC M-y SPC C-j SPC TAB SPC RET SPC C-l 1 2 3"
(single-key-description 'C-mouse-1)
     => "C-mouse-1"

text-char-description character Function
この関数は、characterを テキストに現れる文字向けのEmacsの標準表記で表した文字列を返す。 single-key-descriptionに似ているが、 コントロール文字は、始めにカレットを付けて表現する点が異なる (Emacsのバッファでは、コントロールは普通このように表示される)。
(text-char-description ?\C-c)
     => "^C"
(text-char-description ?\M-m)
     => "M-m"
(text-char-description ?\C-\M-m)
     => "M-^M"

read-kbd-macro string Function
この関数は、キーボードマクロの処理に主に使われるが、 key-descriptionに対するおおまかな逆変換にも使える。 空白で区切ったキーの表記を収めた文字列で、この関数を呼び出す。 対応するイベントを収めた文字列かベクトルを返す。 (指定したイベントに依存して、正しい単一のキー列であったりなかったりする。 see Keymap Terminology。)


Node:Help Functions, Previous:Describing Characters, Up:Documentation

ヘルプ機能

Emacsにはさまざまオンラインヘルプ関数があり、 それらはすべてプレフィックスC-hのサブコマンドとして使えます。 それらについて詳しくは、 Helpを参照してください。 ここでは、同じ情報を得るプログラムレベルのインターフェイスを説明します。

apropos regexp &optional do-all コマンド
この関数は、正規表現regexpに一致する名前を持つすべてのシンボルを探し、 それらのリストを返す(see Regular Expressions)。 さらに、バッファ*Help*に、各シンボルについて、 シンボルとその説明文字列の始めの部分から取り出した1行の説明文を表示する。

do-allnil以外であると、 aproposは、みつけた関数に対するキーバインディングも表示する。 さらに、関数や変数以外も含めてすべてのシンボルを表示する。

つぎの例では、aproposは、 execを名前に含むすべてのシンボルを探しだす。 (ここではバッファ*Help*の表示は示さない。)

(apropos "exec")
     => (Buffer-menu-execute command-execute exec-directory
    exec-path execute-extended-command execute-kbd-macro
    executing-kbd-macro executing-macro)

help-map Variable
この変数の値は、ヘルプキーC-hに続く文字向けのローカルキーマップである。

help-command プレフィックスコマンド
このシンボルは関数ではない。 その関数定義セルは、help-mapとして知られるキーマップを保持している。 help.elでの定義はつぎのとおりである。
(define-key global-map "\C-h" 'help-command)
(fset 'help-command help-map)

print-help-return-message &optional function Function
この関数は、ヘルプコマンドのあとでそれ以前のウィンドウの状態に復元する 方法を述べた文字列を作成する。 メッセージを作成後、functionnil以外であれば、 メッセージをfunctionに適用する。 さもなければ、メッセージをエコー領域に表示するためにmessageを呼び出す。

この関数は、スペシャルフォームwith-output-to-temp-bufferの 中から呼び出され、しかも、 当該スペシャルフォームでstandard-outputに値が束縛されているものと 仮定する。 使用例については、Accessing Documentationの長い例を参照。

help-char Variable
この変数の値はヘルプ文字、つまり、 Emacsがヘルプを意味すると認識する文字である。 デフォルトでは、その値はC-hを表す8である。 help-formnil以外のLisp式であると、 Emacsがこの文字を読み取るとその式を評価し、 その結果が文字列であれば結果をウィンドウに表示する。

通常、help-formの値はnilである。 そうすると、ヘルプ文字にはコマンド入力のレベルでは特別な意味はなく、 普通の意味でのキー列の一部になる。 C-hの標準のキーバインディングは、 いくつかの汎用目的のヘルプ機能向けのプレフィックスキーである。

ヘルプ文字は、プレフィックスキーのうしろでも特別である。 プレフィックスのサブコマンドとしてのバインディングがないと、 プレフィックスキーのすべてのサブコマンドの一覧を表示する describe-prefix-bindingsを実行する。

help-event-list Variable
この変数の値は、別の『ヘルプ文字』として動作するイベント型のリストである。 これらのイベントはhelp-charで指定されたイベントと まったく同様に扱われる。

help-form Variable
この変数がnil以外であると、その値は、 help-charを読むたびに評価すべきフォームである。 フォームを評価すると文字列を生成すれば、その文字列が表示される。

read-eventread-charを呼ぶコマンドは、 入力中にはhelp-formnil以外に(たぶん)束縛すべきである。 (C-hに別の意味がある場合には、こうしないこと。) この式の評価結果は、なんのための入力でどのように入力すべきかを 説明する文字列であること。

ミニバッファに入ると、この変数はminibuffer-help-form (see Minibuffer Misc)の値に束縛される。

prefix-help-command Variable
この変数はプレフィックスキーに対するヘルプを表示する関数を保持する。 ユーザーがプレフィックスキーに続けてヘルプ文字や 当該プレフィックスのあとではバインディングを持たない文字を打つと その関数が呼ばれる。 この変数のデフォルト値はdescribe-prefix-bindingsである。

describe-prefix-bindings Function
この関数は、もっとも最近のキー列のプレフィックスキーの すべてのサブコマンドの一覧を表示するためにdescribe-bindingsを呼び出す。 プレフィックスの説明には、当該キー列の最後のイベント以外のすべてが含まれる。 (最後のイベントはヘルプ文字であると仮定する。)

つぎの2つの関数は、『エレクトリック』モードのように 制御を放棄せずにヘルプを提供したいモードのためです。 それらの名前は、普通のヘルプ関数と区別するためにHelperで始まります。

Helper-describe-bindings コマンド
このコマンドは、ローカルキーマップとグローバルキーマップの両者の すべてのキーバインディングの一覧を収めたヘルプバッファを表示した ウィンドウをポップアップする。 describe-bindingsを呼び出すことで動作する。

Helper-help コマンド
このコマンドはカレントモードについてのヘルプを提供する。 ミニバッファにおいてHelp (Type ? for further options)のメッセージで ユーザーに問い合わせ、キーバインディングの意味やモードの目的を 調べることを補佐する。 nilを返す。

このコマンドは、キーマップHelper-help-mapを 変更することでカスタマイズできる。

data-directory Variable
この変数は、Emacsとともに配布された特定の説明文やテキストファイルを Emacsが探すためのディレクトリの名前を保持する。 Emacsの古い版では、この目的にはexec-directoryを用いていた。

make-help-screen fname help-line help-text help-map Macro
このマクロは、サブコマンドの一覧を表示するプレフィックスキーのように 動作するfnameという名前のコマンドのヘルプを定義する。

起動されると、fnameはウィンドウにhelp-textを表示し、 help-mapに従ってキー列を読み実行する。 文字列help-textは、help-mapが提供する バインディングを記述するべきである。

コマンドfnameは、help-textの表示をスクロールすることで、 それ自身では少数のイベントを扱うように定義される。 fnameがそれらの特殊イベントの1つを読み取ると、 スクロールしてつぎのイベントを読み取る。 読み取ったイベントが、扱えるものでなく、 help-mapにバインディングがあれば、 当該キーのバインディングを実行して戻る。

help-lineは、help-map内の選択項目を1行にまとめたものであること。 Emacsの現在の版では、この引数はオプションthree-step-helptに 設定してある場合にのみ使われる。

このマクロは、C-h C-hのバインディングである コマンドhelp-for-helpで使われている。

three-step-help User Option
この変数がnil以外であると、 make-help-screenで定義されたコマンドは、 まず文字列help-lineをエコー領域に表示し、 ユーザーがヘルプ文字を再度打った場合にのみより長い文字列を表示する。


Node:Files, Next:, Previous:Documentation, Up:Top

ファイル

Emacsでは、ファイルやディレクトリを 探したり、作成したり、眺めたり、保存したり、その他のことをできます。 本章では、Emacs Lispのファイル関連の関数のほとんどについて説明しますが、 他の一部はBuffersで、バックアップや自動保存に関することは Backups and Auto-Savingで説明します。

ファイル関数の多くは、ファイル名の引数を1つないし複数個取ります。 ファイル名は実際には文字列です。 これらのほとんどの関数では、expand-file-nameを呼び出して ファイル名引数を展開することで~や (../を含む)相対ファイル名を正しく処理します。 これらの関数は、$HOMEなどの環境変数置換は認識しません。 See File Name Expansion


Node:Visiting Files, Next:, Up:Files

ファイルの訪問

ファイルを訪問するとは、ファイルをバッファに読み込むことです。 いったんこうすると、バッファはそのファイルを 訪問している(visiting)といい、 そのファイルをバッファの『訪問しているファイル』と呼びます。

ファイルとバッファは2つの異なるものです。 ファイルは、コンピュータ内に(読者が削除しない限り)恒久的に 記録されている情報です。 一方、バッファはEmacs内部にある情報であり、 編集セッションを終了する(あるいはバッファを削除する)と消えてしまいます。 通常、バッファにはファイルからコピーした情報があります。 つまり、バッファはそのファイルを訪問しているのです。 読者は、バッファ内のコピーを編集コマンドで修正するのです。 バッファに対するそのような変更では、ファイルは変更しません。 したがって、変更を恒久的なものにするには、 読者はバッファを保存(save)する、つまり、 バッファの変更した内容をファイルにコピーし戻す必要があります。

ファイルとバッファの区別にも関わらず、 バッファを意味してファイルといったり、その逆のいい方をしばしばします。 もちろん、『同じ名前のファイルにただちに保存するつもりでバッファを 編集している』とはいわずに『ファイルを編集している』といいます。 しばしば、人間は明確に区別する必要はありません。 しかし、コンピュータプログラムを扱ううえでは、 区別を心得ておくことがよいのです。


Node:Visiting Functions, Next:, Up:Visiting Files

ファイルを訪問する関数

本節では、ファイルを訪問するために通常使う関数について述べます。 歴史的な理由で、これらの関数はvisit-でなくfind-という 名前で始まります。 バッファで訪問したファイルの名前を参照するための関数や変数、ならびに、 訪問したファイルの名前で既存バッファを探すための関数や変数については、 See Buffer File Name

Lispプログラムにおいて、ファイルの内容を変更せずにその内容を調べたいときには、 もっとも速い方法は一時的なバッファでinsert-file-contentsを 使うことです。 ファイルを訪問する必要はありませんし、それには余計に時間がかかります。 See Reading from Files

find-file filename コマンド
このコマンドはファイルfilenameを訪問したバッファを選択する。 そのようなバッファが既存ならば当該バッファを使う。 さもなければ、新たなバッファを作成してファイルを読み込む。 当該バッファを返す。

関数find-fileの本体は非常に簡単で、つぎのとおりである。

(switch-to-buffer (find-file-noselect filename))

Displaying Buffersswitch-to-bufferを参照。)

find-fileが対話的に呼び出されると、 ミニバッファでfilenameを問い合わせる。

find-file-noselect filename &optional nowarn rawfile Function
この関数は、ファイルを訪問するすべての関数の基である。 ファイルfilenameを訪問した/するバッファを探し/作成し、 当該バッファを返す。 そのようなバッファが既存ならば当該バッファを使う。 さもなければ、新たなバッファを作成してファイルを読み込む。 必要に応じて、バッファをカレントバッファにしたり ウィンドウに表示できるが、この関数はそこまでは行わない。

find-file-noselectが既存バッファを使うときには、 ファイルの内容が当該バッファに最後に訪問してから、あるいは、 当該バッファを最後に保存してから変更されたかどうかまず確認する。 ファイルが変更されていれば、この関数は変更されたファイルを 再度読み込むかどうかユーザーに問い合わせる。 ユーザーがyesと答えると、バッファ内の変更は破棄される。

省略可能な引数nowarnnilであると、 この関数はさまざまな場面で警告/助言メッセージを表示する。 たとえば、バッファを作成する必要があり、かつ、 指定したファイルfilenameがない場合には、 エコー領域にメッセージNew fileを表示し、バッファは空にしておく。

関数find-file-noselectは、 ファイルを読み込み終えると通常after-find-fileを呼び出す (see Subroutines of Visiting)。 その関数は、バッファのメジャーモードを設定し、ローカル変数を解析し、 訪問したファイルより新しい自動保存ファイルが存在するとユーザーに警告を発し、 find-file-hooksの関数を実行して処理を終える。

省略可能な引数rawfilenil以外であると、 after-find-fileを呼び出さず、 失敗してもfind-file-not-found-hooksを実行しない。 さらに、rawfileの値がnil以外であると、 コーディングシステムの変換(see Coding Systems)や 書式変換(see Format Conversion)も行わない。

関数find-file-noselectは、 ファイルfilenameを訪問したバッファを返す。

(find-file-noselect "/etc/fstab")
     => #<buffer fstab>

find-file-other-window filename コマンド
このコマンドは、選択しているウィンドウ以外のウィンドウにおいて、 ファイルfilenameを訪問したバッファを選択する。 別の既存ウィンドウを使うか、ウィンドウを分割する。 Displaying Buffersを参照。

このコマンドが対話的に呼び出されると、 filenameを問い合わせる。

find-file-read-only filename コマンド
このコマンドは、find-fileのようにファイルfilenameを訪問した バッファを選択するが、当該バッファは読み出し専用となる。 See Read Only Buffers

このコマンドが対話的に呼び出されると、 filenameを問い合わせる。

view-file filename コマンド
このコマンドは、閲覧(view)モードでfilenameを訪問し、 閲覧(view)モードを抜けるとそれ以前のバッファに戻る。 閲覧(view)モードは、ファイルを素早く眺めるためのコマンドを与えるが テキストの変更は許さないマイナモードである。 閲覧(view)モードに入ると、ノーマルフックview-mode-hookを実行する。 see Hooks

view-fileが対話的に呼び出されると、 filenameを問い合わせる。

find-file-hooks Variable
この変数の値は、ファイルを訪問後に呼び出される関数のリストである。 ファイルにローカル変数指定(があれば)は、 フックを実行するまえに処理される。 フック関数が実行されときには、 ファイルを訪問したバッファはカレントバッファになっている。

この変数はノーマルフックのように動作するが、 改名すべきではないと考えている。 see Hooks

find-file-not-found-hooks Variable
この変数の値は、find-filefind-file-noselectに 存在しないファイルを与えたときに呼び出される関数のリストである。 find-file-noselectは、ファイルが存在しないことがわかると ただちにこれらの関数を呼び出す。 nil以外の値が返されるまで、リストに現れる順に呼び出す。 buffer-file-nameは設定済みである。

関数の値を使い、しかも、一部の関数だけを呼び出すので、 これはノーマルフックではない。


Node:Subroutines of Visiting, Previous:Visiting Functions, Up:Visiting Files

訪問するためのサブルーティン

関数find-file-noselectは、ユーザーのLispコードでも有用な 2つの重要なサブルーティン、create-file-bufferafter-find-fileを使います。 本節ではそれらの使い方を説明します。

create-file-buffer filename Function
この関数は、filenameを訪問するのに適するように命名した バッファを作成しそれを返す。 (ディレクトリを除外した)filenameが使用中の名前でなければ、 それを名前とする。 さもなければ、未使用の名前を得るために<2>などの文字列を付加する。 Creating Buffersも参照。

注意: create-file-bufferは、 新たなバッファをファイルに対応付けないし、 当該バッファを選択しない。 デフォルトのメジャーモードも使わない。

(create-file-buffer "foo")
     => #<buffer foo>
(create-file-buffer "foo")
     => #<buffer foo<2>>
(create-file-buffer "foo")
     => #<buffer foo<3>>

この関数はfind-file-noselectで使われる。 この関数はgenerate-new-buffer(see Creating Buffers)を使う。

after-find-file &optional error warn Function
この関数は、バッファのメジャーモードを設定し、 ローカル変数を解析する(see Auto Major Mode)。 find-file-noselectや デフォルトの復元処理関数(see Reverting)から呼ばれる。

ディレクトリはあるのにファイルが存在しないために ファイルの読み込みがエラーになった場合には、 呼び出し側はerrorの値としてnil以外を渡すこと。 その場合、after-find-fileは警告(New File)を表示する。 より重大なエラーの場合には、after-find-fileを呼び出すべきでない。

warnnil以外であると、 自動保存ファイルが存在しそれが訪問したファイルより新しい場合には、 この関数は警告を発する。

after-find-fileが最後に行うことは、 リストfind-file-hooks内のすべての関数を呼び出すことである。


Node:Saving Buffers, Next:, Previous:Visiting Files, Up:Files

バッファの保存

Emacsでファイルを編集するときには、 ファイルを訪問したバッファを実際には扱っています。 つまり、ファイルの内容はバッファにコピーされ、 そのコピーを編集しているのです。 バッファを変更しても、当該バッファを保存(save)するまで、 つまり、バッファの内容をファイルへコピーするまでは、 ファイルを変更しません。

save-buffer &optional backup-option コマンド
この関数は、最後に訪問/保存してからカレントバッファが変更されていれば、 カレントバッファの内容を訪問しているファイルへ保存する。

save-bufferは、バックアップの作成に責任がある。 通常、backup-optionnilであり、 save-bufferは、ファイルを訪問してから 最初に保存するときにのみバックアップファイルを作成する。 backup-optionが別の値であると、 別の場面でもバックアップファイルを作成することを指示する。

  • 引数が1つか3つのC-uを反映した4か64であると、 関数save-bufferは、バッファをつぎに保存したときに ファイルの現在の版をバックアップするように印を付ける。
  • 引数が2つか3つのC-uを反映した16か64であると、 save-bufferは、保存するまえに無条件に ファイルのまえの版をバックアップする。

save-some-buffers &optional save-silently-p exiting コマンド
このコマンドは、ファイルを訪問している変更されたバッファを保存する。 通常、各バッファについてユーザーに問い合わせる。 しかし、save-silently-pnil以外であると、 ユーザーに問い合わせずにファイルを訪問しているバッファをすべて保存する。

省略可能な引数exitingnil以外であると、 この関数は、ファイルを訪問していないある種のバッファを保存する機会も与える。 buffer-offer-saveのバッファローカルな値が nil以外のバッファが対象となる。 (ユーザーがこれらのバッファの1つを保存するように答えると、 ファイル名を指定するように聞いてくる。) 関数save-buffers-kill-emacsは、 この引数にnil以外の値を渡す。

write-file filename コマンド
この関数は、カレントバッファをファイルfilenameに保存し、 当該ファイルを訪問しているバッファとし、さらに未変更という印を付ける。 続いて、バッファ名を一意にするために必要ならば<2>のような 文字列を付加して、バッファをfilenameに基づいた名前に改名する。 この処理のほとんどは、set-visited-file-name(see Buffer File Name) とsave-bufferを呼び出して行う。

バッファを保存すると、いくつかのフックを実行します。 また、書式変換(see Format Conversion)を行い、 テキスト属性を『注記』(annotations)(see Saving Properties)に 保存することもあります。

write-file-hooks Variable
この変数の値は、バッファを訪問しているファイルに書き出すまえに 呼ばれる関数のリストである。 それらの1つがnil以外を返すと、すでにファイルに書き出したとみなして 残りの関数を呼び出さず、ファイルに書き出すための通常のコードも実行しない。

write-file-hooksの関数がnil以外を返すときには、 その関数には(必要ならば)バックアップファイルを作成する責任がある。 そのためにはつぎのコードを実行する。

(or buffer-backed-up (backup-buffer))

backup-bufferが返したファイルモードの値を保存しておき、 読者が書くファイルのモードにその値を使いたい場合がある。 save-bufferは通常そのようにする。

write-file-hooksのフック関数は、 (必要ならば)データの符号化にも責任がある。 適切なコーディングシステム(see Lisp and Coding Systems)を選び、 符号化(see Explicit Encoding)を行い、 使用したコーディングシステムをlast-coding-system-usedに設定する (see Encoding and I/O)。

この変数をバッファローカルにはしないこと。 バッファ固有のフック関数を指定するには、 かわりにwrite-contents-hooksを使う。

これはノーマルフックではないが、 add-hookremove-hookでリストを扱える。 see Hooks

local-write-file-hooks Variable
これはwrite-file-hooksのように働くが、 特定のバッファにバッファローカルにするように意図してあり、 ファイル名に関するフックやバッファ内容を得た方法に関する フックとして使われる。

変数は恒久的にバッファローカルと印が付いているので、 メジャーモードを変更してもバッファローカルな値は変更されない。 これは、『ファイル』の内容を特別な方法で読み込み、 対応した方法でデータを保存するフックを設定するようなパッケージには便利である。

write-contents-hooks Variable
この変数はwrite-file-hooksのように働くが、 ファイルの場所に関するフックではなく、 ファイルの内容に関するフックであると意図されている。 そのようなフックは、この変数のバッファローカルな束縛として メジャーモードが通常設定する。

この変数に設定すると自動的にバッファローカルになる。 このフックに要素を追加するためにadd-hooksを使うときには、 引数localnil以外を指定しないこと。 この変数はバッファローカルのみであるからである。

after-save-hook Variable
このノーマルフックは、バッファを訪問したファイルに 保存し終えてから実行される。 このフックの用途の1つは高速ロック(fast-lock)モードである。 このフックを使って強調表示情報をキャッシュファイルに保存する。

file-precious-flag Variable
この変数がnil以外ならば、 save-bufferは保存処理中の入出力エラーに備えて対処する。 つまり、目的の名前のファイルにではなく一時的な名前の新規ファイルに書き出し、 エラーがないことを確認してから目的の名前に改名する。 これにより、不正なファイルに起因する問題からディスク容量の不足といった 問題を回避できる。

副作用として、バックアップも必然的にコピーして行う。 see Rename or Copy。 それと同時に、大事な(precious)ファイルとして保存すると、 読者が保存したファイルと別のファイル名とのあいだの ハードリンクをつねに切ってしまう。

特定のバッファではこの変数にnil以外のバッファローカルな値を 指定するモードもある。

require-final-newline User Option
この変数は、改行で終らないファイルを書き出すかどうかを決定する。 この変数の値がtであると、save-bufferは、 保存するバッファが改行で終っていないと黙ってファイルの末尾に改行を追加する。 この変数の値がtではないnil以外であると、 save-bufferは、必要な場面では 改行を追加するかどうかユーザーに問い合わせる。

この変数の値がnilであると、save-bufferは改行を追加しない。 デフォルト値はnilであるが、特定のバッファではtに 設定するメジャーモードもある。

関数set-visited-file-name(see Buffer File Name)も 参照してください。


Node:Reading from Files, Next:, Previous:Saving Buffers, Up:Files

ファイルの読み込み

関数insert-file-contentsを使って ディスクからファイルをバッファへコピーできます。 ユーザーレベルのコマンドinsert-fileはマークを設定するので Lispプログラムでは使わないでください。

insert-file-contents filename &optional visit beg end replace Function
この関数は、ファイルfilenameの内容をカレントバッファの ポイントのうしろに挿入する。 絶対ファイル名と挿入したデータの長さから成るリストを返す。 filenameが読み込めるファイルの名前でないと、エラーを通知する。

関数insert-file-contentsは、 ファイルの内容を定義済みのファイルの書式と比較し、 必要ならばファイルの内容を変換する。 see Format Conversion。 リストafter-insert-file-functionsの関数も呼び出す。 Saving Propertiesを参照。

visitnil以外であると、 この関数はバッファを未変更と印を付け、 ファイルfilenameを訪問しているバッファとなるように バッファのさまざまな部分を設定する。 これには、バッファが訪問しているファイルの名前、ファイル更新時刻を含む。 この機能はfind-file-noselectで使われており、 読者自身が使うことはないであろう。

begendnil以外であると、 それらは挿入すべきファイルの部分を指定する整数であること。 この場合、visitnilであること。 たとえば、

(insert-file-contents filename nil 0 500)

はファイルの最初の500文字を挿入する。

引数replacenil以外であると、 バッファの内容(実際には参照可能な部分のみ)を ファイルの内容で置き換えることを意味する。 これは、単純にバッファの内容を削除してからファイル全体を挿入するより 好ましい。 なぜなら、(1)マーカ位置を保存できる場合がある、 (2)アンドゥリストにほとんどデータを入れない、からである。

replacevisitnilである限り、 insert-file-contentsで(FIFOや入出力装置などの) 特別なファイルを読むことも可能である。

insert-file-contents-literally filename &optional visit beg end replace Function
この関数はinsert-file-contentsのように動作するが、 書式を変換しない(see Format Conversion)、 文字コードを変換しない(see Coding Systems)、 find-file-hooksを実行しない、自動的に解凍しないなどが異なる。

別のプログラムが読めるようにファイル名を別のプロセスに渡すには、 関数file-local-copyを使います。 Magic File Namesを参照してください。


Node:Writing to Files, Next:, Previous:Reading from Files, Up:Files

ファイルへの書き出し

関数append-to-filewrite-regionを使って、 バッファの内容やその一部をディスク上のファイルへ直接書き出せます。 訪問しているファイルには、これらの関数で書き出さないでください。 訪問の機構に混乱をきたすことがあります。

append-to-file start end filename コマンド
この関数は、カレントバッファのstartからendで 区切られる領域の内容をファイルfilenameの末尾に追加する。 当該ファイルが存在しなければ作成する。 この関数はnilを返す。

書き込めないファイルをfilenameに指定したり、 ファイルを作成できないディレクトリ上の存在しないファイルを filenameに指定するとエラーを通知する。

write-region start end filename &optional append visit confirm コマンド
この関数は、カレントバッファのstartからendで 区切られる領域の内容をfilenameで指定したファイルに書き出す。

startが文字列であると、 write-regionはバッファのテキストではなく その文字列を書いたり追加する。

appendnil以外であると、 指定したテキストを既存ファイル(があれば)の内容に追加する。

confirmnil以外であると、 filenameが既存ファイルの名前であると write-regionは確認を求める。

visittであると、 Emacsはバッファとファイルの対応を確立する。 つまり、バッファはそのファイルを訪問していることになる。 さらに、カレントバッファの最終ファイル更新時刻を filenameの更新時刻にし、 バッファには未変更と印を付ける。 この機能はsave-bufferが使っているが、 読者自身が使うことはないであろう。

visitが文字列であると、訪問するファイルの名前を指定する。 このようにして、データを1つのファイル(filename)に書き出す一方で、 バッファは別のファイル(visit)を訪問していると設定できる。 引数visitはエコー領域のメッセージに使われ、 ファイルのロックにも使われる。 visitbuffer-file-nameに保存される。 この機能はfile-precious-flagの実装に使われているが、 読者は、なにをしているか理解できない限り、この機能を使わないこと。

関数write-regionは、書き出すデータを buffer-file-formatで指定される適切なファイル書式に変換する。 see Format Conversion。 さらに、リストwrite-region-annotate-functionsの関数も呼び出す。 Saving Propertiesを参照。

通常、write-regionはエコー領域にメッセージ Wrote filenameを表示する。 visittでもnilでも文字列でもないと、 このメッセージは表示しない。 この機能は、ユーザーが知る必要のない 内部目的にファイルを使うプログラムに有用である。

with-temp-file file body... Macro
マクロwith-temp-fileは、一時的なバッファをカレントバッファとして フォームbodyを評価する。 そして最後にバッファの内容をファイルfileに書き出す。 終了すると一時的なバッファを削除し、 フォームwith-temp-fileのまえにカレントバッファであったバッファに戻る。 bodyの最後のフォームの値を返す。

throwやエラーによる異常終了(see Nonlocal Exits)であっても カレントバッファに戻る。 Current Bufferwith-temp-bufferも参照。


Node:File Locks, Next:, Previous:Writing to Files, Up:Files

ファイルロック

2人のユーザーが同時に同じファイルを編集すると、互いに干渉し合います。 Emacsは、ファイルが変更されるとファイルロック(file lock)を 記録することで、このような状況が発生しないように努めます。 すると、Emacsは別のEmacsがロックしているファイルを訪問した バッファを変更しようとする最初の試みを検出でき、 ユーザーにどうすべきかを問い合わせます。

複数の計算機がファイルシステムを共有している場合には、 ファイルロックには完全な信頼性はありません。 ファイルロックが働かないと、 2人のユーザーが同時に変更する可能性がありますが、 それでも、Emacsは2番目に保存したユーザーに警告できます。 また、ディスク上で変更されたファイルを訪問しているバッファの変更を 検出することで、同時編集のある場面を捕捉できます。 Modification Timeを参照してください。

file-locked-p filename Function
ファイルfilenameがロックされていなければ、この関数はnilを返す。 このEmacsプロセスがロックしているときにはtを返す。 他のEmacsがロックしている場合には、ロックしているユーザーの名前を返す。
(file-locked-p "foo")
     => nil

lock-buffer &optional filename Function
この関数は、カレントバッファが変更されていれば ファイルfilenameをロックする。 引数filenameのデフォルトは、 カレントバッファで訪問しているファイルである。 カレントバッファがファイルを訪問していなかったり、 未変更ならばなにもしない。

unlock-buffer Function
この関数は、バッファが変更されていれば、 カレントバッファで訪問しているファイルのロックを解除する。 バッファが未変更ならばファイルをロックしていないはずであり、 この関数はなにもしない。 カレントバッファがファイルを訪問していなければ、 やはりなにもしない。

ask-user-about-lock file other-user Function
この関数は、別のユーザーother-userがロックしている ファイルfileをユーザーが変更しようとしたときに呼び出される。 この関数のデフォルトの定義は、ユーザーになにをすべきか 問い合わせることである。 この関数の戻り値がEmacsのつぎの動作を決定する。
  • 値がtであると、ファイルのロックを取得することを意味する。 すると、このユーザーはファイルを編集でき、 別のユーザーother-userはロックを失う。
  • 値がnilであると、ロックを無視して とにかくユーザーにファイルの編集を許す。
  • この関数はエラーfile-lockedを通知する。 この場合、ユーザーが行おうとしていた変更は行われない。

    このエラーのエラーメッセージはつぎのようである。

    error--> File is locked: file other-user
    

    ここで、fileはファイル名であり、 other-userはそのファイルをロックしているユーザー名である。

読者は、関数ask-user-about-lockを 別の方法で決定する読者独自のものに置き換えてもよい。 通常の定義に対応したコードはuserlock.elにある。


Node:Information about Files, Next:, Previous:File Locks, Up:Files

ファイルに関する情報

本節に述べる関数はすべて、ファイル名を表す文字列に作用します。 すべての関数の名前は単語fileで始まり、 それらの引数は、特に断らないかぎり、 既存のファイルやディレクトリである必要があります。


Node:Testing Accessibility, Next:, Up:Information about Files

参照可能性の検査

これらの関数は、特別な方法でファイル参照のパーミッションを検査します。

file-exists-p filename Function
ファイルfilenameが存在すれば、この関数はtを返す。 これは必ずしもファイルを読めることは意味せず、 単にファイルの属性を調べられるだけである。 (UNIXでは、ファイルが存在し、かつ、 それを収めたディレクトリに対する実行パーミッションがあれば、 ファイル自体のパーミッションに関係なくこのようになる。)

ファイルが存在しなかったり、ファイルの属性を探す権限がなければ、 この関数はnilを返す。

file-readable-p filename Function
ファイルfilenameが存在しそれを読むことができるならば、 この関数はtを返す。 さもなければnilを返す。
(file-readable-p "files.texi")
     => t
(file-exists-p "/usr/spool/mqueue")
     => t
(file-readable-p "/usr/spool/mqueue")
     => nil

file-executable-p filename Function
ファイルfilenameが存在しそれを実行できるならば、 この関数はtを返す。 さもなければnilを返す。 ファイルがディレクトリである場合、実行パーミッションは、 ディレクトリ内のファイルの存在やその属性を検査でき、 それらのファイルのモードが許せばオープンできることを意味する。

file-writable-p filename Function
ファイルfilenameに書き出したり作成できるならば、 この関数はtを返し、さもなければnilを返す。 ファイルに書き出せるのは、ファイルが存在し書ける場合である。 作成できるのは、ファイルは存在しないが 指定したディレクトリが存在しそのディレクトリに書ける場合である。

以下の3番目の例では、fooの親ディレクトリが存在しないので、 たとえディレクトリを作成できるとしてもfooは書けない。

(file-writable-p "~/foo")
     => t
(file-writable-p "/foo")
     => nil
(file-writable-p "~/no-such-dir/foo")
     => nil

file-accessible-directory-p dirname Function
ディレクトリdirnameの既存ファイルをオープンするパーミッションがあれば、 この関数はtを返す。 さもなければ(あるいは当該ディレクトリが存在しなければ)nilを返す。 dirnameの値はディレクトリ名である。

例: つぎの例では、

(file-accessible-directory-p "/foo")
     => nil

から、/foo/内のファイルを読もうとすると エラーになると推論できる。

access-file filename string Function
この関数は、ファイルfilenameを読むためにオープンし、 クローズしてからnilを返す。 しかし、オープンに失敗するとstringをエラーメッセージのテキストとした エラーを通知する。

file-ownership-preserved-p filename Function
もしファイルfilenameを削除して改めて作成しても ファイルの所有者が変更されなければ、この関数はtを返す。

file-newer-than-file-p filename1 filename2 Function
ファイルfilename1filename2より新しければ、 この関数はtを返す。 filename1が存在しなければnilを返す。 filename2が存在しなければtを返す。

以下の例で、ファイルaug-19は19日に書かれ、 ファイルaug-20は20日に書かれ、 ファイルno-fileは存在しないと仮定する。

(file-newer-than-file-p "aug-19" "aug-20")
     => nil
(file-newer-than-file-p "aug-20" "aug-19")
     => t
(file-newer-than-file-p "aug-19" "no-file")
     => t
(file-newer-than-file-p "no-file" "aug-19")
     => nil

file-attributesを使って、 2つの数から成るリストとしてファイルの最終更新時刻を取得できる。 see File Attributes


Node:Kinds of Files, Next:, Previous:Testing Accessibility, Up:Information about Files

ファイルの種類の区別

本節ではさまざまな種類のファイル、つまり、 ディレクトリ、シンボリックリンク、普通のファイルを区別する方法を 説明します。

file-symlink-p filename Function
ファイルfilenameがシンボリックリンクであると、 関数file-symlink-pは当該リンクが指すファイルの名前を返す。 これは、テキストファイル、ディレクトリ、別のシンボリックリンク、 存在しないファイルの名前のいずれかである。

ファイルfilenameがシンボリックリンクでない (あるいは当該ファイルが存在しない)場合、 file-symlink-pnilを返す。

(file-symlink-p "foo")
     => nil
(file-symlink-p "sym-link")
     => "foo"
(file-symlink-p "sym-link2")
     => "sym-link"
(file-symlink-p "/bin")
     => "/pub/bin"

file-directory-p filename Function
ファイルfilenameが既存ディレクトリの名前であるとtを返し、 さもなければnilを返す。
(file-directory-p "~rms")
     => t
(file-directory-p "~rms/lewis/files.texi")
     => nil
(file-directory-p "~rms/lewis/no-such-file")
     => nil
(file-directory-p "$HOME")
     => nil
(file-directory-p
 (substitute-in-file-name "$HOME"))
     => t

file-regular-p filename Function
ファイルfilenameが存在しそれが普通のファイル (ディレクトリでもシンボリックリンクでも名前付きパイプでも 端末でもその他の入出力装置でもない)であれば、 この関数はtを返す。


Node:Truenames, Next:, Previous:Kinds of Files, Up:Information about Files

実名

ファイルの実名(truename)とは、 シンボリックリンクをすべて辿り尽くしてから、 要素として現れる... を簡略化して得られる名前です。 厳密にいえば、ファイルが一意の実名を持つ必要はありません。 ファイルの異なる実名の個数は、当該ファイルに対するハードリンクの個数に 等しいのです。 それでも、実名はシンボリックリンクによる名前の変動を取り除くため、 実名は有用です。

file-truename filename Function
関数file-truenameはファイルfilenameの実名を返す。 これはシンボリックリンクをすべて辿り尽くして得られる名前である。 引数は絶対ファイル名であること。

関連情報については、See Buffer File Name


Node:File Attributes, Previous:Truenames, Up:Information about Files

ファイルに関する他の情報

本節では、ファイルの内容以外の詳しい情報を得るための関数を説明します。 この情報には、参照パーミッションを制御するモードビット、 所有者とグループの番号、名前の個数、iノード番号、サイズ、 参照時刻と更新時刻が含まれます。

file-modes filename Function
この関数はfilenameのモードビットを整数で返す。 モードビットはファイルのパーミッションとも呼ばれ、 UNIX流の参照制御を指定する。 最下位ビットが1であると、当該ファイルはすべてのユーザーが実行でき、 2番目の下位ビットが1であると、当該ファイルはすべてのユーザーが書ける といった具合である。

戻り値の最大値は4095(8進数7777)であり、これは、 だれもが読み/書き/実行でき、 所有者とグループの両者にビットSUIDが設定してあり、 スティッキービットも設定されていることを意味する。

(file-modes "~/junk/diffs")
     => 492               ; 10進整数
(format "%o" 492)
     => "754"             ; 8進数に変換

(set-file-modes "~/junk/diffs" 438)
     => nil

(format "%o" 438)
     => "666"             ; 8進数に変換

% ls -l diffs
  -rw-rw-rw-  1 lewis 0 3063 Oct 30 16:00 diffs

file-nlinks filename Function
この関数は、ファイルfilenameの 名前(つまりハードリンク)の個数を返す。 ファイルが存在しなければ、この関数はnilを返す。 シンボリックリンクはそれが指すファイルの名前とはみなさないので、 シンボリックリンクはこの関数には効果を持たない。
% ls -l foo*
-rw-rw-rw-  2 rms       4 Aug 19 01:27 foo
-rw-rw-rw-  2 rms       4 Aug 19 01:27 foo1

(file-nlinks "foo")
     => 2
(file-nlinks "doesnt-exist")
     => nil

file-attributes filename Function
この関数はファイルfilenameの属性のリストを返す。 オープンできないファイルを指定するとnilを返す。

リストの要素は順につぎのとおりである。

  1. ディレクトリはt、 シンボリックリンクは(それが指す名前の)文字列、 テキストファイルはnilである。
  2. ファイルの名前の個数。 別の名前、つまり、 ハードリンクは関数add-name-to-file(see Changing Files) を使って作成する。
  3. ファイルのUID(所有者番号)。
  4. ファイルのGID(グループ番号)。
  5. 2つの整数から成るリストとしての最終参照時刻。 最初の整数は時刻の上位16ビットであり、2番目は下位16ビット。 (これはcurrent-timeの値と同様。 Time of Dayを参照。)
  6. 2つの整数から成るリストとしての最終更新時刻(上記と同様)。
  7. 2つの整数から成るリストとしての最終状態更新時刻(上記と同様)。
  8. バイト単位でのファイルのサイズ。
  9. ls -lと同様のファイルのモードを表す10文字の文字列。
  10. もしファイルを削除して再度作成した場合に ファイルのGID(グループ番号)が変わる場合にはt。 さもなければnil
  11. ファイルのiノード番号。 可能ならばこれは整数である。 iノード番号がEmacs Lispの整数として表現できないほど大きな場合、 値は(high . low)の形である。 ただし、lowは下位16ビットである。
  12. ファイルが置いてあるファイルシステムのファイルシステム番号。 この要素とファイルのiノード番号により、 システム上の任意の2つのファイルを区別するために十分な情報を与える。 つまり、2つのファイルが同じ値のこれらの番号を持つことはない。

たとえば、files.texiのファイル属性はつぎのようである。

(file-attributes "files.texi")
     =>  (nil 1 2235 75
          (8489 20284)
          (8489 20284)
          (8489 20285)
          14906 "-rw-rw-rw-"
          nil 129500 -32252)

この意味はつぎのとおりである。

nil
ディレクトリでもシンボリックリンクでもない。
1
唯一の名前(カレントディレクトリでfiles.texi)を持つ。
2235
UID(ユーザー番号)2235のユーザーが所有している。
75
GID(グループ番号)75のグループに属する。
(8489 20284)
最後に参照されたのは8月19日00時09分である。
(8489 20284)
最後に更新されたのは8月19日00時09分である。
(8489 20285)
最後にこのiノードを変更したのは8月19日00時09分である。
14906
長さは14906バイトである。
"-rw-rw-rw-"
モードは、所有者/グループ/その他は読み書きできる。
nil
再度作成してもGID(グループ番号)は保存される。
129500
iノード番号は129500。
-32252
ファイルシステム番号は-32252。


Node:Changing Files, Next:, Previous:Information about Files, Up:Files

ファイルの名前と属性の変更

本節の関数は、ファイルを改名/コピー/削除/リンクしたり、 ファイルのモードを設定するためのものです。

引数newnameをとる関数では、 newnameで指定したファイルが既存の場合、 関数の動作は引数ok-if-already-existsの値に依存します。

add-name-to-file oldname newname &optional ok-if-already-exists Function
この関数は、oldnameで指定したファイルに 追加の名前newnameを与える。 つまり、newnameoldnameへの新たな『ハードリンク』になる。

つぎの例では、2つのファイルfoofoo3がある。

% ls -li fo*
81908 -rw-rw-rw-  1 rms       29 Aug 18 20:32 foo
84302 -rw-rw-rw-  1 rms       24 Aug 18 20:31 foo3

add-name-to-fileを呼んでハードリンクを作成し、 ファイル一覧を表示し直す。 1つのファイルに2つの名前foofoo2があることがわかる。

(add-name-to-file "foo" "foo2")
     => nil

% ls -li fo*
81908 -rw-rw-rw-  2 rms       29 Aug 18 20:32 foo
81908 -rw-rw-rw-  2 rms       29 Aug 18 20:32 foo2
84302 -rw-rw-rw-  1 rms       24 Aug 18 20:31 foo3

最後につぎの式を評価し

(add-name-to-file "foo" "foo3" t)

ファイル一覧を表示し直す。 今度は、1つのファイルに3つの名前foofoo2foo3がある。 古いfoo3の内容は失われている。

(add-name-to-file "foo1" "foo3")
     => nil

% ls -li fo*
81908 -rw-rw-rw-  3 rms       29 Aug 18 20:32 foo
81908 -rw-rw-rw-  3 rms       29 Aug 18 20:32 foo2
81908 -rw-rw-rw-  3 rms       29 Aug 18 20:32 foo3

1つのファイルに複数の名前を許さないオペレーティングシステムでは、 この関数は意味がない。 File Attributesfile-nlinksも参照。

rename-file filename newname &optional ok-if-already-exists コマンド
このコマンドは、ファイルfilenamenewnameと改名する。

filenamefilename以外の名前があれば、 それらの名前は存在し続ける。 実際、add-name-to-fileで名前newnameを追加してから filenameを削除すると、一時的な中間状態があることを除けば、 改名と同じ効果がある。

対話的に呼び出されると、この関数は ミニバッファでfilenamenewnameを聞く。 また、newnameが既存であると確認を求める。

copy-file oldname newname &optional ok-if-exists time コマンド
このコマンドはファイルoldnamenewnameへコピーする。 oldnameが存在しないとエラーを通知する。

timenil以外であると、 この関数は新たなファイルに古いファイルと同じ最終更新時刻を与える。 (これは特定のオペレーティングシステムでのみ動作する。) 時刻設定でエラーがあると、copy-fileは エラーfile-date-errorを通知する。

対話的に呼び出されると、この関数は ミニバッファでoldnamenewnameを聞く。 また、newnameが既存であると確認を求める。

delete-file filename コマンド
このコマンドは、シェルコマンドrm filenameと同様に ファイルfilenameを削除する。 ファイルに複数の名前があると、他の名前では存在し続ける。

ファイルが存在しなかったり削除できないと、 エラーfile-errorの適切な種類が通知される。 (UNIXでは、ファイルを収めたディレクトリに書けると 当該ファイルは削除可能である。) Create/Delete Dirsdelete-directoryも参照。

make-symbolic-link filename newname &optional ok-if-exists コマンド
このコマンドは、filenameに対するシンボリックリンクnewnameを 作成する。 これはシェルコマンドln -s filename newnameと同じである。

対話的に呼び出されると、この関数は ミニバッファでfilenamenewnameを聞く。 また、newnameが既存であると確認を求める。

define-logical-name name string Function
この関数は論理名nameに値stringを定義する。 VMSでのみ使える。

set-file-modes filename mode Function
この関数はfilenameのモードビットを mode(整数であること)と設定する。 modeの下位12ビットのみを使う。

set-default-file-modes mode Function
この関数は、Emacsやそのサブプロセスが作成する新規ファイルの デフォルトのファイルモードを設定する。 Emacsが作成する各ファイルは最初このモードになる。 UNIXでは、デフォルトのモードは『umask』の値の1の補数である。

引数modeは整数であること。 ほとんどのシステムでは、modeの下位9ビットのみが意味を持つ。

既存ファイルの変更を保存することはファイルの作成とはみなさないため、 ファイルのモードは変わらず、デフォルトのファイルモードを使わない。

default-file-modes Function
この関数は、現在のデフォルトのファイルモードの値を返す。

MS-DOSでは、『実行可能』ファイルモードビットのようなものはありません。 そのためEmacsは、.com.bat.exeのいずれかで 終る名前のファイルを実行可能であるとみなします。 これは、file-modesfile-attributesが返す値に反映されます。


Node:File Names, Next:, Previous:Changing Files, Up:Files

ファイル名

他の場面と同様にEmacsでは、一般にファイルはその名前で参照します。 Emacsではファイル名は文字列で表します。 ファイルを操作する関数はすべてファイル名引数を仮定します。

ファイル自体の操作に加えて、Emacs Lispプログラムは ファイルの名前そのものを操作する必要があります。 つまり、ファイル名を分解したり、関連するファイル名を作成するために その一部を使います。 本節ではファイル名を操作する方法を説明します。

本節の関数は実際にはファイルを参照しませんから、 既存のファイルやディレクトリを表さないファイル名を操作できます。

VMSでは、これらの関数はすべて、VMSのファイル名構文と UNIXの構文の両方を理解します。 つまり、標準LispライブラリはUNIX構文でファイル名を指定でき、 変更せずにVMS上で正しく動作します。 MS-DOSやMS-Windowsでは、これらの関数は、 UNIX構文に加えてMS-DOSやMS-Windowsのファイル名構文を理解します。


Node:File Name Components, Next:, Up:File Names

ファイル名の構成要素

オペレーティングシステムは、一連のファイルをディレクトリにまとめます。 ファイルを指定するには、ディレクトリと当該ディレクトリ内のファイルの名前を 指定する必要があります。 そのためEmacsは、ファイル名には2つの部分、 ディレクトリ名(directory name)部分と 非ディレクトリ名(nondirectory name)部分 (つまりディレクトリ内のファイル名)があるとみなします。 どちらかの部分は空でもかまいません。 これらの2つの部分を連結するともとのファイル名になります。

UNIXでは、ディレクトリ部分は最後のスラッシュまでを含んだ部分であり、 非ディレクトリ部分は残りの部分です。 VMSの構文規則は複雑です。

ある種の目的のために、非ディレクトリ部分をさらに 名前だけの部分と版番号(version number)に分けます。 UNIXでは、バックアップファイルだけにそれらの名前に版番号があります。 VMSでは各ファイルに版番号がありますが、 ほとんどの場合、Emacsで実際に使うファイル名では版番号を省略します。 そのため、Emacsで版番号が見えるのは多くの場合ディレクトリ一覧です。

file-name-directory filename Function
この関数はfilenameのディレクトリ部分 (ディレクトリ部分がなければnil)を返す。 UNIXでは、この関数はスラッシュで終る文字列を返す。 VMSでは、:]>のいずれかで終る文字列を返す。
(file-name-directory "lewis/foo")  ; UNIXの例
     => "lewis/"
(file-name-directory "foo")        ; UNIXの例
     => nil
(file-name-directory "[X]FOO.TMP") ; VMSの例
     => "[X]"

file-name-nondirectory filename Function
この関数はfilenameの非ディレクトリ部分を返す。
(file-name-nondirectory "lewis/foo")
     => "foo"
(file-name-nondirectory "foo")
     => "foo"
;; つぎの例はVMSでのみ正確である
(file-name-nondirectory "[X]FOO.TMP")
     => "FOO.TMP"

file-name-sans-versions filename Function
この関数は、filenameから版番号、バックアップ版番号、 末尾のティルダをすべて削除したものを返す。
(file-name-sans-versions "~rms/foo.~1~")
     => "~rms/foo"
(file-name-sans-versions "~rms/foo~")
     => "~rms/foo"
(file-name-sans-versions "~rms/foo")
     => "~rms/foo"
;; つぎの例はVMSでのみ正確である
(file-name-sans-versions "foo;23")
     => "foo"

file-name-sans-extension filename Function
この関数は、filenameからあれば『拡張子』を除いたものを返す。 ファイル名の拡張子とは、 名前の最後の部分にある.で始まる部分である。 たとえばつぎのとおりである。
(file-name-sans-extension "foo.lose.c")
     => "foo.lose"
(file-name-sans-extension "big.hack/foo")
     => "big.hack/foo"


Node:Directory Names, Next:, Previous:File Name Components, Up:File Names

ディレクトリ名

ディレクトリ名(directory name)とはディレクトリの名前です。 ディレクトリはファイルの一種であり、ファイル名を持ちますが、 それはディレクトリ名に関連付けられますが同一ではありません。 (これはUNIXの通常の用語と同じではない。) 同じものに対するこれらの異なる2つの名前は、構文の変換で関連付けます。 UNIXではこれは簡単であり、ディレクトリ名はスラッシュで終りますが、 ファイルとしてのディレクトリの名前にはスラッシュはありません。 VMSでは、関係はより複雑です。

ディレクトリ名とそのファイルとしての名前との違いはわずかですが重大です。 Emacsの変数や関数引数がディレクトリ名と記述されているときには、 ディレクトリのファイルとしての名前は受け付けません。

つぎの2つの関数はディレクトリ名とファイルとしての名前を相互に変換します。 これらは、$HOMEなどの環境変数置換や ~..などの構造にはなにも特別なことはしません。

file-name-as-directory filename Function
この関数は、オペレーティングシステムが ディレクトリ名と解釈する表現で表したfilenameの文字列を返す。 UNIXでは、文字列に(最後にスラッシュがなければ)スラッシュを 付加することを意味する。 VMSでは、[X]Y.DIR.1の形の文字列を[X.Y]の形に変換する。
(file-name-as-directory "~rms/lewis")
     => "~rms/lewis/"

directory-file-name dirname Function
この関数は、オペレーティングシステムが ファイルの名前と解釈する表現で表したdirnameの文字列を返す。 UNIXでは、文字列の最後のスラッシュを取り除くことを意味する。 VMSでは、[X.Y]の形の文字列を[X]Y.DIR.1の形に変換する。
(directory-file-name "~lewis/")
     => "~lewis"

シンボリックリンクを介して通常参照されるディレクトリには ディレクトリ名の省略形が有用です。 ユーザーはリンクの名前をディレクトリの『名前』としばしばみなし、 ディレクトリの『本当の』名前を見るのをわずらわしく思うことがあります。 リンク名を『本当の』名前の省略形と定義しておくと、 Emacsはユーザーに省略形を表示します。

directory-abbrev-alist Variable
変数directory-abbrev-alistは、 ディレクトリに使う省略形の連想リストを保持する。 各要素は(from . to)の形であり、 ディレクトリ名にfromが現れるとこれをtoに置き換えることを指示する。 文字列fromは実際には正規表現であり、つねに^で始まること。 関数abbreviate-file-nameがこれらの置換を行う。

ファイルsite-init.elでこの変数に設定し、 読者のサイトに適した省略形を記述できる。

ファイルシステム/home/fsfなどをシンボリック名/fsfで通常参照する システムの例をつぎに示す。

(("^/home/fsf" . "/fsf")
 ("^/home/gp" . "/gp")
 ("^/home/gd" . "/gd"))

ディレクトリ名をその省略形に変換するには、つぎの関数を使います。

abbreviate-file-name dirname Function
この関数は、directory-abbrev-alistの省略形を引数に適用し、 ユーザーのホームディレクトリを~に置き換える。


Node:Relative File Names, Next:, Previous:Directory Names, Up:File Names

ファイルの絶対名と相対名

ファイルシステム内のすべてのディレクトリは、 ルートディレクトリから始まる木を形作ります。 ファイル名では、木のルートから始まるすべてのディレクトリ名を指定できて、 これを絶対(absolute)ファイル名と呼びます。 あるいは、デフォルトディレクトリを基準に 木の中でのファイルの位置を指定することもでき、 これを相対(relative)ファイル名と呼びます。 UNIXでは、絶対ファイル名はスラッシュかティルダ(~)で始まり、 相対ファイル名はそれらでは始まりません。 VMSでの規則は複雑です。

file-name-absolute-p filename Function
この関数は、ファイルfilenameが絶対ファイル名であればtを返し、 さもなければnilを返す。 VMS上では、この関数はUNIXの構文とVMSの構文の両方を理解する。
(file-name-absolute-p "~rms/foo")
     => t
(file-name-absolute-p "rms/foo")
     => nil
(file-name-absolute-p "/user/rms/foo")
     => t


Node:File Name Expansion, Next:, Previous:Relative File Names, Up:File Names

ファイル名を展開する関数

ファイル名の展開(expansion)とは、 相対ファイル名を絶対ファイル名に変換することです。 これはデフォルトディレクトリを基準に行うので、 展開すべきファイル名に加えて、デフォルトディレクトリの名前も 指定する必要があります。 また、展開では、./name/../のような冗長部分を 取り除いてファイル名を単純にします。

expand-file-name filename &optional directory Function
この関数はfilenameを絶対ファイル名に変換する。 directoryが与えられると、 filenameが相対ファイル名であれば、 デフォルトディレクトリを基準にする。 (directoryの値そのものは絶対ディレクトリ名であること。 ~で始まってもよい。) さもなければ、バッファのdefault-directoryの値を使う。 たとえばつぎのとおり。
(expand-file-name "foo")
     => "/xcssun/users/rms/lewis/foo"
(expand-file-name "../foo")
     => "/xcssun/users/rms/foo"
(expand-file-name "foo" "/usr/spool/")
     => "/usr/spool/foo"
(expand-file-name "$HOME/foo")
     => "/xcssun/users/rms/lewis/$HOME/foo"

...を含むファイル名は、それらの正則な形に単純化する。

(expand-file-name "bar/../foo")
     => "/xcssun/users/rms/lewis/foo"

expand-file-nameは環境変数を展開しないことに注意。 substitute-in-file-nameだけがそれを行う。

file-relative-name filename directory Function
この関数は展開の逆操作を行う。 つまり、directoryを基準に解釈すると filenameと等価になる相対名を返す。

絶対ファイル名が装置名で始まるシステムもある。 そのようなシステムでは、directoryfilenameが 2つの異なる装置名で始まると、 filenameに等価なdirectoryを基準にした相対名はない。 そのような場合、file-relative-nameは 絶対名の形でfilenameを返す。

(file-relative-name "/foo/bar" "/foo/")
     => "bar"
(file-relative-name "/foo/bar" "/hack/")
     => "/foo/bar"

default-directory Variable
このバッファローカルな変数の値は、 カレントバッファのデフォルトディレクトリである。 これは絶対ディレクトリ名であること。 ~で始まってもよい。 この変数は各バッファにおいてバッファローカルである。

expand-file-nameは、その第2引数がnilであると デフォルトディレクトリを使う。

UNIXでは、この値はつねにスラッシュで終る文字列である。

default-directory
     => "/user/lewis/manual/"

substitute-in-file-name filename Function
この関数は、filename内の環境変数の参照を 環境変数の値で置き換える。 UNIXのシェルの構文規則に従って、 $は環境変数の値に置換するための接頭辞である。

環境変数名は、$に続く(下線を含む)英数字の列である。 $のつぎの文字が{であると、 対応する}までが変数名である。

ここでは、環境変数HOMEはユーザーのホームディレクトリ名 /xcssun/users/rmsを保持していると仮定する。

(substitute-in-file-name "$HOME/foo")
     => "/xcssun/users/rms/foo"

置換後、/のつぎに~/が現れると、 /までの部分をすべて取り除く。

(substitute-in-file-name "bar/~/foo")
     => "~/foo"
(substitute-in-file-name "/usr/local/$HOME/foo")
     => "/xcssun/users/rms/foo"
     ;; /usr/local/ has been discarded.

VMSでは、$による置換は行わないため、 この関数は冗長部分を取り除く以外にはなにも行わない。


Node:Unique File Names, Next:, Previous:File Name Expansion, Up:File Names

一意なファイル名の生成

一時的なファイルに書く必要があるプログラムもあります。 そのようなファイル向けの名前を作る通常の方法はつぎのとおりです。

(make-temp-name
 (expand-file-name name-of-application
                   temporary-file-directory))

make-temp-nameの仕事は、 異なる2人のユーザーや異なる2つのジョブがまったく同じファイル名を 使わないようにすることです。 この例では、変数temporary-file-directoryを使って 一時的なファイルを置く場所を決めています。 すべてのEmacs Lispプログラムでは、 すべての一時的なファイル向けのディレクトリを指定する 一意な方法をユーザーに提供するために、 この目的にはtemporary-file-directoryを使うべきです。

make-temp-name string Function
この関数は、一意なファイル名として使える文字列を生成する。 名前はstringで始まり、各Emacsジョブごとに異なる数を含む。
(make-temp-name "/tmp/foo")
     => "/tmp/foo232J6v"

同じEmacsで動作している異なるライブラリのあいだで衝突しないように、 make-temp-nameを使う各Lispプログラムでは、 独自のstringを使うべきである。 stringの末尾に付加される数は、 異なるEmacsジョブで動いている同じアプリケーションを区別する。 文字を余計に追加することで、1つのEmacsジョブであっても 異なる名前の個数を非常に多くできる。

temporary-file-directory Variable
この変数は、一時的なファイルを作成するためのディレクトリ名を指定する。 その値はディレクトリ名(see Directory Names)であるべきだが、 Lispプログラムにとっては、 その値がディレクトリのファイルとしての名前であっても処理できるほうがよい。 この値をexpand-file-nameの第2引数に使うと、 そのようにできる。

デフォルト値は、読者のオペレーティングシステムにおいて 合理的な方法で決定される。 GNUとUNIXシステムでは、環境変数TMPTMPDIRを基にする。

読者が一時的なファイル名を選ぶためにmake-temp-nameを 使わない場合であっても、 一時的なファイル名を置くディレクトリを決めるために この変数を使うべきである。


Node:File Name Completion, Next:, Previous:Unique File Names, Up:File Names

ファイル名の補完

本節では、ファイル名の補完向けの低レベルのサブルーティンについて述べます。 他の補完関数については、Completionを参照してください。

file-name-all-completions partial-filename directory Function
この関数は、ディレクトリdirectoryにおいて partial-filenameで始まる名前のファイルに対する すべての補完候補から成るリストを返す。 候補の順番はディレクトリ内でのファイルの順番であり、 それは予測できず有用な情報はなにもない。

引数partial-filenameは、ディレクトリ部分やスラッシュを いっさい含まないファイル名であること。 directoryが絶対名でないと、 カレントバッファのデフォルトディレクトリをdirectoryのまえに補う。

つぎの例で、カレントデフォルトディレクトリは~rms/lewisであり、 fで始まる名前のファイルは、 foofile~file.cfile.c.~1~file.c.~2~の5つであると仮定する。

(file-name-all-completions "f" "")
     => ("foo" "file~" "file.c.~2~"
                "file.c.~1~" "file.c")

(file-name-all-completions "fo" "")
     => ("foo")

file-name-completion filename directory Function
この関数は、ディレクトリdirectoryにおいてファイル名filenameを 補完する。 ディレクトリdirectoryにおいてfilenameで始まる すべてのファイル名に共通な最長の文字列を返す。

filenameで始まるものがたった1つであり完全に一致すると、 この関数はtを返す。 ディレクトリdirectoryfilenameで始まる名前がないと nilを返す。

つぎの例で、カレントデフォルトディレクトリには fで始まる名前のファイルは、 foofile~file.cfile.c.~1~file.c.~2~の5つであると仮定する。

(file-name-completion "fi" "")
     => "file"

(file-name-completion "file.c.~1" "")
     => "file.c.~1~"

(file-name-completion "file.c.~1~" "")
     => t

(file-name-completion "file.c.~3" "")
     => nil

completion-ignored-extensions User Option
file-name-completionは、このリスト内のいずれかの文字列で終る 名前のファイルを通常無視する。 補完候補すべてがこれらの接頭辞の1つで終る場合や、 補完候補すべてを含んだバッファが表示されている場合には無視しない。

典型的な値はつぎのとおりである。

completion-ignored-extensions
     => (".o" ".elc" "~" ".dvi")


Node:Standard File Names, Previous:File Name Completion, Up:File Names

標準ファイル名

Lispプログラムで使われるほとんどのファイル名は、 ユーザーが入力したものです。 しかし、Lispプログラムでは、 特定目的の標準ファイル名を指定する必要がある場合があります。 典型的には、各ユーザーごとのカスタマイズ情報を保持するものです。 たとえば、省略形の定義は(デフォルトでは) ファイル~/.abbrev_defsに保存されます。 パッケージcompletionは、 補完情報をファイル~/.completionsに保存します。 これらは、Emacsで特定目的に使われる多くの標準ファイル名のうちの2つです。

さまざまなのオペレーティングシステムには、 正しいファイル名やユーザーのプロフィールデータに使うファイル名に 独自の慣習があります。 標準ファイル名を使用するファイルを読み込むLispプログラムでは、 各システムごとに当該システムに適したファイル名を使うべきです。 関数convert-standard-filenameは、これを簡単にします。

convert-standard-filename filename Function
この関数は、ファイル名filenameを使用しているオペレーティングシステム の慣習に従うように変換し、新たな文字列として結果を返す。

Lispプログラムにおいて標準ファイル名を指定する推奨方法は、 GNUとUNIXシステムの慣習に従った名前を選ぶことです。 つまり、ピリオドで始まる非ディレクトリ部分を選び、 それを直接使うかわりにconvert-standard-filenameに渡します。 パッケージcompletionからの例をつぎに示します。

(defvar save-completions-file-name
        (convert-standard-filename "~/.completions")
  "*The file name to save completions to.")

GNUとUNIXシステム、および、他のいくつかのシステムでは、 convert-standard-filenameは引数を未変更で返します。 別のシステムでは、システムの慣習に従うように名前を変更します。

たとえば、MS-DOSではこの関数は、先頭の._に、 .がどこにもなければ名前の途中の_.に、 8文字目のうしろに.がなければ.を挿入し、 .以降の3文字よりうしろを切り詰めるなどを行います。 (これ以外にも変更する。) したがって、.abbrev_defs_abbrev.defとなり、 .completions_complet.ionとなります。


Node:Contents of Directories, Next:, Previous:File Names, Up:Files

ディレクトリの内容

ディレクトリは、さまざまな名前で入れた別のファイルを 収めているファイルの一種です。 ディレクトリは、ファイルシステムの機能です。

Emacsは、ディレクトリ内のファイル名をLispのリストとして一覧にしたり、 シェルコマンドlsを使ってバッファに名前を表示できます。 後者の場合、コマンドlsに渡したオプションに応じて、 各ファイルに関する情報も表示できます。

directory-files directory &optional full-name match-regexp nosort Function
この関数は、ディレクトリdirectory内の ファイルの名前から成るリストを返す。 デフォルトでは、リストはアルファベット順になる。

full-namenil以外であると、 関数はファイルの絶対ファイル名を返す。 さもなければ、指定したディレクトリに対する相対名を返す。

match-regexpnil以外であると、 この関数は正規表現match-regexpに一致するファイル名のみを返す。 つまり、他の名前のファイルはリストから除かれる。

nosortnil以外であると、 directory-filesはリストをソートしないので、 ファイル名の順番に規則はない。 処理速度を最大にしてファイルの処理順序に拘らないならば、これを用いる。 処理順序がユーザーに見える場合には、 ソートしたほうがユーザーは幸せであろう。

(directory-files "~lewis")
     => ("#foo#" "#foo.el#" "." ".."
         "dired-mods.el" "files.texi"
         "files.texi.~1~")

directoryが読めないディレクトリの名前であるとエラーを通知する。

file-name-all-versions file dirname Function
この関数は、ディレクトリdirname内のfileという名前の ファイルのすべての版から成るリストを返す。

insert-directory file switches &optional wildcard full-directory-p Function
この関数は、lsswitchesを渡して表示した ディレクトリfileの一覧を(カレントバッファに)挿入する。 ポイントは挿入したテキストのうしろに置かれる。

引数fileは、ディレクトリ名であるか ワイルドカードを含んだファイル指定である。 wildcardnil以外であると、 fileをワイルドカードを含むファイル指定として扱う。

full-directory-pnil以外であると、 ディレクトリ一覧はディレクトリの全内容を表すと仮定することを意味する。 fileがディレクトリでありswitches-dを含まない場合には、 tを指定すべきである。 (lsのオプション-dは、 ディレクトリの内容ではなく、ファイルとしてのディレクトリ自身を 表示することを意味する。)

この関数は、変数insert-directory-programで指定される 名前のディレクトリ表示プログラムを実行して動作する。 wildcardnil以外であると、 ワイルドカードを展開するためにshell-file-nameで指定される シェルを実行する。

insert-directory-program Variable
この変数の値は、関数insert-directoryで ディレクトリ一覧を生成するために実行するプログラムである。


Node:Create/Delete Dirs, Next:, Previous:Contents of Directories, Up:Files

ディレクトリの作成と削除

Emacs Lispのほとんどのファイル操作関数は、 ディレクトリであるファイルに使うとエラーになります。 たとえば、delete-fileではディレクトリを削除できません。 これらの特別な関数はディレクトリを作成したり削除するためのものです。

make-directory dirname Function
この関数はdirnameという名前のディレクトリを作る。

delete-directory dirname Function
この関数は、ディレクトリdirnameを削除する。 関数delete-fileは、ディレクトリであるファイルには使えない。 ディレクトリにはdelete-directoryを使う必要がある。 ディレクトリ内にファイルがあると、delete-directoryは エラーを通知する。


Node:Magic File Names, Next:, Previous:Create/Delete Dirs, Up:Files

ファイル名を『マジック』にする

特定のファイル名を特別に扱うことができます。 これをそれらの名前をマジック(magic)にするといいます。 この機能の主な用途はリモートファイル名 (see Remote Files) を実装することです。

マジックファイル名の種類を定義するには、 名前のクラス(正規表現に一致するものすべて)を定義する正規表現と、 それに一致するファイルに対する Emacsの基本ファイル操作を実装するハンドラを指定する必要があります。

変数file-name-handler-alistは、 ハンドラと当該ハンドラの適用を決定する正規表現からなるリストを保持します。 各要素の形はつぎのとおりです。

(regexp . handler)

Emacsのすべてのファイル操作基本関数とファイル名変換基本関数は、 指定された名前をfile-name-handler-alistに対して検査します。 ファイル名がregexpに一致すると、 基本関数はhandlerを呼び出して当該ファイルを処理します。

handlerに与える最初の引数は基本関数の名前です。 残りの引数は当該操作に渡されるべき引数です。 (それらの引数の最初のものは典型的にはファイル名自身である。) たとえば、つぎのようにした場合、

(file-exists-p filename)

filenameにハンドラhandlerがあると、 handlerはつぎのように呼び出されます。

(funcall handler 'file-exists-p filename)

つぎは、マジックファイル名のハンドラが処理すべき操作です。

insert-file-contentsに対するハンドラは、 引数visitnil以外であるときには (set-buffer-modified-p nil)を使って バッファの変更フラグをクリアする必要が典型的にはあります。

ハンドラ関数は、上のすべての操作、ならびに、 将来追加されるものを扱える必要があります。 これらの操作すべてをハンドラ自身で実装する必要はありません。 特定の操作について特別なことを行う必要がなければ、 『通常どおりに』操作を処理するために基本関数を再起動できます。 ハンドラが認識できない操作については、 基本関数を再起動するべきです。 1つの方法はつぎのとおりです。

(defun my-file-handler (operation &rest args)
  ;; まず、特別に扱う必要がある操作かどうか検査する
  (cond ((eq operation 'insert-file-contents) ...)
        ((eq operation 'write-region) ...)
        ...
        ;; 知らない操作を扱う
        (t (let ((inhibit-file-name-handlers
                  (cons 'my-file-handler
                        (and (eq inhibit-file-name-operation operation)
                             inhibit-file-name-handlers)))
                 (inhibit-file-name-operation operation))
             (apply operation args)))))

ハンドラ関数で、指定された操作についてはEmacsの通常の基本関数を呼び出すと 決定したときには、基本関数から同じハンドラが再度呼ばれて 無限再帰になることを防ぐ必要があります。 上の例は、変数inhibit-file-name-handlersinhibit-file-name-operationを使ってこれを行う方法を示すものです。 それらを上に示したとおりに使うように注意してください。 複数のハンドラがあったり、 2つのファイルを扱う操作において各ファイルにハンドラがある場合には、 この詳細は重要です。

inhibit-file-name-handlers Variable
この変数は、特定操作については 現在適用を禁止されているハンドラのリストを保持する。

inhibit-file-name-operation Variable
特定のハンドラにおいて現在禁止されている操作。

find-file-name-handler file operation Function
この関数はファイル名fileに対するハンドラ関数を返す。 ハンドラがなければnilを返す。 引数operationは、ファイルに対して適用する操作であること。 つまり、ハンドラを呼び出すときに第1引数として渡される値。 当該操作はinhibit-file-name-operationと比較する必要がある。

file-local-copy filename Function
この関数は、ファイルfilenameがマジックでない普通のファイルでなければ、 filenameをマジックでない普通のファイルにコピーする。

filenameが、 Emacsの外側のプログラムからは直接読んだり書けないマジックファイル名であると、 この関数は普通のファイルにコピーしてそのファイルの名前を返す。

filenameが普通のファイル名でマジックでなければ、 この関数はなにもせずにnilを返す。

unhandled-file-name-directory filename Function
この関数は、マジックではないディレクトリの名前を返す。 filenameがマジックでなければ、 filenameのディレクトリ部分を使う。 マジックファイル名であると、ファイル名ハンドラを起動し、 当該ハンドラがどんな値を返すか決定する。

これは実行中のサブプロセスに有用である。 各サブプロセスには、カレントディレクトリとしてマジックでないディレクトリが 必要であり、この関数はそれを扱うのによい方法である。


Node:Format Conversion, Previous:Magic File Names, Up:Files

ファイル書式変換

変数format-alistは、 Emacsバッファ内のデータ(テキスト、テキスト属性、その他の情報)を ファイル内でテキスト表現する方法を記述した ファイル書式(file format)のリストを定義します。 Emacsはファイルを読み書きするときに必要ならば書式変換を行います。

format-alist Variable
このリストは、各ファイル書式の定義を含んだリストである。

各書式定義はつぎの形のリストです。

(name doc-string regexp from-fn to-fn modify mode-fn)

書式定義の各要素の意味はつぎのとおりです。

name
当該書式の名前。
doc-string
当該書式の説明文字列。
regexp
当該書式で表現されたファイルを認識するために使用する正規表現。
from-fn
当該書式のデータを復号化(ファイル内のデータをEmacsの通常のデータ表現へ 変換)するためのシェルコマンドか関数。

シェルコマンドは文字列で表現し、 Emacsは変換を行うために当該コマンドをフィルタとして実行する。

from-fnが関数であると、 バッファの変換すべき部分を指定するbeginendの2つの引数で 呼ばれる。 当該関数はその場で編集してテキストを変換すること。 これによりテキストの長さが変わる可能性があるので、 from-fnは変更部分の末尾位置を返すこと。

from-fnの責任の1つは、 ファイルの先頭がregexpで始まらないように保証することである。 さもないと、再度呼び出される可能性がある。

to-fn
当該書式にデータを符号化するためのシェルコマンドか関数。 つまり、Emacsの通常のデータ表現を当該書式に変換する。

to-fnが文字列であるとそれはシェルコマンドであり、 Emacsは変換を行うために当該コマンドをフィルタとして実行する。

to-fnが関数であると、 バッファの変換すべき部分を指定するbeginendの2つの引数で 呼ばれる。 変換を行うには2つの方法がある。


modify
フラグであり、 符号化関数がバッファを変更する場合にはt、 注記のリストを返す場合にはnilである。
mode
当該書式から変換されたファイルを訪問後に呼び出されるモード関数。

関数insert-file-contentsは、指定されたファイルを読み込むときに ファイル書式を自動的に認識します。 ファイルの先頭のテキストを書式定義の正規表現に対して検査して、 一致がみつかれば当該書式の復号化関数を呼び出します。 そして、既知の書式について再度調べ直します。 適用できる書式がなくなるまで検査し続けます。

関数find-file-noselectやこれを使うコマンドでファイルを訪問すると、 (insert-file-contentsを呼び出すので)同様に変換を行います。 さらに、この関数は、復号した各書式についてモード関数を呼び出します。 バッファローカルな変数buffer-file-formatに 書式名のリストを保存します。

buffer-file-format Variable
この変数は、訪問したファイルの書式を記述している。 より正確には、カレントバッファのファイルを訪問する過程で 復号したファイル書式名のリストである。 この変数は、すべてのバッファにおいてつねにバッファローカルである。

write-regionがデータをファイルに書き出すときには、まず、 buffer-file-formatで指定された書式の符号化関数を リストに現れる順に呼び出します。

format-write-file file format コマンド
このコマンドは、カレントバッファの内容を書式formatにて ファイルfileに書き出す。 さらに、当該書式をバッファを将来保存するときのデフォルトとする。 引数formatは、書式名のリストである。

format-find-file file format コマンド
このコマンドは、ファイルfileを探し、 それを書式formatに従って変換する。 さらに、当該書式をバッファをのちに保存するときのデフォルトとする。

引数formatは、書式名のリストである。 formatnilであると、変換を行わない。 対話的に呼び出した場合、 formatnilを指定するには<RET>のみを打つ。

format-insert-file file format &optional beg end コマンド
このコマンドは、ファイルfileの内容を書式formatに従って 変換して挿入する。 begendnil以外であると、 それらは、insert-file-contents(see Reading from Files)と同様に、 読み込むべきファイルの部分を指定する。

戻り値は、insert-file-contentsが返す値に似ており、 絶対ファイル名と挿入データの(変換後の)長さのリストである。

引数formatは、書式名のリストである。 formatnilであると、変換を行わない。 対話的に呼び出した場合、 formatnilを指定するには<RET>のみを打つ。

auto-save-file-format Variable
この変数は、自動保存に対して使用する書式を指定する。 その値は、buffer-file-formatの値のように、書式名のリストであるが、 buffer-file-formatのかわりに 自動保存ファイルを書くために使われる。 この変数は、すべてのバッファにおいてつねにバッファローカルである。


Node:Backups and Auto-Saving, Next:, Previous:Files, Up:Top

バックアップと自動保存

バックアップファイルと自動保存ファイルは、 クラッシュやユーザー自身の誤りから Emacsがユーザーを保護するための2つの方式です。 自動保存により、現在の編集セッションにおいて、 まえの時点でのテキストを確保します。 バックアップファイルにより、現在のセッション以前の ファイル内容を確保します。


Node:Backup Files, Next:, Up:Backups and Auto-Saving

バックアップファイル

バックアップファイル(backup file)とは、 読者が編集中のファイルの古い内容のコピーです。 バッファを訪問しているファイルに初めて保存するときに、 Emacsはバックアップファイルを作成します。 通常これは、バックアップファイルは 現在の編集セッションよりまえのファイルの内容を保持することを意味します。 バックアップファイルの内容は、通常、それが作られると変更されません。

訪問したファイルを新たな名前に改名することで 通常バックアップは作られます。 訪問したファイルをコピーしてバックアップファイルを作るように 指示することもできます。 どちらを選ぶかによって、複数の名前を持つファイルでは違いがでます。 また、編集したファイルの所有者が元所有者と同じであるか、 それとも編集したユーザーが所有者になるかにも影響します。

デフォルトでは、Emacsは各編集ファイルに1つのバックアップファイルを作ります。 番号付きのバックアップファイルを作るように指示することもでき、 そうすると、新たなバックアップファイルごとに新たな名前が付きます。 古い番号付きバックアップファイルは必要なくなれば削除できますし、 Emacsがそれらを自動的に削除することも可能です。


Node:Making Backups, Next:, Up:Backup Files

バックアップファイルの作成

backup-buffer Function
この関数は、必要ならば、カレントバッファで訪問しているファイルの バックアップを作成する。 バッファを初めて保存するまえにsave-bufferがこの関数を呼び出す。

buffer-backed-up Variable
このバッファローカルな変数は、 当該バッファのもとで当該バッファのファイルの バックアップを作成済みかどうかを表す。 nil以外であれば、バックアップファイルは作成済みであることを表す。 さもなければ、(バックアップがオンになっていれば)つぎに保存するときに ファイルのバックアップを作成するべきであることを表す。 これは恒久的にバッファローカルであり、 kill-local-variablesによって変更されない。

make-backup-files User Option
この変数は、バックアップファイルを作成するかどうかを決定する。 nil以外であると、backup-inhibitednilならば(下記参照) Emacsは初めて保存するときに各ファイルのバックアップを作成する。

つぎの例は、rmailのバッファでのみ変数make-backup-filesを 変更する方法である。 この変数をnilにすると、 Emacsはそれらのファイルのバックアップを作成しなくなり、 ディスクスペースの節約になる。 (このコードを読者のファイル.emacsに入れてもよい。)

(add-hook 'rmail-mode-hook
          (function (lambda ()
                      (make-local-variable
                       'make-backup-files)
                      (setq make-backup-files nil))))

backup-enable-predicate Variable
この変数の値は、ファイルをバックアップすべきかどうかを決定する ために特定の場面で呼び出される関数である。 当該関数は、調べるべきファイルの名前を引数にとる。 当該関数がnilを返すと、当該ファイルのバックアップは禁止である。 さもなければ、本節の他の変数が、 バックアップするかどうかやバックアップ方法を指定する。

デフォルト値はつぎのとおりである。

(lambda (name)
  (or (< (length name) 5)
      (not (string-equal "/tmp/"
                         (substring name 0 5)))))

backup-inhibited Variable
この変数がnil以外であると、バックアップを禁止する。 この変数は、訪問したファイルの名前に対するbackup-enable-predicateの 検査結果を記録している。 訪問したファイルに基づいてバックアップを禁止する 他の機構でもこの変数を使える。 たとえば、VCはこの変数にnil以外を設定し、 版管理システムで管理されているファイルに対してバックアップの作成を禁止する。

これは恒久的にバッファローカルであり、 メジャーモードを変更しても値は失われない。 メジャーモードはこの変数に設定するべきではなく、 かわりに、make-backup-filesに設定するべきである。


Node:Rename or Copy, Next:, Previous:Making Backups, Up:Backup Files

改名によるバックアップかコピーによるバックアップか

Emacsは2つの方法でバックアップファイルを作れます。

最初の改名による方式がデフォルトです。

変数backup-by-copyingnil以外であると、 2番目の方式、つまり、元ファイルをコピーしてから バッファの新たな内容で上書きすることを指示します。 変数file-precious-flagnil以外であっても (その主目的の副作用として)同じ効果があります。 See Saving Buffers

backup-by-copying Variable
この変数がnil以外であると、 Emacsはつねにコピーしてバックアップファイルを作る。

つぎの2つの変数がnil以外であると、 特定の場面では2番目の方式を使うことになります。 これらの変数は、特別な場面に該当しないファイルの扱い方には影響しません。

backup-by-copying-when-linked Variable
この変数がnil以外の場合、Emacsは、 複数の名前(ハードリンク)を持つファイルはコピーしてバックアップする。

この変数はbackup-by-copyingnil以外の場合にのみ意味を持つ。 というのは、その変数がnil以外の場合にコピーを用いるからである。

backup-by-copying-when-mismatch Variable
この変数がnil以外の場合、Emacsは、 改名するとファイルの所有者やグループを変更してしまう場合に コピーしてバックアップする。

改名してもファイルの所有者やグループを変更しなければ、 この値は効果を持たない。 つまり、ユーザーが所有しているファイルであり、 そのグループが当該ユーザーが新規作成するファイルのデフォルトに一致する 場合である。

この変数はbackup-by-copyingnil以外の場合にのみ意味を持つ。 というのは、その変数がnil以外の場合にコピーを用いるからである。


Node:Numbered Backups, Next:, Previous:Rename or Copy, Up:Backup Files

番号付きバックアップファイルの作成と削除

ファイル名がfooであると、 その番号付きバックアップファイルの名前はvを整数として foo.~v~となります。 つまり、foo.~1~foo.~2~foo.~3~...foo.~259~といった具合です。

version-control User Option
この変数は、番号なしの1つのバックアップファイルを作るのか 複数の番号付きバックアップファイルを作るのかを制御する。
nil
訪問したファイルにすでに番号付きバックアップファイルがあれば 番号付きバックアップを作る。 さもなければ作らない。
never
番号付きバックアップは作らない。
その他
番号付きバックアップを作る。

番号付きバックアップファイルを使うと、 最終的には非常に多くのバックアップファイルができてしまい、 それらは削除しなければなりません。 Emacsはそれらを自動的に削除したり、 削除するかどうかユーザーに問い合わせることができます。

kept-new-versions User Option
この変数の値は、新たに番号付きバックアップを作成したときに 保存すべき最新のバックアップの個数である。 新たに作成したバックアップも数える。 デフォルト値は2である。

kept-old-versions User Option
この変数の値は、新たに番号付きバックアップを作成したときに 保存すべき最古のバックアップの個数である。 デフォルト値は2である。

1、2、3、5、7と番号が付いたバックアップがあり、 これらのどちらの変数の値も2であるとすると、 最古のものとして1と2の番号が付いたバックアップを保存し、 最新のものとして5と7の番号が付いたバックアップを保存する。 関数find-backup-file-name(see Backup Names)は、 どの番号のバックアップを削除すべきかを決定する責任があるが、 それ自身はそれらを削除しない。

delete-old-versions User Option
この変数がnil以外であると、 ファイルを保存すると黙って範囲外のバックアップを削除する。 さもなければ、それを削除するかどうかユーザーに問い合わせる。

dired-kept-versions User Option
この変数は、diredのコマンド.dired-clean-directory)で 最新のバックアップを何個保存するかを指定する。 これは、新たなバックアップファイルの作成を指示したときに kept-new-versionsが指定することと同じである。 デフォルト値は2である。


Node:Backup Names, Previous:Numbered Backups, Up:Backup Files

バックアップファイルの命名方法

本節の関数は、それらを再定義することでバックアップファイルの命名方法を カスタマイズできるため、ここで述べることにします。 どれか1つを変更すると、残りのものも変更する必要があるでしょう。

backup-file-name-p filename Function
この関数は、filenameがバックアップファイルの名前である 可能性があるとnil以外の値を返す。 filenameという名前のファイルが存在する必要はなく、 この関数は単に名前だけを検査する。
(backup-file-name-p "foo")
     => nil
(backup-file-name-p "foo~")
     => 3

この関数の標準定義はつぎのとおりである。

(defun backup-file-name-p (file)
  "Return non-nil if FILE is a backup file \
name (numeric or not)..."
  (string-match "~$" file))

したがって、ファイル名が~で終っていると、 この関数はnil以外の値を返す。 (説明文字列を2行に分けるためにバックスラッシュを使っているが、 文字列としては1行になる。)

カスタマイズのために再定義しやすいように、 この単純な式を独立した関数にしてある。

make-backup-file-name filename Function
この関数は、ファイルfilenameに対する 番号なしバックアップファイルに使う名前を表す文字列を返す。 UNIXでは、単にfilenameの末尾にティルダを付加したものである。

ほとんどのオペレーティングシステムでは、 この関数の標準定義はつぎのとおりである。

(defun make-backup-file-name (file)
  "Create the non-numeric backup file name for FILE...."
  (concat file "~"))

この関数を再定義すれば、バックアップファイルの命名方法を変更できる。 つぎの例では、ティルダに加えて先頭に.を付けるように make-backup-file-nameを再定義する。

(defun make-backup-file-name (filename)
  (expand-file-name
    (concat "." (file-name-nondirectory filename) "~")
    (file-name-directory filename)))

(make-backup-file-name "backups.texi")
     => ".backups.texi~"

diredコマンドを含めてEmacsには、 バックアップファイルは~で終ると仮定しているものがある。 この慣習に従わない場合、重大な問題には至らないであろうが、 それらのコマンドがあまり望ましくない結果をもたらすかもしれない。

find-backup-file-name filename Function
この関数は、filenameに対する新たなバックアップファイルの ファイル名を計算する。 さらに、削除すべき既存のバックアップファイルも計算する。 find-backup-file-nameは、 CARに新たなバックアップファイルの名前、 CDRに削除すべきバックアップファイルのリストを持つリストを返す。

2つの変数、kept-old-versionskept-new-versionsは、 どのバックアップを保存すべきかを決定する。 この関数は、値のCDRではそれらのバックアップファイルは 除外してある。 see Numbered Backups

つぎの例の値では、~rms/foo.~5~が 新たなバックアップファイルの名前であり、 ~rms/foo.~3~が『範囲外』のものであり、 呼び出し側で削除するかどうか考慮すべきである。

(find-backup-file-name "~rms/foo")
     => ("~rms/foo.~5~" "~rms/foo.~3~")

file-newest-backup filename Function
この関数は、filenameの最新のバックアップファイルの名前を返す。 当該ファイルにバックアップファイルがなければnilを返す。

ファイルを比較するコマンドのなかには、 最新のバックアップファイルと自動的に比較できるように この関数を使うものがある。


Node:Auto-Saving, Next:, Previous:Backup Files, Up:Backups and Auto-Saving

自動保存

Emacsは編集中のすべてのファイルを定期的に保存します。 これを自動保存(auto-savign)と呼びます。 自動保存により、システムがクラッシュしても、 一定量以上の作業を失わないようにします。 デフォルトでは、300打鍵ごと、あるいは、30秒間なにもしないと自動保存します。 ユーザー向けの自動保存に関する情報については、 See Auto Save。 ここでは、自動保存を実装するための関数と それらを制御する変数について述べます。

buffer-auto-save-file-name Variable
このバッファローカルな変数は、カレントバッファの自動保存に 用いるファイル名である。 当該バッファを自動保存しない場合にはnilである。
buffer-auto-save-file-name
=> "/xcssun/users/rms/lewis/#files.texi#"

auto-save-mode arg コマンド
引数なしに対話的に呼ばれると、 このコマンドは自動保存機能をトグルする。 つまり、カレントバッファの自動保存がオンであるとオフにし、 オフならばオンにする。 引数argを指定すると、 argの値がt、空でないリスト、正整数のいずれかであれば、 このコマンドは自動保存をオンにする。 さもなければ自動保存をオフにする。

auto-save-file-name-p filename Function
この関数は、filenameが自動保存ファイルの名前でありえれば、 nil以外を返す。 この関数は自動保存ファイルの名前の慣習に基づいて動作する。 名前がハッシュマーク(#)で始まりかつ終っていれば、 自動保存ファイルの名前である可能性がある。 引数filenameにはディレクトリ部分を含まないこと。
(make-auto-save-file-name)
     => "/xcssun/users/rms/lewis/#files.texi#"
(auto-save-file-name-p "#files.texi#")
     => 0
(auto-save-file-name-p "files.texi")
     => nil

この関数の標準定義はつぎのとおりである。

(defun auto-save-file-name-p (filename)
  "Return non-nil if FILENAME can be yielded by..."
  (string-match "^#.*#$" filename))

この関数は、自動保存ファイルの名前の慣習を変更したい場合に 当該関数をカスタマイズできるようにするためである。 当該関数を再定義した場合には、関数make-auto-save-file-nameも それに従って必ず再定義すること。

make-auto-save-file-name Function
この関数は、カレントバッファの自動保存に使うファイル名を返す。 その名前は、単にファイル名の前後にハッシュマーク(#)を 付加するだけである。 この関数は変数auto-save-visited-file-name(下記参照)を 調べないため、読者はこの関数を呼び出すまえにその変数を検査しておくこと。
(make-auto-save-file-name)
     => "/xcssun/users/rms/lewis/#backup.texi#"

この関数の標準定義はつぎのとおりである。

(defun make-auto-save-file-name ()
  "Return file name to use for auto-saves \
of current buffer...."
  (if buffer-file-name
      (concat
       (file-name-directory buffer-file-name)
       "#"
       (file-name-nondirectory buffer-file-name)
       "#")
    (expand-file-name
     (concat "#%" (buffer-name) "#"))))

自動保存ファイルの名前の慣習をカスタマイズするために 関数を再定義できるように1つの関数にしてある。 関数auto-save-file-name-pもそれに従って必ず変更すること。

auto-save-visited-file-name Variable
この変数がnil以外であると、 Emacsは訪問しているファイルにバッファを自動保存する。 つまり、読者が編集しているファイルと同じファイルに自動保存を行う。 通常、この変数はnilであり、自動保存ファイルには make-auto-save-file-nameで作成した別の名前がある。

この変数の値を変更しても、 バッファの自動保存をつぎにオンにするまで、この値は効果を発揮しない。 自動保存がすでにオンであると、 auto-save-modeを再度呼び出すまでは、 同じファイルの名前に自動保存し続ける。

recent-auto-save-p Function
カレントバッファに最後に読み込んだり保存してから以降に自動保存していると、 この関数はtを返す。

set-buffer-auto-saved Function
この関数は、カレントバッファに自動保存済みであると印を付ける。 バッファのテキストが再度変更されない限り、バッファは自動保存されない。 この関数はnilを返す。

auto-save-interval User Option
この変数の値は、つぎの自動保存までに Emacsがキーボードから読み取る文字の個数である。 これだけの文字を読み取ると、自動保存をオンにしてあるすべてのバッファを 自動保存する。

auto-save-timeout User Option
この変数の値は、自動保存を引き起こすまでのなにもしていない期間の秒数である。 この時間だけユーザーがなにもしないと、 Emacsは自動保存する必要があるバッファを自動保存する。 (実際には、カレントバッファの大きさに依存した係数を指定時間に掛ける。)

auto-save-hook Variable
このノーマルフックは、自動保存を行う直前に毎回実行される。

auto-save-default User Option
この変数がnil以外であると、 ファイルを訪問しているバッファはデフォルトで自動保存をオンにする。 さもなければ、そうしない。

do-auto-save &optional no-message current-only コマンド
この関数は、自動保存する必要があるすべてのバッファを自動保存する。 自動保存がオンになっていて、かつ、以前の自動保存からあとで 変更されているすべてのバッファを自動保存する。

通常、バッファを自動保存すると、 自動保存を実行中にはエコー領域にメッセージAuto-saving...が表示される。 しかし、no-messagenil以外であると、 メッセージを表示しない。

current-onlynil以外であると、 カレントバッファのみを自動保存する。

delete-auto-save-file-if-necessary Function
この関数は、delete-auto-save-filesnil以外であると、 カレントバッファの自動保存ファイルを削除する。 バッファを保存するたびに呼び出される。

delete-auto-save-files Variable
この変数は、関数delete-auto-save-file-if-necessaryが使う。 nil以外であると、Emacsは(訪問しているファイルに)実際に 保存すると自動保存ファイルを削除する。 これによりディスクスペースを節約し、読者のディレクトリを整頓できる。

rename-auto-save-file Function
この関数は、訪問しているファイルの名前が変更されていると、 カレントバッファの自動保存ファイルの名前を修正する。 さらに、既存の自動保存ファイルも改名する。 訪問しているファイルの名前が変更されていなければ、 この関数はなにもしない。

buffer-saved-size Variable
このバッファローカルな変数の値は、 最後に読み込んだり保存したり自動保存したときの カレントバッファの長さである。 サイズの大幅な変更を検知すると自動保存をオフにするために使われる。

この変数が-1であると、 大幅に削除したために一時的に自動保存をオフにしたことを意味する。 明示的にバッファを保存すると、この変数に正の値が保存され、 自動保存が再度オンになる。 自動保存をオフにしたりオンにしても、この変数が変更される。

auto-save-list-file-name Variable
この変数は(nil以外であると)、 すべての自動保存ファイルの名前を記録するファイルを指定する。 Emacsが自動保存を行うたびに、 自動保存がオンである各バッファに関する2行をこのファイルに書き出す。 1行目は訪問しているファイルの名前を与え(訪問していなければ空)、 2行目は自動保存ファイルの名前を与える。

Emacsが正常に終ると、このファイルは削除される。 Emacsがクラッシュしたら、失われてしまう作業内容を含んでいるかもしれない 自動保存ファイルを探すために読者はこのファイルを調べられる。 コマンドrecover-sessionはこれらのファイルを使う。

このファイルのデフォルト名は、 読者のホームディレクトリにあり.saves-で始まる。 さらに、EmacsのプロセスIDとホスト名も含む。


Node:Reverting, Previous:Auto-Saving, Up:Backups and Auto-Saving

復元

ファイルを大幅に変更したあとで、そのような変更をやめたい場合には、 コマンドrevert-bufferでファイルのまえの版を読み込めます。 See Reverting

revert-buffer &optional ignore-auto noconfirm コマンド
このコマンドは、バッファのテキストを ディスク上の訪問しているファイルのテキストで置き換える。 これにより、ファイルを訪問したり保存してから行った変更をすべて取り消せる。

デフォルトでは、最後の自動保存ファイルが 訪問しているファイルよりも新しい場合には、 revert-bufferは自動保存ファイルを使うかどうか ユーザーに問い合わせる。 しかし、引数ignore-autonil以外であると、 訪問したファイルのみを使う。 対話的に呼ばれた場合、数値前置引数を指定しない限り、 ignore-autotである。 したがって、対話的な場合のデフォルトでは、自動保存ファイルを検査する。

通常、バッファを変更するまえにrevert-bufferは確認してくる。 しかし、引数noconfirmnil以外であると、 revert-bufferは確認しない。

復元作業では、 insert-file-contentsの置換機能を用いて バッファ内のマーカ位置を保存するように努める。 復元操作のまえにバッファの内容とファイルの内容が同一であれば、 すべてのマークが保存される。 同一でなければ、復元によりバッファが変更され、 バッファの先頭と末尾の(あれば)未変更なテキスト内のマーカを保存する。 それ以外のマーカを保存しても問題を引き起こすだけであろう。

以下の変数を典型的にはバッファローカルな変数として設定することで revert-bufferの動作をカスタマイズできます。

revert-without-query Variable
この変数は、問い合わせずに復元すべきファイルのリストを保持する。 値は、正規表現のリストである。 ファイル名がこれらの正規表現の1つに一致すると、 ディスク上のファイルが変更されていて当該バッファが未変更であれば、 revert-bufferはユーザーに確認せずに当該ファイルを復元する。

revert-buffer-function Variable
この変数の値は、このバッファを復元するために使う関数である。 nil以外であれば、復元を行う引数なしの関数として呼び出される。 値がnilであると、復元操作は通常の方法で行われる。

diredモードなどのモードでは、 編集中のテキストはファイルの内容ではなく 別の方法で再生成されたものなので、 この変数のバッファローカルな値には内容を再生成する関数を指定すること。

revert-buffer-insert-file-contents-function Variable
この変数の値がnil以外であると、 このバッファを復元するときに更新内容を挿入するために使われる関数である。 当該関数は2つの引数をとる。 第1引数は、使用するファイル名である。 第2引数は、ユーザーが自動保存ファイルを 読むように指示しているとtである。

before-revert-hook Variable
このノーマルフックは、revert-buffer-functionnilである 場合にのみ、変更内容を実際に挿入するまえにrevert-bufferが実行する。

フォントロック(font-lock)モードはこのフックを使って、 バッファ内容をこれ以上強調表示しないことを記録する。

after-revert-hook Variable
このノーマルフックは、revert-buffer-functionnilである 場合にのみ、変更内容を実際に挿入したあとにrevert-bufferが実行する。

フォントロック(font-lock)モードはこのフックを使って、 更新されたバッファ内容に対するフォントを再計算する。


Node:Buffers, Next:, Previous:Backups and Auto-Saving, Up:Top

バッファ

バッファ(buffer)は、編集するテキストを収めている Lispオブジェクトです。 バッファは、訪問しているファイルのテキストを保持するために使われますが、 ファイルを訪問していないバッファもあります。 一度に複数のバッファが存在してかまいませんが、 ある時点ではたった1つのバッファがカレントバッファ (current buffer)として区別されます。 ほとんどの編集コマンドは、カレントバッファの内容に作用します。 カレントバッファを含む各バッファは、ウィンドウに表示されることも されないこともあります。


Node:Buffer Basics, Next:, Up:Buffers

バッファの基本

Emacsの編集においてバッファとは、 異なる名前を持ち編集可能なテキストを保持するオブジェクトです。 バッファは、Lispプログラムには特別なデータ型として見えます。 バッファの内容は拡張可能な文字列であると考えることができます。 つまり、バッファのどの部分ででも挿入や削除を行えるのです。 See Text

Lispのバッファオブジェクトには、さまざまな情報が含まれています。 変数を介してプログラマが直接参照できる情報もあれば、 特別目的の関数のみを介して参照できる情報もあります。 たとえば、訪問しているファイルの名前は、変数を介して直接参照できますが、 ポイントの値は基本関数を介してのみ参照できます。

直接参照可能なバッファに固有の情報は、 バッファローカル(buffer-local)な変数束縛、 つまり、特定のバッファでのみ有効な変数に保持されています。 この機能により、各バッファでは特定の変数の値を優先できます。 ほとんどのメジャーモードでは、このようにして、 fill-columncomment-columnなどの変数を優先させます。 バッファローカルな変数とそれらに関する関数について詳しくは、 Buffer-Local Variablesを参照してください。

バッファで訪問しているファイルに関する関数や変数については、 Visiting FilesSaving Buffersを参照してください。 ウィンドウにバッファを表示することに関する関数や変数については、 Buffers and Windowsを参照してください。

bufferp object Function
この関数は、objectがバッファであればtを返し、 さもなければnilを返す。


Node:Current Buffer, Next:, Previous:Buffer Basics, Up:Buffers

カレントバッファ

一般に、Emacsセッションには多くのバッファがあります。 いつの時点でも、それらの1つをカレントバッファ (current buffer)として区別します。 バッファ内のテキストを検査したり変更する基本関数は 暗黙のうちにカレントバッファに作用するため、 ほとんどの編集はカレントバッファに対して行われます (see Text)。 通常、スクリーン上で選択されたウィンドウに表示されているバッファが カレントバッファですが、つねにそうとは限りません。 Lispプログラムでは、スクリーン上の表示は変えずに、 任意のバッファの内容を操作するために 一時的に当該バッファをカレントバッファにできます。

Lispプログラムでカレントバッファを指定するには、 set-bufferを呼び出します。 新たに指定し直すまで指定したバッファがカレントバッファであり続けます。

編集コマンドがエディタコマンドループへ戻ると、 コマンドループは、混乱を避けるために、選択されているウィンドウに 表示されているバッファをカレントバッファとします。 つまり、Emacsがコマンドを読むときにカーソルがあるバッファが コマンドが適用されるバッファです。 (See Command Loop。) したがって、set-bufferは、 ユーザーが編集できるように別のバッファへ切り替える方法にはなりません。 これには、Displaying Buffersで述べている関数を使う必要があります。

しかし、別のカレントバッファに替えるLisp関数では、 コマンドループがカレントバッファを あとで戻すということに依存してはいけません。 Emacs Lispで書かれた編集コマンドは、コマンドループに加えて 別のプログラムからも呼ばれます。 サブルーティンがカレントバッファを替えないほうが (それがサブルーティンの目的でなければ)、 呼び出し側にとっては便利です。 したがって、関数の実行が終るともとのカレントバッファに戻す フォームsave-current-buffersave-excursion(see Excursions)の内側で、 普通はset-bufferを使います。 例として、(説明文字列を簡略にして)コマンドappend-to-buffer のコードを示します。

(defun append-to-buffer (buffer start end)
  "Append to specified buffer the text of the region.
..."
  (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でもとのカレントバッファから 指定された(いまはカレント)バッファに文字列をコピーします。

内容を付加したバッファがどれかのウィンドウに表示されていると、 つぎに表示を更新したときに変更されたテキストが表示されます。 それ以外では、スクリーン上でただちには変更を見ることはできません。 コマンドの実行中にはバッファが一時的にカレントバッファになりますが、 それによりそのバッファが表示されるわけではありません。

バッファローカルな束縛を持つ変数を(letや関数の引数で) ローカルに束縛する場合には、ローカルな束縛の有効範囲の開始時と終了時には、 同じバッファが必ずカレントバッファであるようにします。 さもないと、あるバッファでは変数を束縛し、 別のバッファではその束縛を解除してしまうことがあります。 これには2つの方法があります。 単純な場合には、束縛の有効範囲内で カレントバッファが替わらないを確認します。 さもなければ、save-current-buffersave-excursionを使って、 始めにカレントバッファであったバッファが、 変数束縛が解除されるときにはつねにカレントバッファであるようにします。

set-bufferでもとのカレントバッファに戻すのでは信頼性がありません。 正しくないバッファがカレントバッファであるときに 中断が起きると戻せないからです。 してはいけないことをつぎに示します。

(let (buffer-read-only
      (obuf (current-buffer)))
  (set-buffer ...)
  ...
  (set-buffer obuf))

つぎのようにsave-current-bufferを使えば、 通常の評価に加えて、中断、エラー、throwも扱えます。

(let (buffer-read-only)
  (save-current-buffer
    (set-buffer ...)
    ...))

current-buffer Function
この関数はカレントバッファを返す。
(current-buffer)
     => #<buffer buffers.texi>

set-buffer buffer-or-name Function
この関数は、buffer-or-nameをカレントバッファにする。 この関数は現在選択されているウィンドウやその他のウィンドウに 当該バッファを表示しないので、ユーザーが当該バッファを見られるとは限らない。 しかし、Lispプログラムはいずれにしても当該バッファを操作できる。

この関数はbuffer-or-nameで指定されるバッファを返す。 buffer-or-nameが既存のバッファを指定しなければ、エラーを通知する。

save-current-buffer body... Special Form
マクロsave-current-bufferは、 カレントバッファの識別子を保存し、フォームbodyを評価し、 最後にもとのカレントバッファに戻す。 戻り値は、bodyの最後のフォームの値である。 throwやエラー(see Nonlocal Exits)による異常終了であっても カレントバッファは戻される。

save-current-bufferから抜けるときに、 もとのカレントバッファとして使われていたバッファが削除されていると、 もちろん、カレントバッファにはならない。 そのかわりに、抜けるまえにカレントバッファであったバッファが カレントバッファであり続ける。

with-current-buffer buffer body... Macro
マクロwith-current-bufferは、 カレントバッファの識別子を保存し、 bufferをカレントバッファにし、フォームbodyを評価し、 最後にもとのカレントバッファに戻す。 戻り値は、bodyの最後のフォームの値である。 throwやエラー(see Nonlocal Exits)による異常終了であっても カレントバッファは戻される。

with-temp-buffer body... Macro
マクロwith-temp-bufferは、 一時的なバッファをカレントバッファとして フォームbodyを評価する。 カレントバッファの識別子を保存し、 一時的なバッファを作成してそれをカレントバッファにし、 フォームbodyを評価し、 最後にもとのカレントバッファに戻すとともに一時的なバッファを削除する。

戻り値は、bodyの最後のフォームの値である。 最後のフォームとして(buffer-string)を使えば、 一時的なバッファの内容を返せる。

throwやエラー(see Nonlocal Exits)による異常終了であっても カレントバッファは戻される。

Writing to Fileswith-temp-fileも参照してください。


Node:Buffer Names, Next:, Previous:Current Buffer, Up:Buffers

バッファ名

各バッファには、文字列で一意な名前があります。 バッファに作用するほとんどの関数は、 引数としてバッファかバッファ名を受け付けます。 buffer-or-nameという名前の引数はこの種のものであり、 当該引数が文字列でもバッファでもないとエラーを通知します。 bufferという名前の引数は 実際のバッファオブジェクトである必要があり、名前ではだめです。

短命で一般にはユーザーが関心を示さないバッファの名前は空白で始まり、 コマンドlist-buffersbuffer-menuはそれらを表示しません。 さらに、空白で始まる名前のバッファでは、 アンドゥ情報の記録も最初は禁止してあります。 Undoを参照してください。

buffer-name &optional buffer Function
この関数は、bufferの名前を文字列で返す。 bufferを指定しないと、デフォルトはカレントバッファである。

buffer-namenilを返す場合、 bufferが削除されたことを意味する。 see Killing Buffers

(buffer-name)
     => "buffers.texi"

(setq foo (get-buffer "temp"))
     => #<buffer temp>
(kill-buffer foo)
     => nil
(buffer-name foo)
     => nil
foo
     => #<killed buffer>

rename-buffer newname &optional unique コマンド
この関数は、カレントバッファをnewnameと改名する。 newnameが文字列でなかったり、 当該名のバッファがすでに存在していると、エラーを通知する。 関数はnewnameを返す。

通常、newnameがすでに使われていると、 rename-bufferはエラーを通知する。 しかし、uniquenil以外であると、 newnameを未使用な名前に修正する。 対話的に呼び出した場合、数値前置引数を指定すると uniquenil以外になる。

このコマンドの1つの用途は、 バッファ*shell*を別の名前に改名して、 同じ*shell*という名前で別のシェルを作れるようにすることである。

get-buffer buffer-or-name Function
この関数は、buffer-or-nameで指定したバッファを返す。 buffer-or-nameが文字列であり、 そのような名前のバッファが存在しなければnilを返す。 buffer-or-nameがバッファであればそれ自身を返す。 (これは有用ではないので、普通、引数は名前である。) 例を示す。
(setq b (get-buffer "lewis"))
     => #<buffer lewis>
(get-buffer b)
     => #<buffer lewis>
(get-buffer "Frazzle-nots")
     => nil
Creating Buffersの関数get-buffer-createも参照。

generate-new-buffer-name starting-name Function
この関数は、新たなバッファ向けの一意な名前を返すが、バッファは作成しない。 名前はstarting-nameで始まり、 <...>で囲った数を追加することで、 どのバッファでも現在使っていない名前を作成する。 Creating Buffersの関連する関数generate-new-bufferを参照。


Node:Buffer File Name, Next:, Previous:Buffer Names, Up:Buffers

バッファファイル名

バッファファイル名(buffer file name)とは、 当該バッファで訪問しているファイルの名前です。 バッファでファイルを訪問していないときには、 バッファファイル名はnilです。 ほとんどの場面で、バッファ名は バッファファイル名の非ディレクトリ部分と同じですが、 バッファファイル名とバッファ名は別のものであり個別に設定できます。 See Visiting Files

buffer-file-name &optional buffer Function
この関数は、bufferで訪問しているファイルの 絶対ファイル名を返す。 bufferがファイルを訪問していなければ、 buffer-file-namenilを返す。 bufferを指定しないと、 デフォルトはカレントバッファである。
(buffer-file-name (other-buffer))
     => "/usr/user/lewis/manual/files.texi"

buffer-file-name Variable
このバッファローカルな変数は、 カレントバッファで訪問しているファイルの名前を保持する。 あるいは、ファイルを訪問していなければnilである。 これは恒久的にバッファローカルであり、 kill-local-variablesに影響されない。
buffer-file-name
     => "/usr/user/lewis/manual/buffers.texi"

他のさまざまなことを行わずにこの変数の値だけを変更することは危険である。 通常、set-visited-file-name(下記参照)を使うほうがよい。 バッファ名を変更するなどの重要でないことも行うが、 Emacsを混乱させないように本質的なことも行うからである。

buffer-file-truename Variable
このバッファローカルな変数は、 カレントバッファで訪問しているファイルの実名を保持する。 あるいは、ファイルを訪問していなければnilである。 これは恒久的にバッファローカルであり、 kill-local-variablesに影響されない。 see Truenames

buffer-file-number Variable
このバッファローカルな変数は、 カレントバッファで訪問しているファイルの ファイル番号とディレクトリ装置番号を保持する。 あるいは、ファイルを訪問していなければnilである。 これは恒久的にバッファローカルであり、 kill-local-variablesに影響されない。

この値は、通常、(filenum devnum)の形のリストである。 この数の対により、システム上のすべての参照可能なファイルを一意に識別できる。 これらについてより詳しくは、 File Attributesの関数file-attributesを参照。

get-file-buffer filename Function
この関数は、ファイルfilenameを訪問しているバッファを返す。 そのようなバッファが存在しなければnilを返す。 引数filenameは文字列であり、 展開(see File Name Expansion)してから すべてのバッファの訪問しているファイル名と比較する。
(get-file-buffer "buffers.texi")
    => #<buffer buffers.texi>

稀れな状況では、複数のバッファが同じ名前のファイルを訪問している場合がある。 そのような場合、この関数はバッファリストで最初にみつかったバッファを返す。

set-visited-file-name filename &optional no-query along-with-file コマンド
filenameが空でない文字列であると、 この関数はカレントバッファで訪問しているファイルの名前を filenameに変える。 (ファイルを訪問していないバッファでは、 当該バッファに訪問しているファイル名を指定する。) バッファをつぎに保存すると、指定した新たなファイルに保存される。 このコマンドは、バッファに変更済みと印を付ける。 変更まえの訪問しているファイルの内容とバッファ内容が一致していたとしても (Emacsにとっては) バッファ内容はfilenameの内容と一致しないからである。

filenamenilだったり空文字列であると、 『ファイルを訪問していない』ことにする。 この場合、set-visited-file-nameは、 当該バッファではファイルを訪問していないと印を付ける。

通常、この関数は、指定したファイルが既存の場合には ユーザーに確認をとる。 no-querynil以外であると、確認をとらない。

along-with-filenil以外であると、 それ以前に訪問していたファイルはfilenameと改名してあると仮定する。

関数set-visited-file-nameを対話的に呼び出すと、 ミニバッファでfilenameを問い合わせる。

list-buffers-directory Variable
このバッファローカルな変数は、 訪問しているファイル名を持たないバッファに対して、 バッファ一覧において訪問しているファイル名を表示する部分に 表示する文字列を指定する。 diredのバッファはこの変数を使う。


Node:Buffer Modification, Next:, Previous:Buffer File Name, Up:Buffers

バッファの変更

Emacsは、各バッファごとに当該バッファのテキストを変更したかどうかを 記録する変更フラグ(modified flag)と呼ばれるフラグを保持しています。 バッファの内容が変わるたびにこのフラグはtに設定され、 保存するたびにnilに設定されます。 つまり、このフラグは未保存の変更があるかどうかを表します。 このフラグの値は通常モード行(see Mode Line Variables)に表示され、 保存(see Saving Buffers)と 自動保存(see Auto-Saving)を制御します。

このフラグを明示的に設定するLispプログラムもあります。 たとえば、関数set-visited-file-nameはこのフラグをtに設定します。 ファイルを訪問してから変更していなくても、 バッファのテキストが新たな訪問しているファイルとは一致しないからです。

バッファの内容を変更する関数についてはTextに述べてあります。

buffer-modified-p &optional buffer Function
この関数は、最後にファイルから読み込んだり保存してから バッファbufferが変更されていればtを返し、 さもなければnilを返す。 bufferを指定しないとカレントバッファを調べる。

set-buffer-modified-p flag Function
この関数は、flagnil以外であれば カレントバッファは変更されていると印を付け、 nilならば未変更であると印を付ける。

この関数を呼び出した別の効果として、 カレントバッファのモード行を無条件に再表示する。 実際、関数force-mode-line-updateはつぎのようにしている。

(set-buffer-modified-p (buffer-modified-p))

not-modified コマンド
このコマンドは、カレントバッファを未変更であり 保存する必要がないと印を付ける。 前置引数を指定すると、バッファに変更されていると印を付け、 以降の適当な場面で保存される。

エコー領域にメッセージを表示するので、 プログラムからこの関数を使わないこと。 かわりにset-buffer-modified-pを使う(上記)。

buffer-modified-tick &optional buffer Function
この関数は、bufferの変更回数を返す。 変更回数はバッファを変更するたびに増やされる。 buffernilであると(あるいは省略すると)、 カレントバッファを使う。


Node:Modification Time, Next:, Previous:Buffer Modification, Up:Buffers

更新時刻の比較

ファイルを訪問してそのバッファで変更したとします。 そのあいだに、ディスク上の当該ファイル自身も変更されたとします。 ここでバッファを保存すると、ファイルの変更内容を上書きしてしまいます。 たしかにこれを望む場合もあるでしょうが、 普通は重要な情報を失うことになります。 そのため、Emacsは、ファイルに保存するまえに、 以下に述べる関数を用いてファイルの更新時刻を検査します。

verify-visited-file-modtime buffer Function
この関数は、bufferに記録してある 訪問しているファイルの更新時刻と、 オペレーティングシステムが記録している ファイルの実際の更新時刻を比較する。 Emacsが当該ファイルを訪問したり保存してから 他のプロセスが当該ファイルに書いていない限り、 2つの時刻は同じはずである。

実際の更新時刻とEmacsに記録している更新時刻が同じならばtを返し、 さもなければnilを返す。

clear-visited-file-modtime Function
この関数は、カレントバッファで訪問しているファイルの 最終更新時刻の記録を破棄する。 その結果、つぎにこのバッファを保存しようとしても、 ファイルの更新時刻のと不一致を報告しない。

この関数は、set-visited-file-nameや 変更されたファイルを上書きしないためのテストを行わない例外的な場面で 呼び出される。

visited-file-modtime Function
この関数は、 バッファに記録されているファイルの最終更新時刻を (high . low)の形のリストで返す。 (これはfile-attributesが時刻を返すために使う形と同じである。 File Attributesを参照。)

set-visited-file-modtime &optional time Function
この関数は、timenil以外であるときには、 バッファに記録してあるファイルの最終更新時刻を timeで指定された時刻にする。 さもなければ、訪問しているファイルの最終更新時刻にする。

timenilでないときには、 (high . low)(high low)の形であること。 いずれの場合も、2つの整数は時刻の16ビットを保持する。

この関数は、ファイルから普通に読み込んだのではないバッファや ファイル自体が明確な理由で変更された場合に有用である。

ask-user-about-supersession-threat filename Function
この関数は、ファイルfilenameを訪問している廃れたバッファを 変更しようとしたときにどのように処理すべきかをユーザーに問い合わせる ために用いる。 廃れたバッファ(obsolete buffer)とは、 未変更のバッファではあるが、対応するディスク上のファイルが バッファの最終更新時刻よりも新しいものである。 つまり、別のプログラムが当該ファイルを変更した可能性があることを意味する。

ユーザーの応答に依存して、関数は正常に戻る。 その場合、バッファは変更できる。 あるいは、データ(filename)を付けて エラーfile-supersessionを通知する。 その場合、バッファの変更は許されない。

この関数は、適切な場面でEmacsが自動的に呼び出す。 これを再定義することでEmacsをカスタマイズできるようにしている。 標準定義についてはファイルuserlock.elを参照。 File Locksのファイルロック機構も参照。


Node:Read Only Buffers, Next:, Previous:Modification Time, Up:Buffers

読み出し専用バッファ

バッファが読み出し専用(read-only)であると、 スクロールしたりナロイングしてその内容を眺めることはできますが、 その内容は変更できません。

読み出し専用バッファは、2種類の場面で使われます。

buffer-read-only Variable
このバッファローカルな変数は、 バッファが読み出し専用であるかどうかを指定する。 この変数がnil以外であると、バッファは読み出し専用である。

inhibit-read-only Variable
この変数がnil以外であると、 読み出し専用バッファや読み出し専用文字を変更できる。 バッファ内の読み出し専用文字とは (テキスト属性やオーバレイ属性の) 属性read-onlynil以外の文字である。 テキスト属性について詳しくは、see Special Properties。 重ね合わせとそれらの属性について詳しくは、see Overlays

inhibit-read-onlytであると、 すべての文字の属性read-onlyは効果を失う。 inhibit-read-onlyがリストであると、 文字の属性read-onlyが(eqで比較して) リストのメンバであると効果を失う。

toggle-read-only コマンド
このコマンドは、カレントバッファが読み出し専用かどうかを変更する。 対話的な使用を意図しており、プログラムからは使わないこと。 プログラムの任意の箇所で、読み出し専用フラグを オンにしたいかオフにしたいかを読者は知っているはずであり、 そうすれば、読者はbuffer-read-onlytnilの正しい値に明示的に設定できる。

barf-if-buffer-read-only Function
この関数は、カレントバッファが読み出し専用であると エラーbuffer-read-onlyを通知する。 カレントバッファが読み出し専用であるときに エラーを通知する別の方法については、see Interactive Call


Node:The Buffer List, Next:, Previous:Read Only Buffers, Up:Buffers

バッファリスト

バッファリスト(buffer list)は、 すべてのバッファのリストです。 バッファを作成すると当該バッファはこのリストに追加され、 削除するとこのリストから取り除かれます。 リスト内のバッファの順序は、各バッファが選択されているウィンドウに どの程度最近に表示されたかを主な基準にしています。 バッファが選択されるとリストの先頭に移動し、 隠されると(下記のbury-bufferを参照)末尾に移動します。 other-bufferをはじめとするいくつかの関数が、この順序を使います。 ユーザーに表示するバッファ一覧もこの順序を反映しています。

Emacs基本バッファリストに加えて、 各フレームには独自のバッファリストがあります。 そのリストでは、 当該フレームでもっとも最近に選択されたバッファから順に 当該フレームで選択されたバッファが先にきます。 (この順番は、フレームのフレームパラメータbuffer-listに入っている。 Window Frame Parametersを参照。) 当該フレームで選択されたことがないバッファは、 Emacs基本バッファリストでの順にうしろに続きます。

buffer-list &optional frame Function
この関数は、空白で始まる名前のバッファを含めて、 すべてのバッファを含んだバッファリストを返す。 要素は実際にバッファであり、それらの名前ではない。

frameがフレームであると、 この関数はフレームframeのバッファリストを返す。 framenilであるとEmacs基本バッファリストを使う。

(buffer-list)
     => (#<buffer buffers.texi>
         #<buffer  *Minibuf-1*> #<buffer buffer.c>
         #<buffer *Help*> #<buffer TAGS>)

;; ミニバッファの名前は空白で始まることに注意
(mapcar (function buffer-name) (buffer-list))
    => ("buffers.texi" " *Minibuf-1*"
        "buffer.c" "*Help*" "TAGS")

buffer-listが返すリストはbuffer-listが構築したものであり、 Emacsの内部データ構造ではなく、 それを変更してもバッファの順序には影響しません。 フレーム独立なバッファリスト内のバッファ順序を変更するには、 つぎのような簡単な方法があります。

(defun reorder-buffer-list (new-list)
  (while new-list
    (bury-buffer (car new-list))
    (setq new-list (cdr new-list))))

この方法を使えば、どんな順序でもリストに指定でき、 しかも、バッファを失ったり正しくないバッファを 追加してしまう危険はありません。

フレームのバッファリストの順序や値を変更するには、 modify-frame-parameters(see Parameter Access)で、 フレームのフレームパラメータbuffer-listに設定します。

other-buffer &optional buffer visible-ok frame Function
この関数は、バッファリストからbuffer以外の最初のバッファを返す。 通常、当該バッファは、bufferを除いて (frameか現在選択されているフレームで) もっとも最近に選択されたバッファである。 空白で始まる名前のバッファは完全に除外する。

bufferを指定しないと(あるいはバッファでないと)、 other-bufferは、選択されているフレームのバッファリストの中から 可視フレームのどのウィンドウにも表示されていない最初のバッファを返す。

framenil以外のパラメータbuffer-predicateがあると、 other-bufferは当該述語を使って どのバッファを考慮に入れるかを決定する。 各バッファについて当該述語を1回呼び出し、 その値がnilであると当該バッファを無視する。 see Window Frame Parameters

visible-oknilであると、 other-bufferは可視フレームのいずれかのウィンドウに 表示されているバッファを可能な限り返さないようにする。 visible-oknil以外であると、 バッファが表示されているかどうかは関係ない。

適当なバッファが存在しない場合には、 バッファ*scratch*を(必要ならば作成して)返す。

bury-buffer &optional buffer-or-name コマンド
この関数は、バッファリストの他のバッファの順序は変えずに buffer-or-nameを末尾に置く。 この結果、当該バッファは、other-bufferが返す候補としては もっとも可能性が低くなる。

bury-bufferは、 Emacsのフレーム独立なバッファリストに加えて、 各フレームのパラメータbuffer-listも操作する。 したがって、指定したバッファは、 (buffer-list frame)(buffer-list nil)の いずれの値でも最後になる。

buffer-or-namenilであるか省略すると、 カレントバッファを最後尾に置くことを意味する。 さらに、当該バッファが選択されているウィンドウに表示されていると、 そのウィンドウでは(other-bufferで得られる) 別のバッファに切り替わる。 当該バッファが別のウィンドウにも表示されている場合、 その表示は替わらない。

すべてのウィンドウに表示している特定のバッファを置き換えるには、 replace-buffer-in-windowsを使う。 see Buffers and Windows


Node:Creating Buffers, Next:, Previous:The Buffer List, Up:Buffers

バッファの作成

本節では、バッファを作成するための2つの基本関数を説明します。 get-buffer-createは、指定した名前のバッファが 存在しなければバッファを作成します。 generate-new-bufferは、つねに新たなバッファを作成し、 それに一意な名前を与えます。

バッファを作成するために読者が使える他の関数には、 with-output-to-temp-buffer(see Temporary Displays)、 create-file-buffer(see Visiting Files)があります。 サブプロセスを開始してもバッファを作ります(see Processes)。

get-buffer-create name Function
この関数は、nameという名前のバッファを返す。 その名前のバッファが存在すれば、当該バッファを返す。 さもなければ、新たなバッファを作成する。 バッファはカレントバッファにはならない。 この関数は、どのバッファがカレントバッファであるかは変更しない。

nameが文字列でないとエラーを通知する。

(get-buffer-create "foo")
     => #<buffer foo>

新たなバッファのメジャーモードは基本(fundamental)モードに設定される。 変数default-major-modeは、より高いレベルで処理される。 see Auto Major Mode

generate-new-buffer name Function
この関数は、新たに作成した空のバッファを返すが、 それをカレントバッファにはしない。 nameという名前のバッファが存在しなければ、 新たなバッファの名前はnameである。 その名前が使われている場合には、 この関数は、nを整数として<n>の形の接尾辞を nameに付加する。 nを2から始めて順に使える名前を探す。

nameが文字列でないとエラーを通知する。

(generate-new-buffer "bar")
     => #<buffer bar>
(generate-new-buffer "bar")
     => #<buffer bar<2>>
(generate-new-buffer "bar")
     => #<buffer bar<3>>

新たなバッファのメジャーモードは基本(fundamental)モードに設定される。 変数default-major-modeは、より高いレベルで処理される。 see Auto Major ModeBuffer Namesの関連する関数generate-new-buffer-nameを参照。


Node:Killing Buffers, Next:, Previous:Creating Buffers, Up:Buffers

バッファの削除

バッファを削除するとは、Emacsに当該バッファの名前を忘れさせ、 それが使っていた場所を他の目的に使えるようにすることです。

削除されたバッファを表すバッファオブジェクトは、 それを指すものが存在する限り存在し続けますが、 それをカレントバッファにしたり表示できないように特別な印が付いています。 削除されたバッファの識別子は残っているので、 異なる2つのバッファを削除しても、 eqに関する限りそれらは区別できるのです。

カレントバッファやウィンドウに表示しているバッファを削除すると、 そのかわりにEmacsは別のバッファを選択したり表示します。 つまり、バッファを削除すると一般にはカレントバッファが 替わりうることを意味します。 したがって、バッファを削除するときには、 (削除するバッファがカレントバッファではないことがわかっていない限り) カレントバッファを替える可能性についてあらかじめ注意しておく必要があります。 See Current Buffer

複数の間接バッファの基底バッファであるバッファを削除すると、 間接バッファも自動的に削除されます。

削除されたバッファのbuffer-namenilです。 これを使えばバッファが削除されているかどうか調べられます。

(defun buffer-killed-p (buffer)
  "Return t if BUFFER is killed."
  (not (buffer-name buffer)))

kill-buffer buffer-or-name コマンド
この関数はバッファbuffer-or-nameを削除し、 当該バッファが使用していたすべてのメモリを他の目的に使えるように解放したり、 オペレーティングシステムに返すために解放する。 この関数はnilを返す。

当該バッファをprocess-bufferとしているすべてのプロセスに シグナルSIGHUPを送る。 このシグナルは、通常、プロセスを終了させる。 (SIGHUPの基本的な意味は、接続回線が切断されたである。) see Deleting Processes

当該バッファがファイルを訪問していて、かつ、未保存の変更があれば、 kill-bufferは当該バッファを削除するまえにユーザーに確認をとる。 確認をとらないようにするには、kill-bufferを呼び出すまえに バッファの変更フラグをクリアしておく。 see Buffer Modification

削除済みのバッファを削除してもなんの効果もない。

(kill-buffer "foo.unchanged")
     => nil
(kill-buffer "foo.changed")

---------- Buffer: Minibuffer ----------
Buffer foo.changed modified; kill anyway? (yes or no) yes
---------- Buffer: Minibuffer ----------

     => nil

kill-buffer-query-functions Variable
未保存の変更を確認したあとで、kill-bufferは、 リストkill-buffer-query-functionsの関数を現れる順に 引数なしで呼び出す。 これらの関数が呼び出されるときには、 削除対象のバッファがカレントバッファである。 これらの関数でさまざまな非標準的な理由から ユーザーの確認をとることが目的である。 いずれかがnilを返すと、kill-bufferはバッファを削除しない。

kill-buffer-hook Variable
これは、kill-bufferが問い合わせをすべて完了し バッファを実際に削除する直前に実行されるノーマルフックである。 フック関数を実行するときには、削除対象のバッファがカレントバッファである。 see Hooks

buffer-offer-save Variable
この変数が特定のバッファでnil以外であると、 save-buffers-kill-emacssave-some-buffersに対して ファイルを訪問しているバッファと同様に 当該バッファを保存する機会を与えるように指示する。 変数buffer-offer-saveに 設定すると自動的にバッファローカルになる。


Node:Indirect Buffers, Previous:Killing Buffers, Up:Buffers

間接バッファ

間接バッファ(indirect buffer)は、 間接バッファの基底バッファ(base buffer)と呼ばれる 他のバッファのテキストを共有します。 ある意味で、バッファにおいて ファイルのシンボリックリンクに相当するものです。 基底バッファそのものは間接バッファであってはなりません。

間接バッファのテキストは、その基底バッファのテキストとつねに同一です。 どれかを編集して変更すると、別のものでただちに見えます。 これには、文字そのものに加えてテキスト属性も含みます。

しかし、それ以外に関しては、間接バッファと その基底バッファは完全に別のものです。 別の名前を持ち、ポイントの値も別であり、異なったナロイングをでき、 (いずれかのバッファでテキストを挿入したり削除すると マーカと重ね合わせは再配置されるが)マーカやオーバレイも異なり、 異なるメジャーモードを持ち、バッファローカルな変数も異なります。

間接バッファはファイルを訪問できませんが、その基底バッファでは訪問できます。 間接バッファを保存しようとすると、実際にはその基底バッファを保存します。

間接バッファを削除しても、その基底バッファには影響ありません。 基底バッファを削除すると、その間接バッファを実質的には削除することになり、 間接バッファをカレントバッファにはけっしてできなくなります。

make-indirect-buffer base-buffer name コマンド
base-bufferを基底バッファとするnameという名前の 間接バッファを作成する。 引数base-bufferは、バッファか文字列である。

base-bufferが間接バッファであると、 その基底バッファを新たなバッファの基底バッファとして用いる。

buffer-base-buffer buffer Function
この関数はbufferの基底バッファを返す。 bufferが間接バッファでなければ、値はnilである。 さもなければ、値は間接バッファではない別のバッファである。


Node:Windows, Next:, Previous:Buffers, Up:Top

ウィンドウ

本章では、Emacsのウィンドウに関したほとんどの関数と変数について述べます。 ウィンドウにどのようにテキストが表示されるかに関しては、 Displayを参照してください。


Node:Basic Windows, Next:, Up:Windows

Emacsウィンドウの基本概念

Emacsのウィンドウ(window)は、 バッファを表示するスクリーン上の物理的な領域のことです。 この用語は、Emacs Lispにおいて、当該物理領域を表す Lispオブジェクトを意味するためにも使います。 どちらの意味かは文脈から明らかなはずです。

Emacsではウィンドウをフレームにまとめています。 フレームは、Emacsが使えるスクリーンの領域を表します。 各フレームには少なくとも1つのウィンドウがつねにありますが、 フレームは上下や左右に重なり合わない複数のEmacsのウィンドウに分割できます。

ある時点では、各フレームにはフレームの選択されているウィンドウと 区別されるウィンドウがたった1つだけあります。 フレームのカーソルはそのようなウィンドウに現れます。 ある時点では、1つのフレームが選択されているフレームであり、 当該フレームで選択されているウィンドウが選択されているウィンドウです。 選択されているウィンドウのバッファが、 (set-bufferを使った場合を除いて)普通はカレントバッファです。 See Current Buffer

実用上、ウィンドウは、それがフレームに表示されている期間だけ存在します。 フレームからいったん取りさると、(ウィンドウへの参照が残っているとしても) ウィンドウは実質的には削除され使えません。 保存したウィンドウ構成を復元する以外に、 スクリーンから消えたウィンドウを戻す方法はありません。 (see Deleting Windows。)

各ウィンドウにはつぎの属性があります。

複数のバッファを同時に見られるようにユーザーは複数のウィンドウを作ります。 さまざまな理由でLispライブラリは複数のウィンドウを使いますが、 そのほとんどは、関連する情報を表示するためです。 たとえば、rmailでは、あるウィンドウのサマリバッファで移動すると、 別のウィンドウでは対応するメッセージを表示します。

Emacsにおける『ウィンドウ』の意味は、 Xのような汎用目的のウィンドウシステムにおける意味に似ていますが、 同一ではありません。 Xウィンドウシステムは、スクリーン上にXのウィンドウを配置します。 Emacsは、1つか複数のXのウィンドウをフレームとして使い、 それらをEmacsのウィンドウに分割します。 文字端末でEmacsを使うと、 Emacsは端末のクリーン全体を1つのフレームとして扱います。

ほとんどのウィンドウシステムは、任意に重ね合わさったウィンドウを扱えます。 対照的に、Emacsのウィンドウはタイル型です。 つまり、互いに重なり合うことはなく、 スクリーンやフレームの全面に敷き詰められます。 Emacsが新たなウィンドウを作成する方法や ウィンドウサイズの変更方法に起因するのですが、 Emacsのフレームを任意の形にウィンドウで敷き詰めることは、 実際には必ずしも可能であるとは限りません。 Splitting WindowsとSee Size of Window

ウィンドウのバッファの内容がどのようにウィンドウに表示されるかについては、 See Display

windowp object Function
この関数は、objectがウィンドウであればtを返す。


Node:Splitting Windows, Next:, Previous:Basic Windows, Up:Windows

ウィンドウの分割

ここで述べる関数は、ウィンドウを2つに分割するための基本関数です。 上位レベルの2つの関数、pop-to-bufferdisplay-bufferも ウィンドウを分割しますが、 つねに分割するとは限りません(see Displaying Buffers)。

ここに述べる関数は、引数にはバッファを受け付けません。 分割されたウィンドウの2つの『部分』には、分割前に表示されていたのと 同じバッファが始めは表示されます。

split-window &optional window size horizontal コマンド
この関数はwindowを2つのウィンドウに分割する。 もとのウィンドウwindowは、選択されているウィンドウであり続けるが、 以前のスクリーン領域の一部を占めるだけである。 残りの部分は新たに作成されたウィンドウが占め、 そのウィンドウがこの関数の値として返される。

horizontalnil以外であると、windowは左右に分かれる。 もとのウィンドウwindowは左端のsizeコラムに留まり、 残りのコラムは新たなウィンドウに与えられる。 さもなければ、ウィンドウは上下に分かれ、 windowは上側のsize行に留まり、 残りの行は新たなウィンドウに与えられる。 したがって、もとのウィンドウは左側か上側にあり、 新たなウィンドウは右側か下側にある。

windowを省略したりnilであると、 選択されているウィンドウを分割する。 sizeを省略したりnilであると、 windowを均等に分ける。 (余分な行は新たなウィンドウに与える。) split-windowが対話的に呼び出されると、 すべての引数はnilである。

つぎの例では、50行×80コラムのスクリーン上の1つのウィンドウを分割する。

(setq w (selected-window))
     => #<window 8 on windows.texi>
(window-edges)          ; 順に
     => (0 0 80 50)     ;   左端-上端-右端-下端

;; 作成したウィンドウを返す
(setq w2 (split-window w 15))
     => #<window 28 on windows.texi>
(window-edges w2)
     => (0 15 80 50)    ; 下側のウィンドウの上端は15行目
(window-edges w)
     => (0 0 80 15)     ; 上側のウィンドウ

スクリーンはつぎのようになる。

   ┌──────┐
   │      │ 0行目
   │   w  │
   │      │
   ├──────┤
   │      │15行目
   │   w2 │
   │      │
   └──────┘
           50行目
コラム0         コラム80

つぎに上側のウィンドウを左右に分割する。

(setq w3 (split-window w 35 t))
     => #<window 32 on windows.texi>
(window-edges w3)
     => (35 0 80 15)  ; 左端は35コラム目
(window-edges w)
     => (0 0 35 15)   ; 右端は35コラム目
(window-edges w2)
     => (0 15 80 50)  ; 下側のウィンドウは未変更

スクリーンはつぎのようになる。

   コラム35
   ┌─┬────┐
   │ │    │ 0行目
   │w│ w3 │
   │ │    │
   ├─┴────┤
   │      │15行目
   │   w2 │
   │      │
   └──────┘
           50行目
コラム0         コラム80

通常、Emacsは左右に並んだウィンドウの境界を スクロールバー(see Scroll Bars)か 文字|で表す。 表示テーブルで境界に別の文字を指定できる。 Display Tablesを参照。

split-window-vertically size コマンド
この関数は、選択されているウィンドウを上下に2つに分割する。 上側が選択されているウィンドウのままで、size行の大きさになる。 (sizeが負であると、下側のウィンドウが- size行になり、 上側のウィンドウは残りになる。 しかし、それでも上側が選択されているウィンドウである。)

この関数はsplit-windowの単なるインターフェイスである。 その完全な関数定義はつぎのとおりである。

(defun split-window-vertically (&optional arg)
  "Split current window into two windows, ..."
  (interactive "P")
  (split-window nil (and arg (prefix-numeric-value arg))))

split-window-horizontally size コマンド
この関数は、選択されているウィンドウを左右に2つに分割し、 選択されているウィンドウにはsizeコラム残す。

この関数はsplit-windowの単なるインターフェイスである。 split-window-horizontallyの完全な関数定義は (説明文字列を除けば)つぎのとおりである。

(defun split-window-horizontally (&optional arg)
  "Split selected window into two windows, side by side..."
  (interactive "P")
  (split-window nil (and arg (prefix-numeric-value arg)) t))

one-window-p &optional no-mini all-frames Function
この関数は、ウィンドウがたった1つしかなければnil以外を返す。 引数no-mininil以外であると、 ミニバッファが活性であってもそれを数えないことを意味する。 さもなければ、ミニバッファが活性であればそれも総ウィンドウ個数に数えて 1と比較する。

引数all-framesは、どのフレームを対象にするかを指定する。 指定できる値とその意味はつぎのとおりである。

nil
選択されているフレームのウィンドウに加えて、 ミニバッファがどこに置かれていようと 当該フレームが使っているミニバッファを数える。
t
既存のすべてのフレームのウィンドウを数える。
visible
すべての可視フレームのすべてのウィンドウを数える。
0
すべての可視フレームやアイコンになっているフレームの すべてのウィンドウを数える。
その他
選択されているフレームだけでウィンドウを正確に数える。


Node:Deleting Windows, Next:, Previous:Splitting Windows, Up:Windows

ウィンドウの削除

ウィンドウを削除するある種の関数を呼び出して ウィンドウを削除しない限り、 ウィンドウはそのフレームに表示され続けます。 削除されたウィンドウがスクリーンに現れることはありませんが、 それを参照するものがある限りLispオブジェクトととしては 存在し続けます。 保存したウィンドウ構成(see Window Configurations)を復元する以外には、 ウィンドウの削除は取り消せません。 ウィンドウ構成を復元すると、 その構成に含まれないウィンドウはすべて削除されます。

ウィンドウを削除すると、それが使っていた場所は 近接する兄弟ウィンドウの1つに与えられます。

window-live-p window Function
この関数は、windowが削除されているとnilを返し、 さもなければtを返す。

警告: 削除されたウィンドウを正しいものとして使うと、 誤った情報や重大なエラーを引き起こす。

delete-window &optional window コマンド
この関数は、ディスプレイからwindowを取りさり、nilを返す。 windowを省略すると、選択されているウィンドウを削除する。 delete-windowを呼び出したときにたった1つのウィンドウしかないと エラーを通知する。

delete-other-windows &optional window コマンド
この関数は、windowのフレームにある他のウィンドウを削除して windowを当該フレームで唯一のウィンドウにする。 windowを省略したりnilであると、 選択されているウィンドウをデフォルトで使う。

これはnilを返す。

delete-windows-on buffer &optional frame コマンド
この関数は、bufferを表示しているすべてのウィンドウを削除する。 bufferを表示しているウィンドウがなければなにもしない。

delete-windows-onはフレームを1つ1つ処理する。 フレームに異なるバッファを表示しているウィンドウが複数ある場合、 それらのうちでbufferを表示しているものを削除し、 他のものは空いた領域を埋めるために拡張される。 あるフレームのすべてのウィンドウ(たった1つのウィンドウである場合も含む) がbufferを表示している場合、当該フレームは、 other-bufferで選ばれる別のバッファを表示する 1つのウィンドウだけになる。 see The Buffer List

引数frameは、どのフレームを対象にするかを指定する。 この関数は、すべてのウィンドウを走査する他の関数と同じようには frameを使わない。 特に、tnilの値の意味は他の関数とは逆である。 以下に詳細を示す。

  • nilであると、すべてのフレームを対象にする。
  • tであると、選択されているフレームを対象にする。
  • visibleであると、すべての可視フレームを対象にする。
  • 0であると、すべての可視フレームやアイコンになっているフレームを対象にする。
  • フレームであると、当該フレームを対象にする。

この関数はつねにnilを返す。


Node:Selecting Windows, Next:, Previous:Deleting Windows, Up:Windows

ウィンドウの選択

ウィンドウを選択すると、当該ウィンドウのバッファがカレントバッファになり、 カーソルがそのウィンドウに現れます。

selected-window Function
この関数は、選択されているウィンドウを返す。 カーソルが表示され多くのコマンドが作用するウィンドウがそれである。

select-window window Function
この関数は、windowを選択されているウィンドウにする。 すると、カーソルは(再表示すると)windowに現れる。 windowに表示されているバッファがただちにカレントバッファになる。

戻り値はwindowである。

(setq w (next-window))
(select-window w)
     => #<window 65 on windows.texi>

save-selected-window forms... Macro
このマクロは、選択されているウィンドウを記録して、 formsを順に実行し、 もとの選択されているウィンドウに戻す。

このマクロは、ウィンドウサイズ、配置、内容に関して いっさいなにも保存したり復元しないので、 formsがそれらを変更するとその変更は持続する。

ある時点で、各フレームにはフレームの選択されているウィンドウがある。 このマクロは、選択されているウィンドウだけを保存し、 他のフレームについてはなにも保存しない。 formsが別のフレームを選択して そのフレームの選択されているウィンドウを変更すると、その変更は持続する。

以下の関数は、さまざま条件でスクリーン上のウィンドウの1つを選びます。

get-lru-window &optional frame Function
この関数は、もっとも昔に『使われた』 (つまり選択されていた)ウィンドウを返す。 選択されているウィンドウはつねにもっとも最近に使われたウィンドウである。

ウィンドウがたった1つであると、 選択されているウィンドウが もっとも昔に使われたウィンドウであることもありうる。 新たに作成されたウィンドウは、選択されるまではもっとも昔に 使われたウィンドウになる。 ミニバッファ用ウィンドウは候補にはならない。

引数frameは、どのウィンドウを対象とするかを制御する。

  • nilであると、選択されているフレームのウィンドウを対象とする。
  • tであると、すべてのフレームのウィンドウを対象とする。
  • visibleであると、 すべての可視フレームのウィンドウを対象とする。
  • 0であると、すべての可視フレームやアイコンになっているフレーム のウィンドウを対象にする。
  • フレームであると、当該フレームのウィンドウを対象にする。

get-largest-window &optional frame Function
この関数は、もっとも大きな領域(高さ×幅)のウィンドウを返す。 左右に並んだウィンドウがなければ、 これがもっとも行数を持つウィンドウである。 ミニバッファ用ウィンドウは候補にはならない。

同じ大きさのウィンドウが2つある場合、 この関数は、選択されているウィンドウから始めて ウィンドウの巡回順序(次節参照)で最初のウィンドウを返す。

引数frameは、ウィンドウのどのような集まりを対象にするかを指定する。 うえのget-lru-windowを参照。


Node:Cyclic Window Ordering, Next:, Previous:Selecting Windows, Up:Windows

ウィンドウの巡回順序

つぎのウィンドウを選択するためにコマンドC-x oother-window)を 使うと、スクリーン上のすべてのウィンドウをある巡回順序で巡ります。 ウィンドウのある構成において、この順序は変わりません。 これをウィンドウの巡回順序(cyclic ordering of windows)と呼びます。

この順番は一般に上から下、左から右になります。 しかし、ウィンドウを分割した順番に依存して、 下や右が最初になることもあります。

最初に上下に分割してつぎに左右に分割すると、 順番は、フレームの上側で左から右、フレームのその下では左から右 といった具合になります。 最初に左右に分割すると、 順番は、フレームの左側で上から下といった具合になります。 一般に、ウィンドウ木のあるレベルで分割された各兄弟の中では、 順番は、左から右、あるいは、上から下になります。

next-window &optional window minibuf all-frames Function
この関数は、ウィンドウの巡回順序においてwindowのつぎの ウィンドウを返す。 これは、windowが選択されているときに C-x oが選択するであろうウィンドウである。 windowが唯一の可視ウィンドウであると、 この関数はwindowを返す。 windowを省略すると、デフォルトは選択されているウィンドウである。

引数minibufの値は、ミニバッファを ウィンドウの順序に含めるかどうかを決定する。 minibufnilであると、 ミニバッファが活性であるときにはミニバッファを含める。 これはC-x oのふるまいである。 (ミニバッファが使われているあいだは、 ミニバッファ用ウィンドウは活性である。 see Minibuffers。)

minibuftであると、 ミニバッファが活性でなくても巡回順序にミニバッファ用ウィンドウを含める。

minibuftでもnilでもないと、 活性であってもミニバッファ用ウィンドウを含めない。

引数all-framesは、どのフレームを対象にするかを指定する。 可能な値とその意味を以下に示す。

nil
windowのフレームのすべてのウィンドウに加えて、 ミニバッファがどこに置かれていようと 当該フレームが使っているミニバッファを対象にする。
t
既存のすべてのフレームのすべてのウィンドウを対象にする。
visible
すべての可視フレームのすべてのウィンドウを対象にする。 (結果が有用であるためには、可視フレームにwindowがあること)
0
すべての可視フレームやアイコンになっているフレームの すべてのウィンドウを対象にする。
その他
windowのフレームだけのウィンドウを正確に対象にする。

つぎの例では、2つのウィンドウがあり、 どちらもバッファwindows.texiを表示していると仮定する。

(selected-window)
     => #<window 56 on windows.texi>
(next-window (selected-window))
     => #<window 52 on windows.texi>
(next-window (next-window (selected-window)))
     => #<window 56 on windows.texi>

previous-window &optional window minibuf all-frames Function
この関数は、ウィンドウの巡回順序においてwindowのまえの ウィンドウを返す。 他の引数は、next-windowと同様に、 どのようなウィンドウを巡回に含めるかを指定する。

other-window count コマンド
この関数は、ウィンドウの巡回順序においてcount番目うしろの ウィンドウを選択する。 countが負であると、巡回順序において -count番目まえのウィンドウに戻る。 この関数はnilを返す。

対話的に呼び出すと、countは数値前置引数である。

walk-windows proc &optional minibuf all-frames Function
この関数は、各ウィンドウごとに当該ウィンドウを唯一の引数として procを呼び出してすべてのウィンドウを巡る。

省略可能な引数minibufall-framesは、 走査するウィンドウの集まりを指定する。 詳しくは上記のnext-windowを参照。


Node:Buffers and Windows, Next:, Previous:Cyclic Window Ordering, Up:Windows

バッファとウィンドウ

本節では、ウィンドウを調べたり、 正確に制御してウィンドウにバッファを表示する低レベルの関数について述べます。 使用するウィンドウを探したりそれにバッファを指定する関連する関数については、 そこに述べた関数は本節の関数より簡単に使えますが、 それらはウィンドウを選んだり作ったりするときに発見的手法を使います。 完全に制御する必要があるときには、本節の関数を使います。

set-window-buffer window buffer-or-name Function
この関数は、windowの内容としてbuffer-or-nameを表示するようにする。 この関数はnilを返す。 これは、ウィンドウに表示するバッファを切り替える もっとも基本の基本関数であり、 他の切り替え関数はこの関数を呼び出す。
(set-window-buffer (selected-window) "foo")
     => nil

window-buffer &optional window Function
この関数は、windowに表示しているバッファを返す。 windowを省略すると、この関数は選択されているウィンドウのバッファを返す。
(window-buffer)
     => #<buffer windows.texi>

get-buffer-window buffer-or-name &optional all-frames Function
この関数は、現在buffer-or-nameを表示しているウィンドウを返す。 そのようなウィンドウがなければnilを返す。 そのようなウィンドウが複数ある場合、 ウィンドウの巡回順序において選択されているウィンドウから始めて 最初にみつかったウィンドウを返す。 see Cyclic Window Ordering

引数all-framesは、どのウィンドウを対象とするかを制御する。

  • nilであると、選択されているフレームのウィンドウを対象とする。
  • tであると、すべてのフレームのウィンドウを対象とする。
  • visibleであると、 すべての可視フレームのすべてのウィンドウを対象にする。
  • 0であると、すべての可視フレームやアイコンになっているフレーム のウィンドウを対象にする。
  • フレームであると、当該フレームのウィンドウを対象にする。

get-buffer-window-list buffer-or-name &optional minibuf all-frames Function
この関数は、現在buffer-or-nameを表示している すべてのウィンドウのリストを返す。

省略可能な2つの引数は、next-window(see Cyclic Window Ordering)の 省略可能な引数と同様に働き、 get-buffer-windowの省略可能な単一の引数と同じではないget-buffer-windowを他の関数と互換性があるように 将来変更すべきなのであろう。

引数all-framesは、どのウィンドウを対象とするかを制御する。

  • nilであると、選択されているフレームのウィンドウを対象とする。
  • tであると、すべてのフレームのウィンドウを対象とする。
  • visibleであると、 すべての可視フレームのすべてのウィンドウを対象にする。
  • 0であると、すべての可視フレームやアイコンになっているフレーム のウィンドウを対象にする。
  • フレームであると、当該フレームのウィンドウを対象にする。

buffer-display-time Variable
この変数は、バッファがウィンドウで見えるようになった最後の時刻を記録する。 この変数は各バッファでつねにバッファローカルであり、 set-window-bufferは、呼ばれるたびに 指定されたバッファのこの変数に(current-time)を設定する (see Time of Day)。 バッファが初めて作られると、buffer-display-timeは値nilで始まる。


Node:Displaying Buffers, Next:, Previous:Buffers and Windows, Up:Windows

ウィンドウへのバッファの表示

本節では、ウィンドウを自動的に選びそれに指定したバッファを表示する 便利な関数について述べます。 これらの関数は、ある状況では、既存のウィンドウを分割します。 ウィンドウを選ぶ際の発見的手法を制御する変数についても述べます。 より正確に制御するための低レベルの関数については、 これらの関数はすべてset-window-bufferを呼び出して動作します。

バッファをカレントバッファにしてLispプログラムで参照したり変更できるように するためには、本節の関数を使わないでください。 これらはその目的には強力すぎます。 ウィンドウのバッファの表示をユーザーにとっては迷惑で驚くようなものに 変更してしまうからです。 そのかわりに、ウィンドウのバッファの表示には影響せずに バッファをプログラムから参照するためにカレントバッファにする set-buffersave-current-buffer(see Current Buffer)を 使います。

switch-to-buffer buffer-or-name &optional norecord コマンド
この関数は、buffer-or-nameをカレントバッファにし、 さらに、選択されているウィンドウに当該バッファを表示する。 つまり、人間が当該バッファを見ることができるようになり、 以降のキーボードコマンドは当該バッファに適用される。 buffer-or-nameをカレントバッファにするが 選択されているウィンドウには表示しないset-bufferと比較してほしい。 see Current Buffer

buffer-or-nameが既存のバッファを指定しなければ、 その名前の新たなバッファが作成される。 新たなバッファのメジャーモードは変数default-major-modeに 従って設定される。 see Auto Major Mode

通常、指定したバッファはバッファリスト (選択されているフレームのバッファリストとフレーム独立のバッファリストの 両方)の先頭に置かれる。 これは、other-bufferの動作に影響する。 しかし、norecordnil以外であると、これを行わない。 see The Buffer List

関数switch-to-bufferは、しばしば、 C-x bにバインドされて対話的に使われる。 プログラムでも多用される。 つねにnilを返す。

switch-to-buffer-other-window buffer-or-name &optional norecord コマンド
この関数は、buffer-or-nameをカレントバッファにし、 現在選択されていないウィンドウに当該バッファを表示する。 そして当該ウィンドウを選択する。 バッファの扱い方はswitch-to-bufferと同じである。

現在選択されているウィンドウは、この処理には絶対に使わない。 それが唯一のウィンドウである場合には、この目的のために ウィンドウを分割して別のウィンドウを作る。 選択されているウィンドウがすでに当該バッファを表示している場合には、 当該ウィンドウはそのまま表示し続けるが、それにも関わらず、 表示するために別のウィンドウを探す。

この関数は、norecordnilであると、 switch-to-bufferのようにバッファリストを更新する。

pop-to-buffer buffer-or-name &optional other-window norecord Function
この関数は、buffer-or-nameをカレントバッファにし、 以前には選択されていない別のウィンドウで当該バッファに切り替える。 そのウィンドウがそのフレームの選択されているウィンドウになる。

変数pop-up-framesnil以外であると、 pop-to-bufferは、可視フレームから 当該バッファをすでに表示しているウィンドウを探す。 そのようなウィンドウがあれば、そのウィンドウを返すとともに、 そのウィンドウをそのフレームの選択されているウィンドウにする。 そのようなウィンドウがなければ、新たなフレームを作成し それにバッファを表示する。

pop-up-framesnilであると、 pop-to-bufferは選択されているフレーム内だけで処理を行う。 (選択されているフレームがミニバッファのみであるときには、 pop-to-bufferは、ミニバッファのみでない もっとも最近に選択されたフレーム内で処理する。)

変数pop-up-windowsnil以外であると、 もとのウィンドウとは異なる新たなウィンドウを作成するために ウィンドウを分割することがある。 詳しくは、Choosing Windowを参照。

other-windownil以外であると、 選択されているウィンドウにbuffer-or-nameがすでに表示されていても、 pop-to-bufferは別のウィンドウを探したり作成する。 そのため、buffer-or-nameは2つのウィンドウに表示されることになる。 一方で、buffer-or-nameが選択されているウィンドウに すでに表示されていて、かつ、other-windownilであると、 選択されているウィンドウはbuffer-or-nameの表示には十分であるとみなし、 なにも行わない。

display-bufferに影響するすべての変数は、 pop-to-bufferにも影響する。 see Choosing Window

buffer-or-nameが文字列であり既存のバッファを指定しない場合、 その名前のバッファを作成する。 新たなバッファのメジャーモードは変数default-major-modeに 従って設定される。 see Auto Major Mode

この関数は、norecordnilであると、 switch-to-bufferのようにバッファリストを更新する。

replace-buffer-in-windows buffer コマンド
この関数は、bufferを表示しているすべてのウィンドウにおいて bufferを別のバッファに切り替える。 別のバッファはother-bufferで選ぶ。 この関数の普通の用途は、別のバッファがどれになるか気にしない場合である。 つまり、bufferが表示されていないことを保証したい場合である。

この関数はnilを返す。


Node:Choosing Window, Next:, Previous:Displaying Buffers, Up:Windows

表示ウィンドウを選ぶ

本節では、バッファを表示するためのウィンドウを選ぶための基本的な機能、 display-bufferについて述べます。 上位レベルの関数やコマンドはすべてこのサブルーティンを使います。 ここでは、display-bufferの使い方とカスタマイズ方法を説明します。

display-buffer buffer-or-name &optional not-this-window frame コマンド
このコマンドは、pop-to-bufferのように、 buffer-or-nameをあるウィンドウに表示するが、 そのウィンドウを選択しないので当該バッファもカレントバッファにならない。 この関数は、選択されているウィンドウを変えない。

not-this-windownil以外であると、 指定したバッファが選択されているウィンドウにすでに表示されていても、 別のウィンドウに当該バッファを表示することを意味する。 これにより、当該バッファが同時に2つのウィンドウに表示される。 さもなければ、buffer-or-nameがウィンドウにすでに表示されていると、 それで十分とみなしこの関数はなにもしない。

display-bufferは、buffer-or-nameを表示するために 選んだウィンドウを返す。

引数framenil以外であると、 バッファがすでに表示されているかどうかを検査するときに どのフレームを対象とするかを指定する。 それらのフレームのどれかのウィンドウに当該バッファがすでに表示されていると、 display-bufferは単にそのウィンドウを返す。 frameの可能な値はつぎのとおりである。

  • nilであると、選択されているフレームのウィンドウを対象とする。
  • tであると、すべてのフレームのウィンドウを対象とする。
  • visibleであると、 すべての可視フレームのすべてのウィンドウを対象にする。
  • 0であると、すべての可視フレームやアイコンになっているフレーム のウィンドウを対象にする。
  • フレームであると、当該フレームのウィンドウを対象にする。

display-bufferがウィンドウを作成したり探す詳しい手順は、 以下に述べる変数に依存する。

pop-up-windows User Option
この変数は、display-bufferが新たにウィンドウを作るかどうかを制御する。 nil以外であり、かつ、ウィンドウがたった1つである場合、 そのウィンドウを分割する。 nilであると、display-bufferは 単一のウィンドウを分割せずにそれ全体を使う。

split-height-threshold User Option
この変数は、ウィンドウが複数ある場合に display-bufferがどの時点でウィンドウを分割するかを決定する。 display-bufferは、最大ウィンドウの行数が この変数による指定行数より大きければ、最大ウィンドウをつねに分割する。 最大ウィンドウがこれだけ大きくない場合には、 それが唯一のウィンドウであり、かつ、pop-up-windowsnil以外 の場合にのみ最大ウィンドウを分割する。

pop-up-frames User Option
この変数は、display-bufferが新たなフレームを作るかどうかを制御する。 nil以外であると、display-bufferは、 すべての可視フレームから指定されたバッファをすでに表示している 既存のウィンドウを探す。 そのようなウィンドウがあれば、そのウィンドウを返す。 さもなければ、新たなフレームを作る。 変数pop-up-framesnil以外であると、 変数pop-up-windowssplit-height-thresholdは影響しない。

pop-up-framesnilであると、 display-bufferはウィンドウを分割するか再利用する。

詳しくは、see Frames

pop-up-frame-function Variable
この変数は、pop-up-framesnil以外であるときに どのように新たなフレームを作るかを指定する。

その値は引数なしの関数であること。 display-bufferが新たにフレームを作るとき、 フレームを返すこの関数を呼び出す。 この変数のデフォルト値は、 pop-up-frame-alistのパラメータを使って新たなフレームを作る関数である。

pop-up-frame-alist Variable
この変数は、display-bufferが新たにフレームを作るときに 使用するフレームパラメータを指定する連想リストを保持する。 フレームパラメータに関して詳しくは、 see Frame Parameters

special-display-buffer-names User Option
特別に表示すべきバッファのバッファ名のリスト。 バッファ名がこのリストにあると、 display-bufferは当該バッファを特別に扱う。

デフォルトでは、特別に表示するとは、 専用のフレームにバッファを表示することである。

リストの要素が文字列でなくリストであると、 リストのCARがバッファ名であり、 リストの残りはフレームの作成方法を指定する。 それは、フレームパラメータを指定する連想リストであるか、 関数とそれに渡す引数である。 (関数の第1引数はつねに表示すべきバッファである。 そのあとにリスト内の引数が続く。)

special-display-regexps User Option
特別に表示すべきバッファを指定する正規表現のリスト。 バッファ名がこのリストのいずれかの正規表現に一致すると、 display-bufferは当該バッファを特別に扱う。

デフォルトでは、特別に表示するとは、 専用のフレームにバッファを表示することである。

リストの要素が文字列でなくリストであると、 リストのCARが正規表現であり、 リストの残りはフレームの作成方法を指定する。 上記のspecial-display-buffer-namesを参照。

special-display-function Variable
この変数は、バッファを特別に表示するために呼び出す関数を保持する。 引数としてバッファを受け取り、 当該バッファを表示したウィンドウを返すこと。

この関数のデフォルト値はspecial-display-popup-frameである。

special-display-popup-frame buffer Function
この関数は、bufferをそれ専用のフレームに表示する。 あるフレームのウィンドウにbufferがすでに表示されている場合、 当該ウィンドウを使うために当該フレームを可視にし手前に持ってくる。 さもなければ、buffer用にフレームを作成する。

この関数は、bufferを表示している既存のウィンドウのフレームで 当該バッファだけを表示しているかどうかに関わらず、 既存の当該ウィンドウを使う。 しかし、bufferを作るまえに読者の初期化ファイルで上記の変数に設定 しているときには、当該ウィンドウは以前にこの関数が作成したものであろう。

special-display-frame-alist User Option
この変数は、special-display-popup-frameがフレームを作るときに 使用するフレームパラメータを保持する。

same-window-buffer-names User Option
選択されているウィンドウに表示すべきバッファのバッファ名のリスト。 バッファ名がこのリストにあると、 display-bufferは選択されているウィンドウで当該バッファに切り替える。

same-window-regexps User Option
選択されているウィンドウに表示すべきバッファを指定する正規表現のリスト。 バッファ名がこのリストのいずれかの正規表現に一致すると、 display-bufferは選択されているウィンドウで当該バッファに切り替える。

display-buffer-function Variable
この変数は、display-bufferのふるまいをカスタマイズする もっとも柔軟な方法である。 nil以外であると、display-bufferが処理を依頼するために 呼び出す関数であること。 その関数は、display-bufferが受け取るのと同じ2つの引数を受け付けること。 その関数は、ウィンドウを選ぶか作成し、指定されたバッファを表示し、 当該ウィンドウを返すこと。

このフックは、上に述べた他のオプションやフックすべてに優先する。

ウィンドウにはそのバッファ『専用』と印を付けられます。 そうすると、display-bufferは他のバッファを表示するために 当該ウィンドウを使わないようにします。

window-dedicated-p window Function
この関数は、windowに専用と印が付いていればtを返し、 さもなければnilを返す。

set-window-dedicated-p window flag Function
この関数は、flagnil以外であるとwindowに専用の印を付け、 さもなければ専用の印を消す。


Node:Window Point, Next:, Previous:Choosing Window, Up:Windows

ウィンドウとポイント

各ウィンドウには、同じバッファを表示している 別のウィンドウのポイントの値とは独立な独自のポイントの値があります。 これにより、あるバッファを複数のウィンドウに表示しても有用なのです。

ユーザーにとっては、ポイントとはカーソルが置かれた箇所であり、 別のバッファに切り替えるとそのバッファのポイント位置に カーソルが移動します。

window-point window Function
この関数は、windowの現在のポイント位置を返す。 選択されていないウィンドウでは、 当該ウィンドウを選択したときになるであろう (ウィンドウのバッファの)ポイント値である。

windowが選択されているウィンドウであり、かつ、 そのバッファがカレントバッファであれば、 戻り値は当該バッファのポイントと同じである。

厳密にいえば、すべてのフォームsave-excursionの外側での 『トップレベル』のポイントの値を返すほうがより正確である。 しかし、そのような値を探すのは困難である。

set-window-point window position Function
この関数は、windowのバッファ内の位置positionwindowのポイント位置とする。


Node:Window Start, Next:, Previous:Window Point, Up:Windows

ウィンドウの開始位置

各ウィンドウには、バッファのどの箇所から表示を始めるかを指定する バッファ内位置を追跡するために使うマーカがあります。 この位置をウィンドウの表示開始(display-start)位置 (あるいは単に開始(start)位置)と呼びます。 この位置の直後にある文字が、ウィンドウの左上隅に現れます。 この位置は、通常、テキスト行の先頭にありますが、必須ではありません。

window-start &optional window Function
この関数は、ウィンドウwindowの表示開始位置を返す。 windownilであると、 選択されているウィンドウを使う。 たとえばつぎのとおりである。
(window-start)
     => 7058

新たにウィンドウを作成したり異なるバッファをウィンドウに表示すると、 表示開始位置は、当該バッファの最近に使われた表示開始位置になるか、 バッファに表示開始位置がなければ1になる。

再表示するとウィンドウ開始位置は (それ以前の再表示で明示的に位置を指定していなければ)、 ポイントがスクリーンに現れるように更新される。 再表示以外には、ウィンドウ開始位置を自動的に変更しない。 ポイントを移動しても、つぎの再表示までは、 連動してウィンドウ開始位置が変更されると期待しないこと。

window-startを使った実際的な例は、 Text Linescount-linesの記述を参照。

window-end &optional window update Function
この関数は、ウィンドウwindowの表示の末尾の位置を返す。 windownilであると、選択されているウィンドウを使う。

バッファのテキストを変更したりポイントを移動しただけでは、 window-endが返す値は更新されない。 この値は、Emacsが再表示を実行し途中で止めることなく 最後まで終了した場合にのみ更新される。

windowの最後の再表示が途中で止められて完了していないと、 当該ウィンドウの表示の末尾の位置はEmacsにはわからない。

updatenil以外であると、 window-endはウィンドウの末尾の更新値をつねに返す。 保存しておいた値が正しければwindow-endはそれを返す。 さもなければ、バッファのテキストを走査して正しい値を計算する。

set-window-start window position &optional noforce Function
この関数は、windowの表示開始位置を windowのバッファ内の位置positionとする。 これはpositionを返す。

表示ルーティンは、バッファを表示するときには ポイント位置が可視であることを強要する。 通常、表示ルーティンは、ポイントを可視にするために必要なときには 表示開始位置を(つまりウィンドウをスクロールして)変更する。 しかし、noforcenilを指定してこの関数で開始位置を指定すると、 ポイント位置がスクリーンからはみ出したとしても、 表示開始位置をpositionとすることを意味する。 ポイントがスクリーンからはみ出す場合には、 表示ルーティンはウィンドウの中央行の左端にポイントを移動する。

たとえば、ポイントが1にあるときに ウィンドウの開始位置を2にしたとすると、 ポイントはウィンドウの上端より『上』になる。 表示ルーティンは、再表示時にポイントが1のままであると 自動的にポイントを移動する。 以下に例を示す。

;; 式set-window-startを実行するまえの
;; fooの見え方

---------- Buffer: foo ----------
-!-This is the contents of buffer foo.
2
3
4
5
6
---------- Buffer: foo ----------

(set-window-start
 (selected-window)
 (1+ (window-start)))
=> 2

;; 式set-window-startを実行したあとの
;; fooの見え方
---------- Buffer: foo ----------
his is the contents of buffer foo.
2
3
-!-4
5
6
---------- Buffer: foo ----------

noforcenil以外であって positionにするとつぎの再表示時にポイントがスクリーンからはみ出す 場合には、再表示ではポイントが収まるように新たなウィンドウ開始位置を 計算し、positionを使わない。

pos-visible-in-window-p &optional position window Function
この関数は、window内のpositionがスクリーン上で 現在可視なテキストの範囲内にあればtを返す。 positionがスクリーンの上下端からはみ出す場合にはnilを返す。 引数positionのデフォルトはポイントの現在位置であり、 windowのデフォルトは選択されているウィンドウである。 例を示す。
(or (pos-visible-in-window-p
     (point) (selected-window))
    (recenter 0))

関数pos-visible-in-window-pは、垂直方向のスクロールだけを考慮する。 windowを水平方向にスクロールしたために positionがはみ出している場合には、 pos-visible-in-window-ptを返す。 see Horizontal Scrolling


Node:Vertical Scrolling, Next:, Previous:Window Start, Up:Windows

垂直スクロール

垂直スクロールとは、ウィンドウ内のテキストを上向きや下向きに動かすことです。 ウィンドウの表示開始位置の値を変更することで動作します。 ポイントがスクリーン内に留まるようにwindow-pointの 値を変更することもあります。

コマンドscroll-upscroll-downの 方向を示す『up』(上向き)と『down』(下向き)は、 ウィンドウを見ているときのバッファ内のテキストの移動方向を表します。 テキストは縦に長い紙に(横書きで)書いてあり、 スクロールコマンドはその紙を上下に動かすと想像してください。 したがって、バッファの中ほどのテキストを見ているときに scroll-downを繰り返し呼び出すと、 最終的にはバッファの先頭を見ることになります。

逆の慣習の名前を使うべきだと主張する人々もいます。 彼らは、固定されたテキストのうえをウィンドウが動いていると想像するのです。 すると、『下向き』のコマンドはバッファの末尾に移動することになります。 この見方は、ウィンドウとバッファ内のテキストとの実際の関係に よく適合しているのですが、ユーザーはそのように考えないようです。 端末上ではウィンドウは動きませんし、スクロールコマンドは 明らかにテキストをスクリーン上で上下に動かしています。 ユーザーの視点に合う名称を選んだのです。

カレントバッファと選択されているウィンドウに 表示されているバッファとが異なる場合には、 (scroll-other-window以外の)スクロール関数の結果は予測できません。 See Current Buffer

scroll-up &optional count コマンド
この関数は、選択されているウィンドウのテキストを 上向きにcount行だけスクロールする。 countが負であると、実際のスクロール方向は下向きである。

countnil(あるいは省略)であると、 スクロール量は、ウィンドウの(モード行を数えない)利用可能な高さより next-screen-context-linesだけ少なくなる。

scroll-upnilを返す。

scroll-down &optional count コマンド
この関数は、選択されているウィンドウのテキストを 下向きにcount行だけスクロールする。 countが負であると、実際のスクロール方向は上向きである。

countnil(あるいは省略)であると、 スクロール量は、ウィンドウの(モード行を数えない)利用可能な高さより next-screen-context-linesだけ少なくなる。

scroll-downnilを返す。

scroll-other-window &optional count コマンド
この関数は、別のウィンドウのテキストを上向きに count行だけスクロールする。 countの値が負であったりnilであると、 scroll-upと同様に扱う。

変数other-window-scroll-bufferで、スクロールするバッファを指定できる。 選択されているウィンドウがミニバッファ用であるときには、 つぎのウィンドウは、通常、もっとも左上隅にあるウィンドウである。 変数minibuffer-scroll-windowで、 スクロールする別のウィンドウを指定できる。 別のウィンドウが選択されている場合には、この変数の効果はない。 see Minibuffer Misc

ミニバッファが活性であると、 右下隅のウィンドウが選択されているウィンドウであるときには、 つぎのウィンドウはミニバッファ用ウィンドウである。 この場合、scroll-other-windowはミニバッファをスクロールしようとする。 ミニバッファにたった1行しか入っていなければスクロールできず、 エコー領域に『Beginning of buffer』と短時間表示されたあとで、 ミニバッファの行が再度現れる。

other-window-scroll-buffer Variable
この変数がnil以外であると、 scroll-other-windowがスクロールするバッファを指定する。

scroll-margin User Option
このオプションは、スクロール時の余白の大きさ、 つまり、ポイントとウィンドウの上端や下端とのあいだにある最低行数を指定する。 ウィンドウの上端や下端からこの行数以内にポイントが移動するたびに、 (可能ならば)ウィンドウを自動的にスクロールして、 ポイントを余白の外側でウィンドウの中央近くに移動する。

scroll-conservatively User Option
この変数は、ポイントがスクリーンからはみ出したとき (あるいはスクロール時の余白に入ったとき)に どのように自動的にスクロールするかを制御する。 値が0であると、ウィンドウの縦方向でポイントが中央にくるように テキストをスクロールして再表示する。 値が正の整数nであると、 ウィンドウをどちらかの方向に最大n行だけスクロールすると ポイントが見えるようになるときには、そのようにスクロールして再表示する。 さもなければ、ポイントが中央にくるようにする。 デフォルト値は0である。

scroll-step User Option
この変数は、scroll-conservativelyの古い変種である。 違いは、値がnであると正確にn行だけのスクロールを許すことである。 この機能はscroll-marginでは働かない。 デフォルト値は0である。

scroll-preserve-screen-position User Option
このオプションがnil以外であると、 スクロール関数は、可能ならばカーソルの垂直方向の位置を 変えないようにポイントを移動する。

next-screen-context-lines User Option
この変数の値は、1画面分スクロールしたときに連続して残っている行数である。 たとえば、引数nilscroll-upは、 ウィンドウの下端にあるこの行数だけの行が上端にくるようにスクロールする。 デフォルト値は2である。

recenter &optional count コマンド
この関数は、選択されているウィンドウをスクロールして ポイント位置にあるテキストがウィンドウ内の垂直方向の指定位置にくるようにする。

countが非負の数であると、ポイント位置にある行を ウィンドウの上端からcount行下にくるようにする。 countが負の数であると、ウィンドウの下端から数え、 -1はウィンドウの使用可能な最後の行を表す。 countnil以外のリストであると、 ウィンドウの中央の行を表す。

countnilであると、recenterは、 ポイント位置にある行がウィンドウの中央にくるようにして、 選択されているフレーム全体をクリアして再表示する。

recenterが対話的に呼び出されると、countは生の前置引数である。 したがって、前置引数としてC-uと打つと countnil以外のリストになり、 C-u 4と打つとcountは4になって上端から4行目に現在行がくる。

引数が0であると、 recenterはウィンドウの上端に現在行がくるようにする。 この動作は、このための専用のキーバインディングをする人がいるくらい便利である。 たとえばつぎのようにする。

(defun line-to-top-of-window ()
  "Scroll current line to top of window.
Replaces three keystroke sequence C-u 0 C-l."
  (interactive)
  (recenter 0))

(global-set-key [kp-multiply] 'line-to-top-of-window)


Node:Horizontal Scrolling, Next:, Previous:Vertical Scrolling, Up:Windows

水平スクロール

英文は『内側のループ』では左から右へ『外側のループ』では上から下へと読むので、 水平スクロールは垂直スクロールには似ていません。 垂直スクロールでは表示するテキストの連続部分を選びますが、 水平スクロールでは各行の一部がスクリーンからはみ出すことになります。 そのため、水平スクロールの量は、バッファ内の位置ではなく、 コラム数で指定します。 これは、window-startが返す表示開始位置とはなんの関係もありません。

通常、水平スクロールは行われません。 つまり、左端のコラムはウィンドウの左端にあります。 この状態で右向きにスクロールしても、 それによって見えてくるスクリーンの左側にはなにもないので意味がありません。 ですから、これは禁止されます。 左向きへのスクロールは許されて、 テキストの先頭コラムはウィンドウの端からはみ出し、 それまで切り詰められていた右側のコラムが見えるようになります。 左向きの水平スクロール量が0でなければ、 右向きへスクロールして戻せますが、 これは全体としての水平スクロール量が0になるまでです。 左向きスクロールの限界はありませんが、 最終的にはテキストすべてが左端からはみ出してしまいます。

scroll-left count コマンド
この関数は、選択されているウィンドウをcountコラムだけ 左向きに(countが負ならば右向きに)スクロールする。 戻り値は、変更後の左向き水平スクロール量の総量であり、 window-hscroll(下記参照)が返す値と同じである。

scroll-right count コマンド
この関数は、選択されているウィンドウをcountコラムだけ 右向きに(countが負ならば左向きに)スクロールする。 戻り値は、変更後の左向き水平スクロール量の総量であり、 window-hscroll(下記参照)が返す値と同じである。

可能なだけウィンドウを右向きにスクロールしてしまうと、 通常の状態、つまり、左向き水平スクロール量が0になり、 それ以降、右向きスクロールは効果がなくなる。

window-hscroll &optional window Function
この関数は、windowの左向き水平スクロール量の総量、 つまり、windowのテキストが左端を超えてスクロールされたコラム数を返す。

値はけっして負にはならない。 windowが水平方向にスクロールされていなければ (これが通常の状態)0である。

windownilであると、選択されているウィンドウを使う。

(window-hscroll)
     => 0
(scroll-left 5)
     => 5
(window-hscroll)
     => 5

set-window-hscroll window columns Function
この関数は、windowのスクロールされている左端からのコラム数を columnsの値とする。 引数columnsは0か正であること。 さもないと0と仮定する。

戻り値はcolumnsである。

(set-window-hscroll (selected-window) 10)
     => 10

水平スクロールのために指定位置positionが スクリーンからはみ出しているかどうかを調べる方法をつぎに示します。

(defun hscroll-on-screen (window position)
  (save-excursion
    (goto-char position)
    (and
     (>= (- (current-column) (window-hscroll window)) 0)
     (< (- (current-column) (window-hscroll window))
        (window-width window)))))


Node:Size of Window, Next:, Previous:Horizontal Scrolling, Up:Windows

ウィンドウサイズ

Emacsのウィンドウは矩形であり、そのサイズ情報は 高さ(行数)と幅(各行の文字数)から成ります。 モード行は高さに含みます。 しかし、スクロールバーや左右のウィンドウを隔てる文字|のコラムは 幅には含みません。

つぎの3つの関数は、ウィンドウのサイズ情報を返します。

window-height &optional window Function
この関数は、モード行を含むwindowの行数を返す。 windowがフレーム全体を占める場合、この値は典型的には、 当該フレームにおけるframe-heightの値より1小さい (最後の行はミニバッファ用につねに確保してあるため)。

windownilであると、この関数は選択されているウィンドウを使う。

(window-height)
     => 23
(split-window-vertically)
     => #<window 4 on windows.texi>
(window-height)
     => 11

window-width &optional window Function
この関数は、windowのコラム数を返す。 windowがフレーム全体を占める場合、この値は、 当該フレームにおけるframe-widthの値と同じである。 この幅には、ウィンドウのスクロールバーや 左右のウィンドウを隔てる文字|のコラムは含まない。

windownilであると、この関数は選択されているウィンドウを使う。

(window-width)
     => 80

window-edges &optional window Function
この関数は、windowの四隅の座標から成るリストを返す。 windownilであると、選択されているウィンドウを使う。

list内の順番は(left top right bottom) (つまり、左端、上端、右端、下端)であり、 フレームの左上隅を0としてすべての要素は0を基準とする。 要素rightwindowが使用する右端のコラムより1大きく、 bottomwindowが使用する下端より1大きく モード行と同じである。

左右に隣り合ったウィンドウがある場合、 右隣にウィンドウがあるウィンドウの右端の値には、 ウィンドウを隔てる区切りの幅が含まれる。 この区切りは、文字|のコラムであるかスクロールバーである。 ウィンドウの幅にはこの区切りは含まないため、 この場合、左端と右端の差は幅に等しくない。

典型的な24行の端末でウィンドウが1つの場合に得られる結果を示す。

(window-edges (selected-window))
     => (0 0 80 23)

下端が23行目であるのは、最下行はエコー領域だからである。

windowがフレームの左上隅にあると、 bottom(window-height)の値に等しく、 right(window-width)の値にほぼ等しく 9topleftは0である。 たとえば、つぎのウィンドウは0 0 5 8である。 当該フレームには8コラムより多くあり、 ウィンドウの最終コラム(7コラム目)はテキストではなく境界であると仮定する。 最後の行(4行目)はモード行であり、ここではxxxxxxxxxで示した。

           0
           _______
        0 |       |
          |       |
          |       |
          |       |
          xxxxxxxxx  4

                  7

左右に隣り合ったウィンドウがあるときには、 フレームの右端にないウィンドウの最後のコラムは区切りである。 区切りは、ウィンドウの幅では1コラムか2コラム占める。 左側の区切りは左隣のウィンドウに属するので、 ウィンドウには左側の区切りは含まれない。

つぎの例では、フレームは7コラム幅であるとする。 すると、左側のウィンドウの四隅は0 0 4 3であり、 右側のウィンドウの四隅は4 0 7 3である。

           ___ ___
          |   |   |
          |   |   |
          xxxxxxxxx

           0  34  7


Node:Resizing Windows, Next:, Previous:Size of Window, Up:Windows

ウィンドウサイズの変更

ウィンドウサイズ関数は2つに大別できます。 ウィンドウサイズを変える上位レベルのコマンドと ウィンドウサイズを調べる下位レベルの関数です。 Emacsでは重なり合ったウィンドウやウィンドウのあいだに隙間を許さないので、 1つのウィンドウの大きさを変えると別のウィンドウにも影響します。

enlarge-window size &optional horizontal コマンド
この関数は、隣り合うウィンドウから場所を奪って、 選択されているウィンドウをsize行高くする。 1つのウィンドウから場所を奪い取り、奪い尽くすと別のウィンドウから取る。 場所を奪われたウィンドウがwindow-min-height行未満になると、 そのウィンドウは消える。

horizontalnil以外であると、 この関数は、隣り合うウィンドウから場所を奪って、 選択されているウィンドウをsizeコラム広くする。 場所を奪われたウィンドウがwindow-min-widthコラム未満になると、 そのウィンドウは消える。

指定した大きさがウィンドウのフレームの大きさを超える場合、 この関数は、ウィンドウがフレームの高さ(あるいは幅)全体を占めるようにする。

sizeが負であると、この関数は-size行/コラムだけ ウィンドウを縮める。 ウィンドウが(window-min-heightwindow-min-widthの) 最小サイズより小さくなると、enlarge-windowは 当該ウィンドウを削除する。

enlarge-windownilを返す。

enlarge-window-horizontally columns コマンド
この関数は、選択されているウィンドウをcolumnsコラム広くする。
(defun enlarge-window-horizontally (columns)
  (enlarge-window columns t))

shrink-window size &optional horizontal コマンド
この関数はenlarge-windowに似ているが引数sizeの符号を変えて、 選択されているウィンドウを縮めて指定行数(コラム数)を 他のウィンドウに与える。 ウィンドウがwindow-min-heightwindow-min-width未満に縮むと、 そのウィンドウは消える。

sizeが負であると、ウィンドウは -size行/コラムだけ伸びる。

shrink-window-horizontally columns コマンド
この関数は、選択されているウィンドウをcolumnsコラム狭くする。 つぎのように定義できる。
(defun shrink-window-horizontally (columns)
  (shrink-window columns t))

shrink-window-if-larger-than-buffer window コマンド
このコマンドは、バッファの全内容を表示するに十分なだけの大きさに windowを縮めるが、window-min-height行未満にはしない。

しかし、バッファの全テキストを表示するにはウィンドウが小さすぎる場合や、 内容の一部がスクロールでスクリーンからはみ出している場合や、 ウィンドウの幅がフレームの幅と同じでない場合や、 ウィンドウがフレームの唯一のウィンドウである場合には、 このコマンドはなにもしない。

つぎの2つの変数は、ウィンドウサイズを変える関数に最小の高さと幅を課します。

window-min-height User Option
この変数の値は、ウィンドウが自動的に削除されるまでに どの程度までウィンドウが短くなりうるかを決定する。 ウィンドウをwindow-min-height行未満に小さくすると自動的に削除され、 これより短いウィンドウは作成できない。 絶対的な最小の高さは2行(モード行に1行、バッファの表示に1行)である。 ウィンドウサイズを変える処理では、この変数が2未満であると2に設定し直す。 デフォルト値は4である。

window-min-width User Option
この変数の値は、ウィンドウが自動的に削除されるまでに どの程度までウィンドウが狭くなりうるかを決定する。 ウィンドウをwindow-min-widthコラム未満に小さくすると自動的に削除され、 これより狭いウィンドウは作成できない。 絶対的な最小の幅は1であり、それ未満は無視する。 デフォルト値は10である。


Node:Coordinates and Windows, Next:, Previous:Resizing Windows, Up:Windows

座標とウィンドウ

本節では、スクリーン座標をウィンドウに関連付ける方法を述べます。

window-at x y &optional frame Function
この関数は、フレームframeにおいて指定したカーソル位置を含んでいる ウィンドウを返す。 座標xyは、フレームの左上隅から文字単位で数える。 座標が範囲外であるとwindow-atnilを返す。

frameを省略すると、選択されているフレームを使う。

coordinates-in-window-p coordinates window Function
この関数は、指定したフレーム位置がウィンドウwindowの中に 入るかどうかを検査する。

引数coordinatesは、(x . y)の形のコンスセルである。 座標xyは、スクリーンやフレームの左上隅から文字単位で数える。

coordinates-in-window-pが返す値がnil以外であると、 当該座標はwindowの内側にある。 つぎのように、この値はウィンドウ内での位置も表す。

(relx . rely)
当該座標はwindowの内側である。 数relxrelyは、指定位置に対応するウィンドウ相対の座標であり、 ウィンドウの左上隅を0として数えたものである。
mode-line
当該座標はwindowのモード行の内側である。
vertical-split
当該座標はwindowと右隣のウィンドウのあいだの垂直行である。 ウィンドウにスクロールバーがない場合に限って、この値になる。 スクロールバーはウィンドウの外側であるとみなす。
nil
当該座標はwindowのどこでもない。

関数coordinates-in-window-pは、 windowのフレームをつねに使うため、引数にフレームを必要としない。


Node:Window Configurations, Next:, Previous:Coordinates and Windows, Up:Windows

ウィンドウ構成

ウィンドウ構成(window configuration)は、 1つのフレームの全体の配置、つまり、 すべてのウィンドウ、それらの大きさ、表示しているバッファ、 各バッファの表示位置、ポイントとマークの値を記録します。 保存しておいたウィンドウ構成を復元すれば、 まえとまったく同じ配置に戻せます。

1つのフレームではなくすべてのフレームを記録するには、 ウィンドウ構成のかわりにフレーム構成を使います。 See Frame Configurations

current-window-configuration Function
この関数は、選択されているフレームの現在のウィンドウ構成を表す 新たなオブジェクトを返す。 ウィンドウ構成には、ウィンドウの個数、それらの大きさとカレントバッファ、 どのウィンドウが選択されているウィンドウであるか、 各ウィンドウが表示しているバッファ、表示開始位置、 ポイントとマークの位置が含まれる。 window-min-heightwindow-min-widthminibuffer-scroll-windowの値も含む。 例外はカレントバッファのポイントであり、その値は保存されない。

set-window-configuration configuration Function
この関数は、configurationで指定される ウィンドウとバッファの構成に復元する。 引数configurationは、 current-window-configurationが返した値であること。 configurationを作成したフレームにおいて、 そのフレームが選択されているかどうかに関わらず、この構成を復元する。 set-window-configurationは、新たな構成が古いものと 実際に異なるのかどうか識別する方法を知らないため、 ウィンドウサイズの変更とつねにみなして window-size-change-functions(see Window Hooks)の 実行を引き起こす。

configurationを保存したフレームがなくなっていると、 この関数は、3つの変数、window-min-heightwindow-min-widthminibuffer-scroll-windowを 復元するだけである。

save-window-excursionと同じ効果を得るための この関数の使い方をつぎに示す。

(let ((config (current-window-configuration)))
  (unwind-protect
      (progn (split-window-vertically nil)
             ...)
    (set-window-configuration config)))

save-window-excursion forms... Special Form
このスペシャルフォームは、ウィンドウ構成を記録し、 formsを順に評価し、もとのウィンドウ構成に復元する。 ウィンドウ構成には、ポイントの値と可視なバッファの部分が含まれる。 また、選択されているウィンドウも含む。 しかし、これにはカレントバッファのポイント値は含まれないため、 ポイント位置を保存したい場合にはsave-excursionも使う。

save-selected-windowで十分なときには、この構文を使わないこと。

save-window-excursionから抜けると、 window-size-change-functionsの実行をつねに引き起こす。 (復元した構成とformsの終りでの構成が実際に異なるかどうかを 識別する方法を知らない。)

戻り値は、formsの最後のフォームの値である。 例を示す。

(split-window)
     => #<window 25 on control.texi>
(setq w (selected-window))
     => #<window 19 on control.texi>
(save-window-excursion
  (delete-other-windows w)
  (switch-to-buffer "foo")
  'do-something)
     => do-something
     ;; スクリーンはここでふたたび分割される

window-configuration-p object Function
この関数は、objectがウィンドウ構成であればtを返す。

compare-window-configurations config1 config2 Function
この関数は、ウィンドウの構造を基に2つのウィンドウ構成を比較する。 ポイントとマークの値、保存されたスクロール位置は無視するので、 それらが異なっていてもtを返す。

関数equalでも2つのウィンドウ構成を比較できるが、 保存されたポイントやマークが違うだけであっても異なる部分があると、 等しくない構成とみなす。

ウィンドウ構成の内部を調べる基本関数には意味があるでしょうが、 実装してありません。 実装するだけの価値があるほど有用なのかはっきりしないのです。


Node:Window Hooks, Previous:Window Configurations, Up:Windows

ウィンドウのスクロールとサイズ変更向けのフック

本節では、ウィンドウにバッファの別の部分を表示したり 別のバッファを表示するたびに、 Lispプログラムが動作する方法を述べます。 変更できる動作は3種類、ウィンドウをスクロールするとき、 ウィンドウでバッファを切り替えるとき、 ウィンドウサイズを変えるときです。 最初の2つの動作ではwindow-scroll-functionsを実行し、 3つ目はwindow-size-change-functionsを実行します。 これらのフックの模範的な使用例は遅延ロック(lazy-lock)モードの 実装の中にあります。 Support Modesを参照してください。

window-scroll-functions Variable
この変数は、スクロールによりウィンドウを再表示するまえに Emacsが呼び出すべき関数のリストを保持する。 各関数はウィンドウと新たな表示開始位置の2つの引数で呼ばれるため、 これはノーマルフックではない。

ウィンドウに別のバッファを表示する場合でも これらの関数が実行される。

これらの関数でwindow-end(see Window Start)を使うには 注意が必要である。 更新された値が必要なときには、確実に更新値を得るために 引数updateを使う必要がある。

window-size-change-functions Variable
この変数は、いかなる理由であれウィンドウサイズが変わるときに 呼び出される関数のリストを保持する。 関数は、再表示のたびにサイズ変更が起きたフレームごとに呼ばれる。

各関数はフレームを唯一の引数として受け取る。 当該フレームで大きさが変更されたウィンドウを探す直接的な方法や 正確な方法はない。 しかし、サイズ変更関数が呼ばれるたびに 既存のウィンドウとそれらの大きさを記録すれば、 現在の大きさと以前の大きさを比較できる。

ウィンドウを作成したり削除してもサイズ変更とみなすので、 これらの関数が呼び出される。 フレームの大きさが変わると既存のウィンドウの大きさも変わるので、 これもサイズ変更とみなす。

これらの関数でsave-window-excursion (see Window Configurations)を使うのはよくない。 この関数はつねにサイズ変更とみなしこれらの関数を呼び出し、 これが繰り返されてしまうからである。 多くの場合、ここで必要なのはsave-selected-window (see Selecting Windows)である。

redisplay-end-trigger-functions Variable
このアブノーマルフックは、ウィンドウの再表示において、 指定された終了トリガ位置を超えて伸びるテキストを使うたびに実行される。 終了トリガ位置は関数set-window-redisplay-end-triggerで設定する。 フック関数は2つの引数、ウィンドウと終了トリガ位置で呼ばれる。 終了トリガ位置としてnilを保存するとこの機能をオフにし、 フックを実行直後にトリガ値は自動的にnilに再設定される。

set-window-redisplay-end-trigger window position Function
この関数は、windowの終了トリガ位置をpositionとする。

window-redisplay-end-trigger window Function
この関数は、windowの現在の終了トリガ位置を返す。

window-configuration-change-hook Variable
このノーマルフックは、 既存のフレームのウィンドウの構成を変更するたびに呼び出される。 これには、ウィンドウの分割や削除、ウィンドウサイズの変更、 ウィンドウに別のバッファを表示することが含まれる。 このフックを実行するときには、 ウィンドウの構成が変更されたフレームが選択されているフレームである。


Node:Frames, Next:, Previous:Windows, Up:Top

フレーム

フレーム(frame)とは、1つかそれ以上のEmacsのウィンドウを 収めているスクリーン上の矩形です。 フレームには最初は1つのウィンドウ(およびミニバッファ用ウィンドウ)が ありますが、それを上下や左右に小さなウィンドウに分割できます。

Emacsを文字端末で実行すると、 1つの端末フレーム(terminal frame)を使います。 別のフレームを作成すると、もちろん端末画面上では、 Emacsは一度に1つのフレームしか表示しません。

EmacsがXウィンドウのような対応しているウィンドウシステムと 直接通信しているときには、端末フレームは使いません。 そのかわりに、1つのウィンドウフレーム(window frame)で始まりますが、 いくつでもフレームを作れますし、ウィンドウシステムでは普通のことですが、 Emacsはそのようなフレームを同時に複数表示できます。

framep object Function
この関数は、objectがフレームならばtを返し、 さもなければnilを返す。

Emacsの再表示の制御に関連する情報についてはSee Display


Node:Creating Frames, Next:, Up:Frames

フレームの作成

新たなフレームを作成するには、関数make-frameを呼び出します。

make-frame &optional alist Function
この関数は新たなフレームを作成する。 対応しているウィンドウシステムを使っていれば、ウィンドウフレームを作る。 さもなければ端末フレームを作る。

引数alistはフレームパラメータを指定する連想リストである。 alistで指定していないパラメータは、 変数default-frame-alistの値に従って決まる。 それでも決まらないパラメータは、 標準のXリソースやそれにかわる読者のシステムの設定を使う。

指定可能なパラメータは、Emacsがフレームの表示に使う ウィンドウシステムの種類に原理的には依存します。 指定可能な各パラメータの説明は、see Window Frame Parameters

before-make-frame-hook Variable
make-frameがフレームを実際に作成する直前に実行するノーマルフック。

after-make-frame-hook Variable
make-frameがフレームを作成後に実行するアブノーマルフック。 after-make-frame-hookの各関数は、1つの引数、 つまり、作成したばかりのフレームを受け取る。


Node:Multiple Displays, Next:, Previous:Creating Frames, Up:Frames

複数ディスプレイ

1つのEmacsは複数のXディスプレイと通信できます。 Emacsは始めは1つのディスプレイ、つまり、 環境変数DISPLAYかオプション--display (see Initial Options)で決まる ものを使います。 別のディスプレイに接続するには、 コマンドmake-frame-on-displayを使うか、 フレームを作るときにフレームパラメータdisplayを指定します。

Emacsは各Xサーバーを別々の端末として扱い、 それらのおのおのには選択されているフレームと ミニバッファ用ウィンドウがあります。

少数のLisp変数は端末にローカル(terminal-local)です。 つまり、各端末ごとに別々の束縛があります。 ある時点で有効な束縛は、選択されているフレームが属する端末のものです。 このような変数には、default-minibuffer-framedefining-kbd-macrolast-kbd-macrosystem-key-alistがあります。 これらはつねに端末にローカルであり、 バッファローカル(see Buffer-Local Variables)や フレームローカルにはけっしてなりません。

1つのXサーバーは複数のスクリーンを扱えます。 ディスプレイ名host:server.screenには3つの部分があり、 最後の部分で指定したサーバーのスクリーン番号を指定します。 1つのサーバーに属する2つのスクリーンを使うと、 Emacsはそれらの名前の類似性からそれらが1つのキーボードを共有していると判断し、 それらのスクリーンを1つの端末として扱います。

make-frame-on-display display &optional parameters コマンド
新たなフレームをディスプレイdisplay上に作成する。 他のフレームパラメータはparametersから得る。 引数displayを除けばmake-frame(see Creating Frames)と 同様である。

x-display-list Function
Emacsが接続しているXディスプレイを表すリストを返す。 リストの要素は文字列であり、それぞれはディスプレイ名である。

x-open-connection display &optional xrm-string Function
この関数はXディスプレイdisplayとの接続を開く。 当該ディスプレイ上にフレームは作らないが、 これにより当該ディスプレイと通信可能かどうか検査できる。

省略可能な引数xrm-stringnilでなければ、 ファイル.Xresourcesで使われ書式と同じ リソース名と値を表す文字列である。 これに指定した値は、Xサーバー自体に記録されているリソースの値に優先し、 Emacsが当該ディスプレイ上に作成するすべてのフレームに適用される。 この文字列の例を以下に示す。

"*BorderWidth: 3\n*InternalBorder: 2\n"

see Resources

x-close-connection display Function
この関数はディスプレイdisplayとの接続を閉じる。 これを行うまえに、 まず当該ディスプレイ上に作ったフレームをすべて削除しておくこと。


Node:Frame Parameters, Next:, Previous:Multiple Displays, Up:Frames

フレームパラメータ

フレームには、その見ためやふるまいを制御する多くのパラメータがあります。 フレームのパラメータの種類は、使用する表示機構に依存します。

フレームパラメータはウィンドウシステム向けです。 端末フレームにはごく少数のパラメータがありますが、 そのほとんどは互換性のためであり、 heightwidthnametitlebuffer-listbuffer-predicateのパラメータだけが意味を持ちます。


Node:Parameter Access, Next:, Up:Frame Parameters

フレームパラメータの参照

これらの関数は、フレームのパラメータの値を読んだり変更するためのものです。

frame-parameters frame Function
関数frame-parametersは、 frameのすべてのパラメータとそれらの値から成る連想リストを返す。

modify-frame-parameters frame alist Function
この関数は、alistの要素に基づいてフレームframeの パラメータを変更する。 alistの各要素は(parm . value)の形であり、 parmはパラメータを表すシンボルである。 alistに指定しないパラメータの値は変更されない。


Node:Initial Parameters, Next:, Previous:Parameter Access, Up:Frame Parameters

初期フレームのパラメータ

読者のファイル.emacsinitial-frame-alistに設定すれば、 起動時の初期フレームのパラメータを指定できます。

initial-frame-alist Variable
この変数の値は、初期フレームを作るときに 使用するパラメータの値から成る連想リストである。 この変数を指定すれば初期フレームの見ためを指定できるが、 それ以降に作成するフレームには影響しない。 各要素はつぎの形である。
(parameter . value)

Emacsは読者のファイル~/.emacsを読むまえに初期フレームを作る。 このファイルを読んだあとに、Emacsはinitial-frame-alistを検査し 異なる値が設定されているパラメータをすでに作成した初期フレームに適用する。

これらの設定がフレームの大きさと位置や見ために関するものであると、 指定とは違うフレームが現れてから指定したものに変わるのを目にする。 これがわずらわしい場合には、Xリソースにも同じ大きさと位置や見ためを指定する。 Xリソースはフレームを作成するまえに適用される。 see Resources X

Xリソースの設定は、典型的にはすべてのフレームに適用される。 初期フレームだけに特定のXリソースを指定し、 それ以降のフレームに適用したくない場合には、つぎのようにする。 パラメータをdefault-frame-alistで指定し、 以降のフレーム向けのXリソースを無効にする。 そしてそれらが初期フレームに影響しないように、 initial-frame-alistのパラメータでXリソースに一致する値を指定する。

これらのパラメータにミニバッファ専用のフレームを作る (minibuffer . nil)を指定しているのに ミニバッファ専用フレームを作っていないと、Emacsがそれを作成します。

minibuffer-frame-alist Variable
この変数の値は、初期のミニバッファ専用フレームを作るときに使用する パラメータの連想リストである。 初期フレームのパラメータからミニバッファ専用フレームが 必要であると判断するとそれを作る。

default-frame-alist Variable
これは、Emacsのすべてのフレーム、つまり、 初期フレームとそれ以降のフレームのフレームパラメータのデフォルト値を 指定する連想リストである。 Xウィンドウシステムを使っているときには、多くの場合、 Xリソースによっても同じ結果を得られる。
Choosing Windowspecial-display-frame-alistも 参照してください。

Emacsを起動するときにウィンドウの見ためを指定するオプションを使うと、 それらはdefault-frame-alistに要素を追加することで効果を発揮します。 1つの例外は-geometryで、指定位置はinitial-frame-alistに 追加されます。 See Command Arguments


Node:Window Frame Parameters, Next:, Previous:Initial Parameters, Up:Frame Parameters

ウィンドウフレームのパラメータ

フレームのパラメータの種類は、使用する表示機構に依存します。 ウィンドウフレームにおいて特別な意味を持つパラメータの一覧をつぎに示します。 これらのうち、nametitleheightwidthbuffer-listbuffer-predicateは 端末フレームでも意味を持ちます。

display
このフレームを開くディスプレイ。 環境変数DISPLAYと同様に、 "host:dpy.screen"の形の文字列であること。
title
フレームのタイトルtitlenil以外であると、 フレーム向けのウィンドウシステムの枠にタイトルが現れる。 また、mode-line-frame-identification%F (see %-Constructs)を使っていれば、 当該フレームのモード行にもタイトルが現れる。 Emacsがウィンドウシステムを使っていない場合には、 これは普通はモード行に表示され一度に1つのフレームだけを表示できる。 see Frame Titles
name
フレームの名前。 パラメータtitleを指定しないかnilであると、 フレーム名はフレームタイトルのデフォルトになる。 nameを指定しないと、Emacsが自動的にフレーム名を設定する (see Frame Titles)。

フレームを作るときにフレーム名を明示的に指定すると、 その名前は(Emacsの実行形式ファイルの名前のかわりに) フレーム向けのXリソースを探すためにも使われる。

left
スクリーンの左端を基準にしたピクセル単位の左端位置。 この値は正の数posであるか、 負のposの値を指定できる(+ pos)の形のリストである。

負の数-pos(- pos)の形のリストは、 実際には、スクリーンの右端を基準にしたウィンドウの右端位置を指定する。 posの正の値は左へ向けて数える。 注意: パラメータが負の整数-posであると、 posは正である。

プログラムが指定した位置を無視するウィンドウマネージャもある。 指定した位置が無視されないように保証したい場合には、 パラメータuser-positionにもnil以外の値を指定する。

top
スクリーンの上端を基準にしたピクセル単位の上端位置。 この値は正の数posであるか、 負のposの値を指定できる(+ pos)の形のリストである。

負の数-pos(- pos)の形のリストは、 実際には、スクリーンの下端を基準にしたウィンドウの下端位置を指定する。 posの正の値は上へ向けて数える。 注意: パラメータが負の整数-posであると、 posは正である。

プログラムが指定した位置を無視するウィンドウマネージャもある。 指定した位置が無視されないように保証したい場合には、 パラメータuser-positionにもnil以外の値を指定する。

icon-left
スクリーンの左端を基準にした フレームのアイコンのピクセル単位の左端位置。 フレームをアイコンにしたときに効果を発揮する。
icon-top
スクリーンの上端を基準にした フレームのアイコンのピクセル単位の上端位置。 フレームをアイコンにしたときに効果を発揮する。
user-position
パラメータlefttopでスクリーン上の位置を指定して フレームを作るときに、このパラメータは指定位置が、 (利用者がなんらかの方法で与えた)ユーザー指定のものなのか、 (プログラムが選んだ)プログラム指定のものなのかを指定する。 nil以外の値であるとユーザー指定の位置であることを意味する。

ウィンドウマネージャはユーザー指定の位置を一般に尊重し、 プログラム指定の位置も尊重するものもある。 しかしその多くはプログラム指定の位置を無視し、 デフォルトに基づいてウィンドウを配置したり、 マウスでユーザーに配置させる。 twmを含むウィンドウマネージャには、 プログラム指定の位置に従うかそれらを無視するかを ユーザーが指定できるものもある。

make-frameを呼び出すときには、 パラメータlefttopの値がユーザーの希望を表す場合には このパラメータの値にはnil以外を指定すること。 さもなければnilを指定する。

height
フレームの内側の文字単位の高さ。 (ピクセル単位の高さを得るにはframe-pixel-heightを呼び出す。 Size and Positionを参照。)
width
フレームの内側の文字単位の幅。 (ピクセル単位の幅を得るにはframe-pixel-widthを呼び出す。 Size and Positionを参照。)
window-id
フレームとして使うウィンドウシステムのウィンドウ番号。
minibuffer
このフレームに独自のミニバッファがあるかどうかを表す。 値tはあることを表し、nilはないことを表す。 onlyは、このフレームがミニバッファだけであることを表す。 (別のフレームの)値がミニバッファだけであると、 新たなフレームはそのミニバッファを使う。
buffer-predicate
このフレーム向けのバッファ述語関数。 これがnilでなければ、 関数other-bufferが(選択されているフレームから)この述語を使用して、 どのバッファにするかを決定する。 other-bufferは各バッファごとにバッファを引数としてこの述語を呼び出す。 この述語がnil以外を返すと当該バッファを選ぶ。
buffer-list
このフレームで選択されたバッファを もっとも最近に選択されたものから順に並べたリスト。
font
フレーム内でテキストの表示に使うフォントの名前。 これは、読者のシステムにおいて正しいフォントの名前であるか Emacsのフォントセット(see Fontsets)の名前を表す文字列である。
auto-raise
フレームを選択したときにフレームを手前に移動するかどうかを表す (nil以外であるとそのようにする)。
auto-lower
フレームの選択を止めたときにフレームを奥へ移動するかどうかを表す (nil以外であるとそのようにする)。
vertical-scroll-bars
フレームに垂直スクロール用のスクロールバーを付けるかどうか、 どちら側に付けるかを表す。 指定できる値は、leftright、あるいは スクロールバーなしを意味するnil
horizontal-scroll-bars
水平スクロール用のスクロールバーを付けるかどうかを表す (nil以外だと付ける)。 (水平スクロールバーはいまのところ実装してない。)
scroll-bar-width
垂直スクロールバーのピクセル単位の幅。
icon-type
このフレームをアイコンにしたときに使うアイコンの種類。 値が文字列であると、使用するビットマップを収めたファイルを指定する。 それ以外のnil以外の値はデフォルトのビットマップアイコン (gnuの絵)を指定する。 nilはテキストのアイコンを指定する。
icon-name
このフレーム向けのアイコンを表示するときに使用するアイコンの名前。 これがnilであると、フレームのタイトルを使う。
foreground-color
文字の描画に使う表示色。 これは文字列である。 ウィンドウシステムが妥当な表示色の名称を定義する。

フレームパラメータforeground-colorに設定したときには、 それに対応してフェイスを更新するために frame-update-face-colorsを呼び出すこと。

background-color
文字の背景に使う表示色。

フレームパラメータbackground-colorに設定したときには、 それに対応してフェイスを更新するために frame-update-face-colorsを呼び出すこと。 see Face Functions

background-mode
背景色が明るいか暗いかにしたがって、 このパラメータはdarklightである。
mouse-color
マウスポインタの表示色。
cursor-color
ポイントを表すカーソルの表示色。
border-color
フレームの枠の表示色。
display-type
このパラメータはこのフレームで使用可能な表示色の範囲を表す。 値は、colorgrayscalemonoのいずれかである。
cursor-type
カーソルの表示方法。 正しい値は、barbox(bar . width)のいずれかである。 シンボルboxは、ポイント直後の文字に重なる通常の黒い箱型の カーソルを指定し、これがデフォルトである。 シンボルbarは、カーソルとして文字のあいだに縦棒を置く指定である。 (bar . width)は、ピクセル幅widthの縦棒を指定する。
border-width
ウィンドウ枠のピクセル単位の幅。
internal-border-width
枠とテキストのあいだのピクセル単位の間隔。
unsplittable
nil以外であると、このフレームのウィンドウをけっして自動的に分割しない。
visibility
フレームの可視性。 不可視を表すnil、可視を表すt、 アイコンになっていることを表すiconの3の可能性がある。 see Visibility of Frames
menu-bar-lines
フレームの上端に割り当てるメニューバー向けの行の個数。 デフォルトは1である。 see Menu Bar。 (Xツールキットを使うEmacsでは、メニューバーは1行だけである。 この場合、0より大きな数を指定したかどうかに意味がある。)


Node:Size and Position, Previous:Window Frame Parameters, Up:Frame Parameters

フレームのサイズと位置

フレームパラメータlefttopheightwidthを 使って、フレームのサイズや位置を読み取ったり変更できます。 指定しなかった大きさと位置のパラメータは、 ウィンドウマネージャが通常どおりに選びます。

以下はサイズや位置を操作する特別な機能です。

set-frame-position frame left top Function
この関数は、フレームframeの左上隅の位置を left(左端)とtop(上端)にする。 これらの引数は、スクリーンの左上隅からピクセル単位で数える。

パラメータ値が負であると、スクリーンの下端から測ってウィンドウの下端を 位置決めしたり、スクリーンの右端から測ってウィンドウの右端を位置決めする。 つねに左端や上端から測った値にして、負の値はフレームを スクリーンの上端や左端から部分的にはみ出して位置決めする 意味にするほうがよいかもしれないが、 現状ではそのように変えるのは不適当と思われる。

frame-height &optional frame Function
frame-width &optional frame Function
この関数は、フレームframeの高さや幅を行単位やコラム単位で返す。 frameを指定しないと、選択されているフレームを使う。

screen-height Function
screen-width Function
これらの関数はframe-heightframe-widthの古い別名である。 文字端末を使っている場合、通常、フレームの大きさは 端末スクリーンの大きさと同じである。

frame-pixel-height &optional frame Function
frame-pixel-width &optional frame Function
これらの関数は、フレームframeの高さや幅をピクセル単位で返す。 frameを指定しないと、選択されているフレームを使う。

frame-char-height &optional frame Function
frame-char-width &optional frame Function
これらの関数は、フレーム内の文字の高さや幅をピクセル単位で返す。 frameを指定しないと、選択されているフレームを使う。

set-frame-size frame cols rows Function
この関数は、フレームframeの大きさを文字単位で指定する。 colsrowsは、新たな幅と高さを指定する。

ピクセル単位で大きさを指定するには、 frame-char-heightframe-char-widthで ピクセル単位の値を文字単位に変換する。

set-frame-height frame lines &optional pretend Function
この関数は、フレームframeの高さをlines行に変える。 それに合わせてframe内の既存のウィンドウの大きさは比例して変わる。

pretendnil以外であると、 Emacsはframelinesだけを表示するが、 フレームの実際の高さは変更しない。 これは端末フレームでのみ有用である。 実際の端末より小さな高さを使うと、小さなスクリーンでの動作を再現したり、 スクリーン全体を使うと端末が誤動作するような場合に有用である。 フレームの『実際』の高さを指定してもつねにそうなるとは限らない。 端末フレーム上で正しくカーソルを位置決めするには、 実サイズを知る必要がある場合もあるからである。

set-frame-width frame width &optional pretend Function
この関数は、フレームframeの幅を設定する。 引数pretendset-frame-heightと同じ意味を持つ。

set-screen-heightset-screen-widthの古い関数は、 複数フレームを扱えないEmacsの版でスクリーンの高さや幅を 指定するために使われていました。 これらはほぼ廃れていますが、まだ動作します。 これらは選択されているフレームに適用されます。

x-parse-geometry geom Function
関数x-parse-geometryは、Xウィンドウの標準のジオメトリ文字列を make-frameの引数の一部に使えるように連想リストに変換する。

この連想リストは、geomで指定されているパラメータとその値を記述する。 各要素は(parameter . value)の形である。 parameterの可能な値は、 lefttopwidthheightである。

大きさを表すパラメータでは、その値は整数であること。 位置を表すパラメータでは、右端や下端の位置を表す値もあるので、 lefttopというパラメータ名は必ずしも正確ではない。 位置を表すパラメータの可能なvalueはつぎのとおりである。

整数
正の整数は、ウィンドウの左端や上端をスクリーンの左端や上端に関連付ける。 負の整数は、ウィンドウの右端や下端をスクリーンの右端や下端に関連付ける。
(+ position)
スクリーンの左端や上端を基準にしたウィンドウの左端や上端の位置を指定する。 整数positionは正でも負でもよいが、 負の値はスクリーンからはみ出した位置を指定する。
(- position)
スクリーンの右端や下端を基準にしたウィンドウの右端や下端の位置を指定する。 整数positionは正でも負でもよいが、 負の値はスクリーンからはみ出した位置を指定する。

例を示す。

(x-parse-geometry "35x70+0-0")
     => ((height . 70) (width . 35)
         (top - 0) (left . 0))


Node:Frame Titles, Next:, Previous:Frame Parameters, Up:Frames

フレームタイトル

各フレームにはパラメータnameがあります。 これは、典型的にはウィンドウシステムがフレームの先頭に表示する フレームタイトルのデフォルトにもなります。 フレーム属性nameに設定することで明示的に名前を指定できます。

通常は名前を明示的に指定しないでしょうから、 変数frame-title-formatに保持してある雛型から Emacsが自動的にフレーム名を計算します。 Emacsは、フレームを再表示するたびに名前を再計算します。

frame-title-format Variable
この変数は、読者がフレーム名を明示的に指定しなかったときの フレーム向けの名前の計算方法を指定する。 変数の値は実際には、mode-line-formatのようなモード行構成である。 see Mode Line Data

icon-title-format Variable
この変数は、フレームタイトルを明示的に指定しなかったときの アイコンにしたフレーム向けの名前の計算方法を指定する。 これはアイコンそのものに現れる。

multiple-frames Variable
この変数はEmacsが自動的に設定する。 (ミニバッファ専用のフレームや不可視フレームを数えずに) 複数個のフレームがあるとこの値がtである。 frame-title-formatのデフォルト値ではmultiple-framesを使っており、 複数のフレームがあるときに限りフレームタイトルにバッファ名が入るようにする。


Node:Deleting Frames, Next:, Previous:Frame Titles, Up:Frames

フレームの削除

フレームを明示的に削除(delete)しない限り、 フレームは見える可能性があります。 フレームを削除するとスクリーンに表示できなくなりますが、 それを参照するものがなくならない限りLispオブジェクトとしては存在し続けます。 保存したフレーム構成(see Frame Configurations)を復元する以外には、 フレームの削除を取り消すことはできません。 これはウィンドウと同様です。

delete-frame &optional frame コマンド
この関数はフレームframeを削除する。 デフォルトでは、frameは選択されているフレームである。

frame-live-p frame Function
関数frame-live-pは、フレームframeが削除されていなければ nil以外を返す。

ウィンドウを削除するコマンドを与えるウィンドウマネージャもあります。 それらは、ウィンドウを操作しているプログラムに特別なメッセージを 送ることで動作します。 Emacsがそのようなコマンドを受け取ると、 イベントdelete-frameを生成します。 このイベントの普通の定義は、関数delete-frameを呼び出すコマンドです。 See Misc Events


Node:Finding All Frames, Next:, Previous:Deleting Frames, Up:Frames

すべてのフレームを探す

frame-list Function
関数frame-listは、削除されていないすべてのフレームから成るリストを返す。 これは、バッファに対するbuffer-listに相当する。 得られるリストは新たに作成したものであり、 このリストを変更してもEmacs内部にはなんの効果もない。

visible-frame-list Function
この関数は、現在可視のフレームだけのリストを返す。 see Visibility of Frames。 (選択されているフレームだけが実際に表示されている場合でも、 端末フレームはすべてつねに『可視』とみなす。)

next-frame &optional frame minibuf Function
関数next-frameにより、 任意の位置から始めてすべてのフレームを便利に巡回できる。 巡回順の中でframeの『つぎ』のフレームを返す。 frameを省略したりnilであると、 デフォルトでは選択されているフレームを使う。

第2引数minibufは、対象とするフレームを指定する。

nil
ミニバッファ専用のフレームを除外する。
visible
すべての可視なフレームを対象にする。
0
すべての可視なフレームやアイコンにしたフレームを対象にする。
ウィンドウ
ミニバッファとして特定のウィンドウを使っているフレームのみを対象にする。
その他
すべてのフレームを対象にする。

previous-frame &optional frame minibuf Function
next-frameと同様であるが、すべてのフレームを逆方向に巡回する。
Cyclic Window Orderingnext-windowprevious-windowも 参照してください。


Node:Frames and Windows, Next:, Previous:Finding All Frames, Up:Frames

フレームとウィンドウ

各ウィンドウはある1つのフレームだけの一部であり、 window-frameで当該フレームを得られます。

window-frame window Function
この関数は、windowが属するフレームを返す。

フレーム内のミニバッファ用以外のすべてウィンドウには、 巡回順序がついています。 その順序は、フレームの左上隅の先頭のウィンドウから始まって、 右下隅のウィンドウ(フレームにミニバッファがあれば、 これはつねにミニバッファ用ウィンドウ)に達するまで下向き右向きに進み、 そして先頭へ戻ります。

frame-top-window frame Function
この関数は、フレームframeのもっとも上端のもっとも左端の 先頭のウィンドウを返す。

ある時点では、各フレームではたった1つのフレームが 当該フレームで選択されているのです。 このような区別の意味は、 フレームを選択するとそのようなウィンドウも選択されるということです。 フレームで現在選択されているフレームは frame-selected-windowで得られます。

frame-selected-window frame Function
この関数は、フレームframeで選択されている frame内のウィンドウを返す。

逆に、select-windowでEmacsのウィンドウを選ぶと、 それがそのフレームで選択されているウィンドウになります。 see Selecting Windows

指定したフレームのウィンドウの1つを返す別の関数は minibuffer-windowです。 See Minibuffer Misc


Node:Minibuffers and Frames, Next:, Previous:Frames and Windows, Up:Frames

ミニバッファとフレーム

通常、各フレームにはそれ独自のミニバッファ用ウィンドウが底にあり、 フレームが選択されているときにはいつもそれが使われます。 フレームにミニバッファがあれば、minibuffer-window (see Minibuffer Misc)でそれを得られます。

しかし、ミニバッファのないフレームを作ることもできます。 そのようなフレームでは、別のフレームのミニバッファ用ウィンドウを 使う必要があります。 そのようなフレームを作成するときには、 使用する(他のフレームの)ミニバッファを明示的に指定できます。 そうしないと、変数default-minibuffer-frameの値で指定される フレームのミニバッファを使います。 その値は、ミニバッファを有したフレームである必要があります。

ミニバッファ専用のフレームを使うときは、 ミニバッファで入力するときにそのフレームが 自動的に手前にくるようにしたいでしょう。 そうしたい場合には、変数minibuffer-auto-raisetに設定します。 See Raising and Lowering

default-minibuffer-frame Variable
この変数は、デフォルトで使うミニバッファ用ウィンドウのフレームを指定する。 この変数は現在の端末につねにローカルであり、 バッファローカルにはなりえない。 see Multiple Displays


Node:Input Focus, Next:, Previous:Minibuffers and Frames, Up:Frames

入力フォーカス

ある時点では、Emacsの1つのフレームが選択されているフレーム (selected frame)です。 選択されているウィンドウは選択されているフレームの中につねにあります。

selected-frame Function
この関数は選択されているフレームを返す。

マウスが入っているウィンドウにキーボード入力を振り向ける ウィンドウシステムやウィンドウマネージャがあります。 ウィンドウにフォーカスを置くために、 明示的にクリックしたりコマンドを必要とするものもあります。 いずれであっても、Emacsはどのフレームにフォーカスがあるかを 自動的に追跡します。

Lispプログラムからは、関数select-frameを呼ぶことで、 『一時的に』フレームを切り替えることもできます。 これは、ウィンドウシステムのフォーカスは変えません。 というよりは、プログラムで指定するまで ウィンドウシステムの制御を回避します。

文字端末を使っているときには、 選択されているフレームのみが端末に実際に表示されます。 フレームを切り替える唯一の方法はswitch-frameであり、 それ以降にswitch-frameを呼び出すまで切り替えた効果は持続します。 初期フレーム以外の各端末フレームには番号が付いていて、 選択されているフレームの番号がモード行内のバッファ名のまえに現れます (see Mode Line Variables)。

select-frame frame Function
この関数はフレームframeを選択し、 Xサーバーのフォーカスを一時的に無視する。 frameを選択している状態は、 ユーザーが別のフレームを選択する動作を行うか 再度この関数が呼ばれるまで持続する。

サーバーやウィンドウマネジャーの要請にしたがって フレームを選択するようにして、 Emacsはウィンドウシステムと協調します。 必要なときにはfocusイベントと呼ばれる特別な入力イベントを 生成することでこのようにします。 コマンドループはhandle-switch-frameを呼び出すことで イベントfocusを処理します。 See Focus Events

handle-switch-frame frame コマンド
この関数は、フレームframeを選択することでフォーカスイベントを 処理する。

フォーカスイベントは、通常、このコマンドを起動することで処理される。 それ以外の理由ではこれを呼び出さないこと。

redirect-frame-focus frame focus-frame Function
この関数は、フォーカスをframeからfocus-frameへ振り向ける。 つまり、以降の打鍵やイベントは、focusではなく、 focus-frameが受け取ることになる。 そのようなイベントのあとでは、 last-event-frameの値はfocus-frameになる。 また、focusを指定したイベントswitch-frameは、 focus-frameを選ぶことになる。

focus-framenilであると、frameでの振り向けを取り消す。 つまり、frameはイベントをふたたび受けるようになる。

フォーカスの振り向けの用途の1つは、 ミニバッファを持たないフレームのためである。 これらのフレームでは、別のフレームのミニバッファを使う。 別のフレームのミニバッファを活性にすると、 フォーカスを当該フレームへ振り向ける。 これにより、ミニバッファを活性にしたフレームにマウスが入っていても、 ミニバッファのフレームにフォーカスを置ける。

フレームを選択してもフォーカスの振り向けを変更する。 フレームfooを選択しているときにフレームbarを選択すると、 fooへの振り向けをbarへ振り向けるように変更する。 これにより、select-windowを使ってユーザーが 別のフレームへ切り替えても、フォーカスの振り向けが正しく動作する。

これは、フォーカスを自分自身へ振り向けているフレームは、 フォーカスを振り向けていないフレームとは異なる扱いを受けることを意味する。 select-frameは前者に影響するが後者には影響しない。

redirect-frame-focusで変更するまで、振り向けは持続する。

focus-follows-mouse User Option
このオプションは、ユーザーがマウスを動かしたときに ウィンドウマネージャがフォーカスを移動するかどうかをEmacsに伝える。 nil以外であるとフォーカスが移動することを意味する。 その場合、コマンドother-frameは、 新たに選択されたフレームに適合するような位置にマウスを移動する。


Node:Visibility of Frames, Next:, Previous:Input Focus, Up:Frames

フレームの可視性

ウィンドウフレームは、可視不可視アイコンになっているのいずれかです。 フレームが可視であると、その内容を見ることができます。 アイコンになっているとフレームの内容はスクリーンで見えませんが、 アイコンは見えます。 フレームが不可視であると、それはスクリーン上に見えず アイコンでもありません。

端末フレームは選択されているものだけが表示されるので、 端末フレームでは可視性は意味がありません。

make-frame-visible &optional frame コマンド
この関数は、フレームframeを可視にする。 frameを省略すると、選択されているフレームを可視にする。

make-frame-invisible &optional frame コマンド
この関数は、フレームframeを不可視にする。 frameを省略すると、選択されているフレームを不可視にする。

iconify-frame &optional frame コマンド
この関数は、フレームframeをアイコンにする。 frameを省略すると、選択されているフレームをアイコンにする。

frame-visible-p frame Function
この関数は、フレームframeの可視性を返す。 その値は、frameが可視ならばt、 不可視ならばnil、アイコンになっていればiconである。

フレームの可視性は、フレームパラメータとしても得られます。 フレームパラメータとして読んだり変更できます。 See Window Frame Parameters

ユーザーは、ウィンドウマネージャを用いて フレームをアイコンにしたりアイコンを開けます。 これは、Emacsが制御できるレベルよりしたで行われますが、 Emacsはそのような変更を追跡できるようにイベントを提供します。 See Misc Events


Node:Raising and Lowering, Next:, Previous:Visibility of Frames, Up:Frames

フレームを手前にしたり奥へ置く

ほとんどのウィンドウシステムでは、机のたとえを使います。 つまり、スクリーンの面に垂直な方向を概念的な3軸目と考えて、 ウィンドウは積み重なっていて、 もっとも手前からもっとも奥に順序がついています。 2つのウィンドウが重なり合っているところでは、 手前のものがそのしたのものを隠しています。 もっとも奥にあるウィンドウであっても、 それに重なるウィンドウがなければ見ることができます。

ウィンドウのこのような順序は固定されていません。 実際、ユーザーは順序を頻繁に変更します。 ウィンドウを手前に置く(raising)とは、 ウィンドウを積み重ねのもっとも上に移動することです。 ウィンドウを奥に置く(lowering)とは、 ウィンドウを積み重ねのもっとも下に移動することです。 この移動は概念的な3軸目に限り、 スクリーン上でのウィンドウの位置は変えません。

Emacsのフレームを表すウィンドウは、つぎの関数で 手前へ置いたり奥へ置けます。

raise-frame &optional frame コマンド
この関数は、フレームframeを手前に置く (デフォルトは選択されているフレーム)。

lower-frame &optional frame コマンド
この関数は、フレームframeを奥に置く (デフォルトは選択されているフレーム)。

minibuffer-auto-raise User Option
これがnil以外であると、ミニバッファが活性になると ミニバッファ用ウィンドウがあるフレームを手前に置く。

フレームパラメータを使うと、フレームが 選択されると自動的に手前に置いたり(auto-raise)、 選択を止めると奥へ置け(auto-lower)ます。 See Window Frame Parameters


Node:Frame Configurations, Next:, Previous:Raising and Lowering, Up:Frames

フレーム構成

フレーム構成(frame configuration)は、 現在のフレームの配置、それらのすべての属性、それぞれのウィンドウ構成を 記録したものです。 (see Window Configurations。)

current-frame-configuration Function
この関数は、現在のフレームの配置とそれらの内容を記述した フレーム構成のリストを返す。

set-frame-configuration configuration Function
この関数は、configurationで記述されたフレームの状態に復元する。


Node:Mouse Tracking, Next:, Previous:Frame Configurations, Up:Frames

マウスの追跡

マウスを追跡(track)できると有用なことがあります。 つまり、マウスがどこにあるかを表す指示子を表示して マウスの移動に従って指示子を動かすのです。 効率よくマウスを追跡するには、マウスが実際に移動するまで待つ手段が必要です。

マウスを追跡する便利な方法は、マウスの移動を表すイベントを待つことです。 そうすれば、そのようなイベントを待てばマウスの移動を待てます。 さらに、発生しうるそれ以外の種類のイベントを扱うのも簡単です。 普通はマウスを永遠に追跡し続けたいのではなく ボタンを離すなどの別のイベントを待ちたいのでしょうから、 これは有用です。

track-mouse body... Special Form
このスペシャルフォームは、マウスモーションイベントを生成するようにして bodyを実行する。 典型的にはbodyではread-eventを使って モーションイベントを読み、それに従って表示を変更する。 マウスモーションイベントの形式については、 see Motion Events

track-mouseの値はbodyの最後のフォームの値である。 bodyは、ボタンを離したことを表すイベントや 追跡を終えるべきイベントに出会うと戻るように設計すること。

マウスの移動を追跡する普通の目的は、 現在の位置でボタンを押したり離すとなにが起こるかを スクリーン上に示すことです。

多くの場面では、テキスト属性mouse-face(see Special Properties) を使えば、マウスを追跡する必要はなくなります。 これはとても低いレベルで動作し、 Lispレベルでマウスを追跡するより滑らかに動作します。


Node:Mouse Position, Next:, Previous:Mouse Tracking, Up:Frames

マウスの位置

関数mouse-positionset-mouse-positionで、 マウスの現在位置を参照できます。

mouse-position Function
この関数は、マウスの位置を表すものを返す。 その値は(frame x . y)の形であり、 xyはフレームframeの内側の左上隅を基準にした 文字数で数えた位置を表す整数である。

set-mouse-position frame x y Function
この関数は、フレームframe内でxyの位置にマウスを移動する。 引数xyは整数であり、 フレームframeの内側の左上隅を基準にした文字数で数えた位置である。 frameが不可視であると、この関数はなにもしない。 戻り値には意味はない。

mouse-pixel-position Function
この関数はmouse-positionに似ているが、 文字単位ではなくピクセル単位で座標を返す。

set-mouse-pixel-position frame x y Function
この関数はset-mouse-positionのようにマウスを移動するが、 xyは文字単位でなくピクセル単位である。 これらの座標はフレームの内側にある必要はない。

frameが不可視であると、この関数はなにもしない。 戻り値には意味はない。


Node:Pop-Up Menus, Next:, Previous:Mouse Position, Up:Frames

ポップアップメニュー

ウィンドウシステムを使っているときには、 ユーザーがマウスで選択できるように Lispプログラムからメニューをポップアップできます。

x-popup-menu position menu Function
この関数はポップアップメニューを表示し、 ユーザーが行った選択を表す指示子を返す。

引数positionは、スクリーンのどこにメニューを置くかを指定する。 それはマウスのボタンイベント(ユーザーがボタンを押した場所にメニューを置く)か つぎの形のリストでもよい。

((xoffset yoffset) window)

ここで、xoffsetyoffsetは ウィンドウwindowのフレームの左上隅から測ったピクセル単位の座標である。

positiontであるとマウスの現在位置を使うことを意味する。 positionnilであると、 メニューを実際には表示せずに、 menuに指定してあるキーマップに等価なキーバインディングを あらかじめ計算することを意味する。

引数menuは、メニューに表示するものを指定する。 それはキーマップかキーマップのリストである(see Menu Keymaps)。 あるいは、つぎの形でもよい。

(title pane1 pane2...)

ここで、各ペインはつぎの形のリストである。

(title (line . item)...)

lineは文字列であり、 各itemは対応するlineが選ばれたときに返される値であること。

使用上の注意: メニューキーマップで定義したプレフィックスキーでできることには、 メニューを表示するためにx-popup-menuを使わないこと。 メニューキーマップを使ってメニューを実装すると、 C-h cC-h aで当該メニューの個々の項目を見ることができ、 それらに対するヘルプを提供できる。 x-popup-menuを呼び出すコマンドを定義してメニューを実装すると、 ヘルプ機能には当該コマンドの内側でなにがなされるかわからないので、 メニューの項目に対するヘルプを提供できない。

マウスの移動でサブメニューを切り替えられるメニューバーの機構では、 x-popup-menuを呼び出すコマンドの定義を調べられません。 したがって、x-popup-menuを使ってサブメニューを実装すると、 それらはメニューバーに適応した動作をできません。 このために、メニューバーのすべてのサブメニューは、 親メニュー内のメニューキーマップとして実装してあり、 x-popup-menuは使っていません。 See Menu Bar

メニューバーに内容が変化するサブメニューを使いたいときでも、 メニューキーマップを使って実装するべきです。 内容を変えるには、必要に応じてメニューキーの内容を更新するために menu-bar-update-hookにフック関数を追加します。


Node:Dialog Boxes, Next:, Previous:Pop-Up Menus, Up:Frames

対話ボックス

対話ボックスはポップアップメニューの変形です。 少々異なって見えますが、フレームの中央につねに現れ、 たった1つのレベルで1つのペインです。 対話ボックスの主な用途は、 ユーザーが『yes』、『no』、および他の少数の選択肢で答えるような 問い合わせを行うためです。 関数y-or-n-pyes-or-no-pは、 マウスクリックで起動されたコマンドから呼ばれると キーボードではなく対話ボックスを使います。

x-popup-dialog position contents Function
この関数は、対話ボックスを表示し、 ユーザーが選んだ選択肢を表す指示子を返す。 引数contentsは表示する選択肢を指定し、つぎの形である。
(title (string . value)...)

これは、x-popup-menuに対して単一のペインを指定するリストに似ている。

戻り値は、選ばれた選択肢のvalueである。

リストの要素は、(string . value)の形の コンスセルのかわりに単に文字列でもよい。 そうすると、対話ボックスでは選択できなくなる。

リストにnilが現れると、それは左側の項目と右側の項目を区切る。 nilのまえの項目は左側に現れ、 nilに続く項目は右側に現れる。 リストにnilを含めなければ、項目のほぼ半分がそれぞれの側に現れる。

対話ボックスはフレームの中央につねに現れ、 引数positionはそのフレームを指定する。 可能な値はx-popup-menuと同様であるが、 正確な座標は関係なくフレームだけが意味を持つ。

場合によっては、Emacsは本当の対話ボックスを表示できない。 そのときにはフレームの中央にポップアップメニューで同じ項目を表示する。


Node:Pointer Shapes, Next:, Previous:Dialog Boxes, Up:Frames

ポインタの形状

これらの変数は、Xウィンドウシステムを使っているときに さまざまな場面で使用するマウスポインタの形状を指定します。

x-pointer-shape
この変数は、Emacsのフレーム内で普通に使うポインタ形状を指定する。
x-sensitive-text-pointer-shape
この変数は、マウスに反応するテキスト上にマウスがあるときに 使用するポインタ形状を指定する。

これらの変数は、新たに作成したフレームに影響します。 既存のフレームには通常は影響しません。 しかし、フレームのマウスの表示色を設定すると、 これらの変数の現在値に基づいてポインタ形状も更新します。 See Window Frame Parameters

これらのポインタ形状の指定に使える値は、 ファイルlisp/term/x-win.elで定義してあります。 それらの一覧を見るには M-x apropos <RET> x-pointer <RET>を使います。


Node:Window System Selections, Next:, Previous:Pointer Shapes, Up:Frames

ウィンドウシステムのセレクション

Xサーバーは、アプリケーションプログラムのあいだでデータを 転送するためのセレクション(selection)の集まりを記録します。 さまざまなセレクションは、Emacsではシンボルで表した セレクション型(selection type)で区別されます。 Emacsを含むXクライアントは、任意の型のセレクションを読んだり設定できます。

x-set-selection type data Function
この関数は、Xサーバーに『セレクション』を設定する。 これは2つの引数、セレクション型typeと それに割り当てる値dataを取る。 datanilであると、当該セレクションを削除することを意味する。 さもなければdataは、文字列、 整数(あるいは2つの数のコンスセルかリスト)、 オーバレイ、同じバッファを指す2つのマーカのコンスセルのいずれかである。 オーバレイやマーカの対は、 オーバレイのテキストやマーカのあいだのテキストを表す。

引数dataは、ベクトルではない正しいセレクション値のベクトルでもよい。

可能な各typeには型に依存した独自のセレクション値がある。 typeの普通の値はPRIMARYSECONDARYである。 これらのシンボルは、Xウィンドウシステムの慣習に従って 大文字の名前である。 デフォルトはPRIMARYである。

x-get-selection &optional type data-type Function
この関数は、Emacsや他のXクライアントが設定したセレクションを参照する。 これは2つの引数、typedata-typeを取る。 セレクション型typeのデフォルトはPRIMARYである。

引数data-typeは、他のXクライアントから得た生データを Lispデータに変換するために使用するデータ変換の書式を指定する。 意味のある値は、TEXTSTRINGCHARACTER_POSITIONLINE_NUMBERCOLUMN_NUMBEROWNER_OSHOST_NAMEUSERCLASSNAMEATOMINTEGERである。 (これらのシンボルは、Xウィンドウシステムの慣習に従って 大文字の名前である。) data-typeのデフォルトはSTRINGである。

Xサーバーには、アプリケーションのあいだで移動するテキストや他のデータを 保存できる番号付きのカットバッファ(cut buffer)の集まりもあります。 カットバッファは廃れているとみなされますが、 それらを使っているXクライアント向けにEmacsはカットバッファを扱えます。

x-get-cut-buffer n Function
この関数は、番号nのカットバッファの内容を返す。

x-set-cut-buffer string Function
Emacsが連続したキルをキルリングで順に下向きに移動するのと同様に、 この関数は一連のカットバッファの値を順に下向きに移動してから 文字列stringを最初のカットバッファ(番号0)に保存する。

selection-coding-system Variable
この変数は、セレクション、クリップボード、カットバッファを 読み書きするときに使うコーディングシステムを指定する。 see Coding Systems。 デフォルトはcompound-textである。


Node:Font Names, Next:, Previous:Window System Selections, Up:Frames

フォント名の探索

x-list-font pattern &optional face frame maximum Function
この関数は、パターンpatternに一致する 利用可能なフォント名のリストを返す。 省略可能な引数faceframeを指定すると、 frameで現在オンになっているfaceと同じサイズのフォントに リストを制限する。

引数patternは文字列であること。 これはワイルドカード文字を含んでいてもよい。 *は任意の部分文字列に一致し、?は任意の1文字に一致する。 フォント名とパターンの一致を取る際には、大文字小文字を区別しない。

faceframeを指定するときには、 faceはフェイス名(シンボル)であり、frameはフレームであること。

省略可能な引数maximumは、返すフォントの個数を制限する。 これがnil以外であると、戻り値は最初のmaximum個の 一致したフォントに切り詰める。 maximumに小さな値を指定すると、 多くのフォントに一致する場合ではこの関数の動作がだいぶ速くなる。


Node:Fontsets, Next:, Previous:Font Names, Up:Frames

フォントセット

フォントセット(fontset)は、フォントのリストであって、 各フォントが文字コードのある範囲に割り付けられています。 個々のフォントだけでは、Emacsが扱う文字集合の範囲全体を表示できませんが、 フォントセットならば可能です。 フォントセットにはフォントと同様に名前があり、 フレームやフェイス向けに『フォント』を指定するときの フォント名のかわりにフォントセット名を使えます。 ここでは、Lispプログラムの制御のもとにフォントセットを定義することに 関する情報を述べます。

create-fontset-from-fontset-spec fontset-spec &optional style-variant-p noerror Function
この関数は、指定文字列fontset-specに従って 新たなフォントセットを定義する。 文字列はつぎの形であること。
fontpattern, [charsetname:fontname]...

コンマの前後の白文字は無視する。

文字列の始めの部分fontpatternは、 最後の2つのフィールドがfontset-aliasであることを除いて、 Xの標準フォント名であること。

新たなフォントセットには2つの名前、つまり、長い名前と短い名前がある。 長い名前はfontpatternそのものである。 短い名前はfontset-aliasである。 どちらの名前でもフォントセットを参照できる。 同じ名前のフォントセットがすでに存在する場合、 noerrornilであるとエラーを通知し、 この関数はなにもしない。

省略可能な引数style-variant-pnil以外であると、 フォントセットのbold(太字)、italic(斜体)、bold-italic(太字斜体)の 各変種も作成することを指示する。 これらの変種のフォントセットには短い名前はなく、 varfontpatternのboldやitalicを変更して作った長い名前だけである。

指定文字列ではフォントセットで使うフォントも指定する。 詳しくは下記参照。

charset:fontという構成は、 特定の1つの文字集合向けに(このフォントセットで)使うフォントを指定します。 ここで、charsetは文字集合の名前であり、 fontはその文字集合に使うフォントです。 この構成は、指定文字列で何回でも使えます。

明示してない残りの文字集合向けには、 fontpatternに基づいてEmacsがフォントを選びます。 つまり、fontset-aliasを1つの文字集合を指名する値で置き換えます。 ASCII文字集合向けには、 fontset-aliasISO8859-1で置き換えます。

これに加えて、いくつか連続したフィールドがワイルドカードであるなら、 Emacsはそれらを1つのワイルドカードにまとめます。 これは、自動的に拡大縮小したフォントの使用を避けるためです。 大きめのフォントを縮小したフォントは編集には使えません。 また、小さめのフォントを拡大したフォントも有用ではありません。 というのは、Emacsがそうするように、 もともと小さなフォントを使うほうがよいからです。

したがって、fontpatternがつぎのようであると、

-*-fixed-medium-r-normal-*-24-*-*-*-*-*-fontset-24

ASCII文字に対するフォント指定はつぎのようになります。

-*-fixed-medium-r-normal-*-24-*-ISO8859-1

また、Chinese GB2312文字に対するフォント指定はつぎのようになります。

-*-fixed-medium-r-normal-*-24-*-gb2312*-*

上のフォント指定に一致する中国語フォントがないかもしれません。 多くのXの配布には、familyフィールドが song tifangsong tiの中国語フォントだけが含まれています。 そういった場合、Fontset-nをつぎのように指定します。

Emacs.Fontset-0: -*-fixed-medium-r-normal-*-24-*-*-*-*-*-fontset-24,\
        chinese-gb2312:-*-*-medium-r-normal-*-24-*-gb2312*-*

そうすると、Chinese GB2312の文字を除くフォント指定では familyフィールドがfixedとなり、 Chinese GB2312の文字に対するフォント指定では familyフィールドが*となります。


Node:Color Names, Next:, Previous:Fontsets, Up:Frames

表示色名

x-color-defined-p color &optional frame Function
この関数は、表示色名が意味のあるものかどうかを報告する。 意味があればtを返し、さもなければnilを返す。 引数frameは、どのフレームで調べるかを指定する。 frameを省略したりnilであると、選択されているフレームを使う。

この関数では、読者が使用しているディスプレイで 当該表示色を実際に表示できるかどうかはわからない。 どんな種類のディスプレイでも定義されていればどんな表示色でも 問い合わせることができ、なんらかの結果を得られる。 Xサーバーはこのように動作するのである。 読者のディスプレイで表示色colorを使えるかどうかを 検査する近似方法はつぎのとおりである。

(defun x-color-supported-p (color &optional frame)
  (and (x-color-defined-p color frame)
       (or (x-display-color-p frame)
           (member color '("black" "white"))
           (and (> (x-display-planes frame) 1)
                (equal color "gray")))))

x-color-values color &optional frame Function
この関数は、表示色colorが理想的にはどのように見えるかを記述した値を返す。 colorが定義されていれば、その値は、赤の分量、緑の分量、青の分量を表す 3つの整数のリストである。 各整数の範囲は原理的には0から65535であるが、 実際には65280を超えることはないようである。 colorが定義されていなければ、値はnilである。
(x-color-values "black")
     => (0 0 0)
(x-color-values "white")
     => (65280 65280 65280)
(x-color-values "red")
     => (65280 0 0)
(x-color-values "pink")
     => (65280 49152 51968)
(x-color-values "hungry")
     => nil

フレームframeのディスプレイに対する表示色の値を返す。 frameを省略したりnilであると、 選択されているフレームのディスプレイに対する値を返す。


Node:Resources, Next:, Previous:Color Names, Up:Frames

Xリソース

x-get-resource attribute class &optional component subclass Function
関数x-get-resourceは、 Xウィンドウのデフォルトのデータベースからリソースの値を取り出す。

リソースは、keyclassの組み合わせで添字付けされる。 この関数はinstance.attributeの形 (instanceはEmacsを起動した名前)のキーと クラスとしてEmacs.classを使って探索する。

省略可能な引数componentsubclassは、それぞれ、 キーとクラスに追加される。 2つを指定するかまったく指定しないこと。 これらを指定すると、 キーはinstance.component.attributeであり、 クラスはEmacs.class.subclassである。

x-resource-class Variable
この変数は、x-get-resourceが探すアプリケーション名を指定する。 デフォルト値は"Emacs"である。 x-get-resourceを呼び出す周りでこの変数に別の文字列を束縛すれば、 『Emacs』以外のアプリケーション名でXリソースを探せる。

See Resources X


Node:Server Data, Previous:Resources, Up:Frames

Xサーバーに関するデータ

本節では、Emacsが使っているXディスプレイの能力や製造元に関する情報を 得るために使う関数について述べます。 これらの関数のそれぞれには、どのディスプレイを対象にするか 引数displayで指定できます。 引数displayは、ディスプレイ名か フレーム(が表示されいるディスプレイを意味する)のいずれかです。 引数displayを省略したりnilであると、 選択されているフレームのディスプレイを使うことを意味します。

x-display-screens &optional display Function
この関数は、ディスプレイに対応付けられているスクリーンの個数を返す。

x-server-version &optional display Function
この関数は、ディスプレイで動作中のXサーバーの版番号のリストを返す。

x-server-vendor &optional display Function
この関数は、Xサーバーソフトウェアの提供業者を返す。

x-display-pixel-height &optional display Function
この関数はスクリーンのピクセル単位の高さを返す。

x-display-mm-height &optional display Function
この関数はスクリーンのミリメートル単位の高さを返す。

x-display-pixel-width &optional display Function
この関数はスクリーンのピクセル単位の幅を返す。

x-display-mm-width &optional display Function
この関数はスクリーンのミリメートル単位の幅を返す。

x-display-backing-store &optional display Function
この関数は、スクリーンのバッキングストア機能を返す。 その値は、alwayswhen-mappednot-usefulのシンボルの いずれかである。

x-display-save-under &optional display Function
この関数は、ディスプレイにセーブアンダー機能があればnil以外を返す。

x-display-planes &optional display Function
この関数は、ディスプレイのプレイン数を返す。

x-display-visual-class &optional display Function
この関数は、スクリーンのビジュアルクラスを返す。 その値は、static-graygray-scalestatic-colorpseudo-colortrue-colordirect-colorのシンボルのいずれかである。

x-display-grayscale-p &optional display Function
この関数は、スクリーンで白黒の濃淡を表示できるとtを返す。

x-display-color-p &optional display Function
この関数は、スクリーンがカラースクリーンならばtを返す。

x-display-color-cells &optional display Function
この関数はスクリーンで使えるカラーセルの個数を返す。


Node:Positions, Next:, Previous:Frames, Up:Top

バッファ内の位置

バッファ内位置(position)は、 バッファ内のテキストの文字を添字付けします。 より正確にいえば、バッファ内位置は2つの文字のあいだの箇所 (あるいは、先頭文字ではそのまえ、最後の文字ではそのうしろ)を識別して、 指定位置のまえやうしろの文字を指定できるようにします。 しかし、しばしば位置『にある』文字といいますが、 これは位置の直後の文字を意味します。

バッファ内位置は、通常、1から始まる整数で表しますが、 マーカ(marker)で表すこともできます。 マーカは特別なオブジェクトであり、 テキストを挿入したり削除しても 同じ周りの文字に留まるように自動的に再配置されます。 See Markers


Node:Point, Next:, Up:Positions

ポイント

ポイント(point)は、 自己挿入文字やテキスト挿入関数を含む多くの編集コマンドが使う バッファ内の特別な位置です。 他のコマンドは、バッファ内の別の箇所で編集したり挿入できるように ポイントをテキスト内で移動します。

他のバッファ内位置と同様に、ポイントは文字そのものではなく、 2つの文字のあいだの箇所 (あるいは、先頭文字ではそのまえ、最後の文字ではそのうしろ)を指定します。 通常、端末では、ポイントの直後の文字に重ねてカーソルを表示します。 ポイントはカーソルがある文字のまえに実際にはあります。

ポイントの値は、1からバッファのサイズ足す1です。 ナロイング(see Narrowing)していると、 ポイントはバッファの参照可能な (バッファの端を含むかもしれない)範囲内に制限されます。

各バッファには独自のポイント値があり、 それは他のバッファのポイント値とは独立です。 各ウィンドウにも独自のポイント値があり、 同じバッファを表示している他のウィンドウのポイント値とは独立です。 このようなわけで、同じバッファを表示しているさまざまなウィンドウで 異なるポイント値を持てるのです。 1つのウィンドウだけにバッファが表示されているときには、 バッファのポイントとウィンドウのポイントは、通常、同じ値であり、 それらを区別することはほとんど重要ではありません。 詳しくは、See Window Point

point Function
この関数はカレントバッファのポイント値を整数で返す。
(point)
     => 175

point-min Function
この関数は、カレントバッファで参照可能なポイント値の最小値を返す。 これは通常1であるが、 ナロイングしているときには、ナロイングした領域の開始位置である。 (see Narrowing。)

point-max Function
この関数は、カレントバッファで参照可能なポイント値の最大値を返す。 ナロイングしていなければ、これは(1+ (buffer-size))である。 ナロイングしているときには、ナロイングした領域の終了位置である。 (see Narrowing。)

buffer-end flag Function
この関数は、flagが1未満であれば(point-min)を返し、 さもなければ(point-max)を返す。 引数flagは整数であること。

buffer-size Function
この関数は、カレントバッファ内の総文字数を返す。 ナロイング(see Narrowing)していなければ、 point-maxはこの値より1大きな値を返す。
(buffer-size)
     => 35
(point-max)
     => 36


Node:Motion, Next:, Previous:Point, Up:Positions

移動

移動関数は、現在のポイント値やバッファの先頭や末尾を基準にして、 あるいは、選択されているウィンドウの端を基準にして、 ポイント値を変更します。 See Point


Node:Character Motion, Next:, Up:Motion

文字単位の移動

これらの関数は、文字数に基づいてポイントを移動します。 goto-charが基本になる基本関数であり、他の関数はこれを使っています。

goto-char position コマンド
この関数は、カレントバッファのポイント位置を値positionとする。 positionが1未満であると、バッファの先頭にポイントを移動する。 positionがバッファの長さより大きい場合には、 バッファの末尾にポイントを移動する。

ナロイングしている場合であっても、 positionはバッファの先頭から数えるが、 参照可能部分の外側にはポイントは移動できない。 positionが範囲外であると、 goto-charは参照可能部分の先頭か末尾にポイントを移動する。

この関数を対話的に呼び出すと、 前置引数があればpositionは数値前置引数である。 さもなければミニバッファから読む。

goto-charpositionを返す。

forward-char &optional count コマンド
この関数は、前方へ、つまり、バッファの末尾に向けて (countが負であれば、後方へ、つまり、バッファの先頭へ向けて) count文字分ポイントを移動する。 バッファの先頭や末尾を越えて (ナロイングしているときには参照可能部分を越えて) ポイントを移動しようとすると、 beginning-of-bufferend-of-bufferのエラーコードで エラーを通知する。

対話的に呼び出されると、countは数値前置引数である。

backward-char &optional count コマンド
この関数は、後方へ、つまり、バッファの先頭に向けて (countが負であれば、前方へ、つまり、バッファの末尾へ向けて) count文字分ポイントを移動する。 バッファの先頭や末尾を越えて (ナロイングしているときには参照可能部分を越えて) ポイントを移動しようとすると、 beginning-of-bufferend-of-bufferのエラーコードで エラーを通知する。

対話的に呼び出されると、countは数値前置引数である。


Node:Word Motion, Next:, Previous:Character Motion, Up:Motion

単語単位の移動

これらの単語を解析する関数は、 当該文字が単語の一部かどうかを判定するために構文テーブルを使います。 See Syntax Tables

forward-word count コマンド
この関数は、前方へ(countが負ならば後方へ) count単語分ポイントを移動する。 『1単語分移動する』とは、 単語構成文字を越えてから単語区切り文字(あるいはバッファの参照可能部分の 境界)に出会うまでポイントを移動することを意味する。

バッファの境界で止まらず(最後の単語は除く)に count単語分移動できると、値はtである。 さもなければ値はnilであり、ポイントはバッファの境界で止まる。

対話的に呼び出されると、countは数値前置引数である。

backward-word count コマンド
この関数はforward-wordと同様であるが、 前方へではなく後方へ単語の先頭に出会うまで移動する。

対話的に呼び出されると、countは数値前置引数である。

この関数は、プログラムではほとんど使われない。 負の引数でforward-wordを呼び出すほうが効率的だからである。

words-include-escapes Variable
この変数は、forward-wordとそれを使うもののふるまいに影響する。 nil以外であると、『エスケープ』や『文字クォート』の 構文クラスに属する文字も単語の一部とみなす。 さもなければ、単語の一部とはみなさない。


Node:Buffer End Motion, Next:, Previous:Word Motion, Up:Motion

バッファの両端への移動

バッファの先頭にポイントを移動するには、つぎのように書きます。

(goto-char (point-min))

同様に、バッファの末尾に移動するには、つぎのようにします。

(goto-char (point-max))

上のことを行うためにユーザーが使うコマンドが2つあります。 これらはマークを設定してエコー領域にメッセージを表示するので、 これらをLispプログラムからは使わないように警告しておきます。

beginning-of-buffer &optional n コマンド
この関数は、バッファ(あるいはナロイングしているときには参照可能部分) の先頭にポイントを移動し、移動前の位置にマークを設定する。 nnil以外であると、 バッファの先頭から10分のnの箇所にポイントを移動する。

対話的に呼び出すと、前置引数があればnは数値前置引数である。 さもなければnのデフォルトはnilである。

警告: Lispプログラムではこの関数を使わないこと!

end-of-buffer &optional n コマンド
この関数は、バッファ(あるいはナロイングしているときには参照可能部分) の末尾にポイントを移動し、移動前の位置にマークを設定する。 nnil以外であると、 バッファの末尾から10分のnの箇所にポイントを移動する。

対話的に呼び出すと、前置引数があればnは数値前置引数である。 さもなければnのデフォルトはnilである。

警告: Lispプログラムではこの関数を使わないこと!


Node:Text Lines, Next:, Previous:Buffer End Motion, Up:Motion

テキスト行単位の移動

テキスト行とは、改行文字で区切られたバッファの部分です。 改行文字はまえの行に属するとみなします。 最初のテキスト行がバッファの先頭から始まり、 バッファの末尾の文字が改行であってもなくても、 最後のテキスト行はバッファの末尾で終ります。 バッファをテキスト行に分割することは、 ウィンドウの幅、表示上の行の継続、タブやコントロール文字の表示方法には 影響されません。

goto-line line コマンド
この関数は、バッファの先頭を1行目と数えてline行目の先頭に ポイントを移動する。 lineが1未満であると、バッファの先頭へポイントを移動する。 lineがバッファ内の行数より大きいと、 バッファの末尾、つまり、バッファの最後の行の末尾にポイントを移動する。 これは、goto-lineが行頭にポイントを移動しない唯一の場面である。

ナロイングしているときでも、 lineはバッファの先頭から数えるが、 参照可能部分の外側にはポイントは移動しない。 したがって、行番号が参照不可な部分を指定するときには、 goto-lineは参照可能部分の先頭か末尾へポイントを移動する。

goto-lineの戻り値は、 (ナロイングを考慮せずにバッファ全体でみた) lineと実際のポイントの移動先の行の行番号との差である。 したがって、指定した行に達するまえにバッファの末尾に出会うと値は正である。 バッファの実際の末尾にではなく参照可能部分の末尾に出会うと値は0である。

対話的に呼び出すと、 前置引数があればlineは数値前置引数である。 さもなければlineをミニバッファから読む。

beginning-of-line &optional count コマンド
この関数は、現在行の先頭にポイントを移動する。 引数countnilでも1でもないと、 count-1行だけ前方へ移動してから行頭に移動する。

バッファ(ナロイングしているときには参照可能部分)の末尾に達すると ポイントをそこへ移動する。 エラーは通知しない。

end-of-line &optional count コマンド
この関数は、現在行の末尾にポイントを移動する。 引数countnilでも1でもないと、 count-1行だけ前方へ移動してから行末に移動する。

バッファ(ナロイングしているときには参照可能部分)の末尾に達すると ポイントをそこへ移動する。 エラーは通知しない。

forward-line &optional count コマンド
この関数は、count行前方の行頭にポイントを移動する。 countが負であると、 -count行後方の行頭にポイントを移動する。 countが0であると、現在行の先頭にポイントを移動する。

指定行数だけ移動するまえに バッファ(ナロイングしているときには参照可能部分)の先頭や末尾に達すると ポイントをそこへ移動する。 エラーは通知しない。

forward-lineは、 countと実際に移動した行数の差を返す。 3行しかないバッファの先頭で5行前方へ移動しようとすると、 ポイントは最後の行の末尾で止まり、値は2になる。

対話的に呼び出すと、countは数値前置引数である。

count-lines start end Function
この関数は、カレントバッファのstartendの あいだの部分にある行の行数を返す。 startendが等しければ0を返す。 さもなければ、startendが同じ行にある場合であっても 少なくとも1を返す。 というのは、それらのあいだのテキストは孤立しているとみなされ、 空でなければ少なくとも1行はあるはずだからである。

count-linesの使用例を示す。

(defun current-line ()
  "Return the vertical position of point..."
  (+ (count-lines (window-start) (point))
     (if (= (current-column) 0) 1 0)
     -1))
Near Pointの関数bolpeolpも参照してください。 これらの関数はポイントを移動しませんが、ポイントがすでに行の先頭や末尾に あるかどうかを検査します。


Node:Screen Lines, Next:, Previous:Text Lines, Up:Motion

スクリーン行分の移動

前節の行単位の関数は、改行文字で区切られたテキスト行だけを数えます。 対照的に、これらの関数は、スクリーン上にどのようにテキストが現れるかで 定義されるスクリーン上の行を数えます。 テキスト行が選択されているウィンドウの幅に収まるだけ短ければ、 1テキスト行は1スクリーン行ですが、 しかし、それ以外では1テキスト行は複数のスクリーン行を占めます。

テキスト行を複数のスクリーン行に継続せずに スクリーン上で切り詰める場合もあります。 このような場合、vertical-motionは、 forward-lineによく似たポイントの移動を行います。 See Truncation

与えられた文字列の幅は、各文字の見ためを制御するフラグに依存するので、 vertical-motionは、 テキストを収めたバッファや選択されているウィンドウ (その幅や切り詰めフラグ、ウィンドウごとに異なりうる表示テーブルが あるため)に依存して、特定のテキスト部分に対して異なったふるまいをします。 See Usual Display

これらの関数は、スクリーン行がどこで区切れるかを決定するためにテキストを走査 するので、走査する量に比例して時間がかかります。 読者がこれらを多用する意図があるときには、 読者のコードの効率を改善するキャッシュをEmacsが提供します。 See cache-long-line-scans

vertical-motion count &optional window Function
この関数は、ポイントを含むスクリーン行から countスクリーン行数だけ下向きにポイントを移動する。 countが負であると上向きに移動する。

vertical-motionは、ポイントを移動したスクリーン行数を返す。 バッファの先頭や末尾に達すると、 この値は絶対値ではcountより小さい。

ウィンドウwindowは、 幅、水平スクロール、表示テーブルなどのパラメータを得るために使われる。 しかし、windowに別のバッファが表示されているとしても、 vertical-motionはつねにカレントバッファに作用する。

move-to-window-line count コマンド
この関数は、選択されているウィンドウに現在表示されているテキストに 基づいてポイントを移動する。 ウィンドウの先頭からcountスクリーン行の先頭にポイントを移動する。 countが負であると、底(あるいはバッファの末尾がスクリーンの 底より上にある場合にはバッファの最終行)から数えて -countスクリーン行位置を指定する。

countnilであると、 ウィンドウの中央の行の先頭にポイントを移動する。 count の絶対値がウィンドウのサイズよりも大きいときには、 ウィンドウに十分な高さがあった場合に移動するであろう スクリーン行の箇所にポイントを移動する。 そのため、スクロールして当該箇所がスクリーンに現れるように再表示する。

対話的に呼び出されると、countは数値前置引数である。

戻り値は、ウィンドウの先頭行を0と数えて、移動先の行のウィンドウ行番号である。

compute-motion from frompos to topos width offsets window Function
この関数は、スクリーン上での位置を計算しながらカレントバッファを走査する。 バッファ内位置fromがスクリーン座標fromposに対応すると仮定して、 fromから前方へ向けてtotoposのどちらかに 達するまでバッファを走査する。 バッファ内の終了位置とスクリーン座標を返す。

座標引数frompostoposは、 (hpos . vpos)の形のコンスセルである。

引数widthは、テキストを表示できるコラム数であり、 これは継続行の扱いに影響する。 読者が選んだウィンドウに対してwindow-widthが返した値、 つまり、通常、(window-width window)を使う。

引数offsetsは、nilであるか、 (hscroll . tab-offset)の形のコンスセルである。 ここで、hscrollは左端に表示されていないコラム数であり、 多くの場合はwindow-hscrollを呼び出して得た値を使う。 一方、tab-offsetはスクリーン上でのコラム番号と バッファ内でのコラム番号の差である。 この値は、継続行においてまえのスクリーン行の幅がtab-widthで終らない 場合に0以外になる。 継続しない行ではつねに0である。

ウィンドウwindowは、使用する表示テーブルを指定するためだけに使われる。 windowに表示されているバッファに関わらず、 compute-motionはつねにカレントバッファに作用する。

戻り値は、5要素のリストである。

(pos vpos hpos prevhpos contin)

ここで、posは走査を終えたバッファ内位置であり、 vposは垂直方向のスクリーン位置、 hposは水平方向のスクリーン位置である。

結果のprevhposは、posから1文字分戻った箇所の水平位置である。 この文字のあとで最終行が継続しているときには、 結果のcontintである。

たとえば、あるウィンドウのlineスクリーン行のcolコラムに 対応するバッファ内位置を探すには、 fromとしてウィンドウの表示開始位置、 fromposとしてウィンドウの左上隅の座標を渡します。 toにはバッファの(point-max)を渡して 走査をバッファの参照可能部分のみに制限し、 toposとしてlinecolを渡す。 つぎのように呼び出す。

(defun coordinates-of-position (col line)
  (car (compute-motion (window-start)
                       '(0 . 0)
                       (point-max)
                       (cons col line)
                       (window-width)
                       (cons (window-hscroll) 0)
                       (selected-window))))

ミニバッファに対してcompute-motionを使うときには、 minibuffer-prompt-widthを使って 最初のスクリーン行の先頭の水平位置を得る必要がある。 see Minibuffer Misc


Node:List Motion, Next:, Previous:Screen Lines, Up:Motion

式単位の移動

ここでは、釣り合った括弧で囲まれた式 (Emacs内でそれらを単位に移動するときにはS式(sexps)とも呼ばれる)を 扱う関数について述べます。 構文テーブルは、これらの関数がさまざまな文字を どのように解釈するかを制御します。 Syntax Tablesを参照してください。 S式やその一部を走査する下位レベルの基本関数については、 See Parsing Expressions。 ユーザーレベルのコマンドに関しては、 List Commandsを参照してください。

forward-list arg コマンド
この関数は、釣り合った括弧で囲まれたものをarg個前方へ飛び越えて移動する。 (単語や文字列のクォート対などの他の構文要素は無視する。)

backward-list arg コマンド
この関数は、釣り合った括弧で囲まれたものをarg個後方へ飛び越えて移動する。 (単語や文字列のクォート対などの他の構文要素は無視する。)

up-list arg コマンド
この関数は、前方へ向けてarg個の括弧のレベルを抜ける。 負の引数では後方へ向けて浅いレベルへ移動する。

down-list arg コマンド
この関数は、前方へ向けてarg個の括弧のレベルだけ深く入る。 負の引数では後方へ向けて括弧の深い(-arg)レベルへ移動する。

forward-sexp arg コマンド
この関数は、arg個の釣り合った式を前方へ向けて飛び越えて移動する。 釣り合った式には、括弧で区切られたものに加えて、 単語や文字列定数などの他の種類も含まれる。 たとえばつぎのとおり。
---------- Buffer: foo ----------
(concat-!- "foo " (car x) y z)
---------- Buffer: foo ----------

(forward-sexp 3)
     => nil

---------- Buffer: foo ----------
(concat "foo " (car x) y-!- z)
---------- Buffer: foo ----------

backward-sexp arg コマンド
この関数は、arg個の釣り合った式を後方へ向けて飛び越えて移動する。

beginning-of-defun arg コマンド
この関数は、前方へ向けてarg個目の関数定義の先頭へ移動する。 argが負であると、後方へ向けて、 関数定義の末尾ではなく関数定義の先頭へ移動する。

end-of-defun arg コマンド
この関数は、前方へ向けてarg個目の関数定義の末尾へ移動する。 argが負であると、後方へ向けて、 関数定義の先頭ではなく関数定義の末尾へ移動する。

defun-prompt-regexp User Option
この変数がnil以外であると、 関数定義を始める開き括弧のまえに現れうるテキストを指定する正規表現を保持する。 つまり、関数定義は、 行の先頭がこの正規表現に一致するテキストで始まり、 それに開き括弧の構文に属する文字が続く行で始まる。


Node:Skipping Characters, Previous:List Motion, Up:Motion

文字群の飛び越し

つぎの2つの関数は、指定した種類の文字を飛び越えてポイントを移動します。 たとえば、白文字を飛び越すためにこれらはしばしば使われます。 関連する関数については、Motion and Syntaxを参照してください。

skip-chars-forward character-set &optional limit Function
この関数は、指定した文字の集まりを飛び越えて、 カレントバッファ内で前方にポイントを移動する。 ポイントのあとの文字を調べ、 その文字がcharacter-setに一致するとポイントを進める。 これをcharacter-setに一致しない文字に達するまで繰り返す。 この関数は飛び越えた文字の個数を返す。

引数character-setは、正規表現の[...]の内側と同じであるが、 ]は特別扱いせず、\^-\をクォートする。 したがって、"a-zA-Z"はすべての英文字を飛び越えて 最初の英文字でない文字のまえで止まる。 "^a-zA-Z"は英文字でない文字を飛び越えて最初の英文字で止まる。 see Regular Expressions

limitを指定すると(数かマーカであること)、 ポイントを移動できるバッファ内の最大位置を指定する。 ポイントは、limitで止まるかlimitに達するまえに止まる。

つぎの例では、ポイントは最初はTの直前に位置している。 フォームを評価後には、ポイントはその行末 (hattと改行のあいだ)に位置している。 この関数は、すべての英文字と空白を飛び越えるが、改行は飛び越えない。

---------- Buffer: foo ----------
I read "-!-The cat in the hat
comes back" twice.
---------- Buffer: foo ----------

(skip-chars-forward "a-zA-Z ")
     => nil

---------- Buffer: foo ----------
I read "The cat in the hat-!-
comes back" twice.
---------- Buffer: foo ----------

skip-chars-backward character-set &optional limit Function
この関数は、limitに達するまで、 後方へ向かってcharacter-setに一致する文字を飛び越えてポイントを移動する。 これはskip-chars-forwardと同様であるが、移動方向が異なる。

移動距離を表す値を返す。 それは0以下の整数である。


Node:Excursions, Next:, Previous:Motion, Up:Positions

エクスカージョン

プログラムの局所的な部分で『一時的に』ポイントを移動したり、 一時的にバッファを切り替えられるとしばしば有用です。 これをエクスカージョン(excursion、周遊)と呼び、 スペシャルフォームsave-excursionで行います。 この構文は、カレントバッファとそのポイントやマーカの値を保存し、 エクスカージョンの完了後にそれらを復元します。

ウィンドウの構成を保存したり復元するフォームは、 別のところで述べてあります (Window Configurationsとsee Frame Configurations)。

save-excursion forms... Special Form
スペシャルフォームsave-excursionは、 カレントバッファの識別子とそのポイントやマーカの値を保存し、 formsを評価し、最後に、 バッファと保存しておいたポイントやマーカの値を復元する。 throwやエラーによる異常脱出(see Nonlocal Exits)であっても、 これらの保存した値を復元する。

スペシャルフォームsave-excursionは、 プログラムの一部分だけでバッファやポイントを移動し プログラムの他の部分への影響を防ぐ標準的な方法である。 EmacsのLispソースでは4000回以上も使われている。

save-excursionは他のバッファのポイントやマークの値は保存しないので、 他のバッファでの変更はsave-excursionから抜けても持続する。

同様に、save-excursionは、 switch-to-bufferなどの関数で変更された ウィンドウとバッファの対応関係は復元しない。 これらの対応関係や選択されているウィンドウを復元する1つの方法は、 save-excursionの内側でsave-window-excursionを 使うことである(see Window Configurations)。

save-excursionの戻り値は、formsの最後の結果であるか、 formsを与えなければnilである。

(save-excursion forms)
==
(let ((old-buf (current-buffer))
      (old-pnt (point-marker))
      (old-mark (copy-marker (mark-marker))))
  (unwind-protect
      (progn forms)
    (set-buffer old-buf)
    (goto-char old-pnt)
    (set-marker (mark-marker) old-mark)))

警告: 保存されたポイント値の箇所に 普通にテキストを挿入すると、すべてのマーカを再配置するように 保存されたポイント値を再配置する。 したがって、保存されたポイント値が復元されると、 ポイントは挿入されたテキストのまえに普通どおりにくる。

save-excursionはマーカの位置を保存しますが、 バッファを変更する関数がdeactivate-markを行うことを防ぎませんから、 コマンドが終了するとマーカが不活性になってしまいます。 See The Mark


Node:Narrowing, Previous:Excursions, Up:Positions

ナロイング

ナロイング(narrowing)とは、 Emacsの編集コマンドが参照できるテキストを バッファの制限された文字の範囲に限定することです。 参照できるテキストのことをバッファの 参照可能部分(accessible portion)と呼びます。

ナロイングは、参照可能部分の先頭と末尾になる2つのバッファ内位置で指定します。 ほとんどの編集コマンドやほとんどのEmacs基本関数にとっては、 これらの位置はバッファの先頭や末尾の値を置き換えることになります。 ナロイングしていると、参照可能部分の外側のテキストは表示されませんし、 ポイントは参照可能部分の外側へは移動できません。

通常はバッファの先頭から数える位置や行番号などの値は ナロイングしていても同様に数えますが、 それらを使う関数は参照できないテキストを操作することを拒否します。

バッファを保存するコマンドはナロイングの影響を受けません。 つまり、ナロイングに関係なくバッファ全体を保存します。

narrow-to-region start end コマンド
この関数は、カレントバッファのstartで始まりendで終る部分を 参照可能部分にする。 どちらの引数も文字の位置であること。

対話的に呼び出されると、startendは 現在のリージョンの境界(ポイントとマークの小さいほうがさきにくる)である。

narrow-to-page move-count コマンド
このコマンドは、カレントバッファの参照可能部分を 現在のページのみを含むようにする。 省略可能な第1引数move-countnil以外であると、 move-countページだけ前方か後方へ移動してから 1ページ分にナロイングする。 変数page-delimiterがページの開始箇所と終了箇所を指定する (see Standard Regexps)。

対話的に呼び出されると、move-countは数値前置引数である。

widen コマンド
この関数は、カレントバッファのナロイングを解除し、 全体を参照できるようにする。 これをワイドニング(widening)と呼ぶ。 これはつぎの式と等価である。
(narrow-to-region 1 (1+ (buffer-size)))

save-restriction body... Special Form
このスペシャルフォームは、現在の参照可能部分の境界を保存し、 フォームbodyを評価し、最後に、保存した境界を復元して まえと同じナロイング状態(あるいはナロイングなし)に復元する。 throwやエラーによる異常脱出(see Nonlocal Exits)であっても、 ナロイング状態を復元する。

save-restrictionの戻り値は、bodyの最後の結果であるか、 bodyを与えなければnilである。

注意: 構文save-restrictionを使うときには まちがいやすい。 使うまえにこの説明全体を読むこと。

bodyでカレントバッファを切り替えても save-restrictionはもとのバッファ(バッファの制限を保存したバッファ)に 制限を復元するが、もとのカレントバッファには戻さない。

save-restrictionはポイントやマークは復元しない。 それにはsave-excursionを使う。 save-restrictionsave-excursionの両者を 一緒に使うときには、save-excursionが先に(外側に)くること。 さもないと、古いポイント値は一時的なナロイングが有効な状態で復元される。 古いポイント値が一時的なナロイングの範囲外にあると正しく復元できない。

スペシャルフォームsave-restrictionは、 参照可能部分の先頭と末尾をバッファの先頭と末尾からの距離として記録する。 いいかえれば、参照可能部分の前後の参照できないテキストの量を記録する。

この方法は、bodyでさらにナロイングしても正しい結果を生じる。 しかし、bodyでワイドニングして保存されているナロイングの範囲外を 変更するとsave-restrictionが混乱する。 このようにしたいときには、 save-restrictionは正しい解法ではない。 つぎのようにする必要がある。

(let ((beg (point-min-marker))
      (end (point-max-marker)))
  (unwind-protect
      (progn body)
    (save-excursion
      (set-buffer (marker-buffer beg))
      (narrow-to-region beg end))))

save-restrictionの正しい使い方の簡単な例を示す。

---------- Buffer: foo ----------
This is the contents of foo
This is the contents of foo
This is the contents of foo-!-
---------- Buffer: foo ----------

(save-excursion
  (save-restriction
    (goto-char 1)
    (forward-line 2)
    (narrow-to-region 1 (point))
    (goto-char (point-min))
    (replace-string "foo" "bar")))

---------- Buffer: foo ----------
This is the contents of bar
This is the contents of bar
This is the contents of foo-!-
---------- Buffer: foo ----------


Node:Markers, Next:, Previous:Positions, Up:Top

マーカ

マーカ(marker)とは、バッファ内位置をそれを取り巻くテキストを 基準に指定するために使われるLispオブジェクトです。 テキストが挿入されたり削除されると、 バッファの先頭からマーカまでの距離は自動的に変更され、 マーカは同じ前後の文字のあいだに留まります。


Node:Overview of Markers, Next:, Up:Markers

マーカの概要

マーカは、バッファとそのバッファ内での位置を指定します。 マーカは、位置を必要とする関数に対して位置を表すものとして使えます。 バッファ内の位置について詳しくはSee Positions

マーカには2つの属性、つまり、マーカ位置とマーカバッファがあります。 マーカ位置は、当該バッファ内の位置としてのマーカに (その時点で)等価な整数です。 しかし、マーカの生存期間中、マーカ位置の値はしばしば変化します。 バッファにテキストを挿入したり削除すると、マーカは再配置されます。 これは、バッファの任意の箇所で挿入したり削除したとしても、 2つの文字のあいだに置かれたマーカが 同じ文字のあいだに留まるようにするためです。 再配置によって、マーカに等価な整数は変わります。

マーカ位置の周りのテキストを削除すると、 削除されたテキストの前後の文字のあいだにマーカは留まります。 マーカの位置にテキストを挿入すると、 insert-before-markers(see Insertion)で挿入しない限り、 マーカの挿入型(insertion type)(see Marker Insertion Types)に 依存して、マーカは挿入されたテキストのまえかうしろに留まります。

バッファに対する挿入や削除では、 すべてのマーカを検査し、必要ならばマーカを再配置する必要があります。 マーカを多数抱えるバッファでは、このために処理が遅くなります。 そのため、マーカが不要であると確信したときには、 マーカがどこも指さないようにしておくのがよいです。 参照されていないマーカは最終的には(ガベッジコレクションで)回収されますが、 それまでは、マーカがどこかを指していると処理時間を浪費します。

マーカ位置にはよく算術演算を施すので、 (+-を含む)ほとんどの算術演算は 引数としてマーカを受け付けます。 そのような場合、マーカはその現在位置を表します。

マーカを作って位置を設定し、ポイントをマーカへ移動する例を示します。

;; どこも指していない新しいマーカを作る
(setq m1 (make-marker))
     => #<marker in no buffer>

;; マーカm1の位置をカレントバッファの
;; 99番目と100番目の文字のあいだにする
(set-marker m1 100)
     => #<marker at 100 in markers.texi>

;; バッファの先頭に1文字挿入する
(goto-char (point-min))
     => 1
(insert "Q")
     => nil

;; それにしたがってm1が更新される
m1
     => #<marker at 101 in markers.texi>

;; 同じ位置を指す2つのマーカはeqではないが
;; equalである
(setq m2 (copy-marker m1))
     => #<marker at 101 in markers.texi>
(eq m1 m2)
     => nil
(equal m1 m2)
     => t

;; マーカを使い終ったら、どこも指していないようにする
(set-marker m1 nil)
     => #<marker in no buffer>


Node:Predicates on Markers, Next:, Previous:Overview of Markers, Up:Markers

マーカ向けの述語

オブジェクトがマーカであるかどうかや、 オブジェクトが整数かマーカであるかどうかを検査できます。 マーカと整数の両者を扱う算術関数に関連して、 後者の検査は有用です。

markerp object Function
この関数は、objectがマーカであればtを返し、 さもなければnilを返す。 多くの関数がマーカや整数を受け付けるが、 整数はマーカではないことに注意すること。

integer-or-marker-p object Function
この関数は、objectが整数かマーカであるとtを返し、 さもなければnilを返す。

number-or-marker-p object Function
この関数は、objectが数(整数か浮動小数点数)かマーカであると tを返し、さもなければnilを返す。


Node:Creating Markers, Next:, Previous:Predicates on Markers, Up:Markers

マーカ作成関数

新たにマーカを作成するときには、そのマーカが、 どこも指していない、現在のポイント位置を指している、 バッファの参照可能部分の先頭や末尾を指している、 別のマーカと同じ箇所を指しているのいずれかにできます。

make-marker Function
この関数は、どこも指していない新たに作成したマーカを返す。
(make-marker)
     => #<marker in no buffer>

point-marker Function
この関数は、カレントバッファの現在のポイント位置を 指す新たに作成したマーカを返す。 see Point。 例については、下記のcopy-markerを参照。

point-min-marker Function
この関数は、バッファの参照可能部分の先頭を指す新たに作成したマーカを返す。 ナロイングしていなければ、これはバッファの先頭である。 see Narrowing

point-max-marker Function
この関数は、バッファの参照可能部分の末尾を指す新たに作成したマーカを返す。 ナロイングしていなければ、これはバッファの末尾である。 see Narrowing

本章のソースファイル(の原文)を入れたバッファでの この関数とpoint-min-markerの例を示す。

(point-min-marker)
     => #<marker at 1 in markers.texi>
(point-max-marker)
     => #<marker at 15573 in markers.texi>

(narrow-to-region 100 200)
     => nil
(point-min-marker)
     => #<marker at 100 in markers.texi>
(point-max-marker)
     => #<marker at 200 in markers.texi>

copy-marker marker-or-integer &optional insertion-type Function
引数としてマーカを渡されると、copy-markerは、 marker-or-integerが指すのと同じ バッファとバッファ内位置を指す新たなマーカを返す。 引数として整数を渡されると、copy-markerは、 カレントバッファで位置marker-or-integerを指す新たなマーカを返す。

新たなマーカの挿入型は引数insertion-typeで指定する。 see Marker Insertion Types

渡された整数引数が1未満であると、copy-markerは、 カレントバッファでバッファの先頭を指す新たなマーカを返す。 渡された整数引数がバッファの長さより大きいと、copy-markerは、 バッファの末尾を指す新たなマーカを返す。

(copy-marker 0)
     => #<marker at 1 in markers.texi>

(copy-marker 20000)
     => #<marker at 7572 in markers.texi>

marker-or-integerがマーカでも整数でもないと、エラーを通知する。

2つの異なるマーカが、同じバッファの同じバッファ内位置であるか、 どちらもどこも指していないときには、 両者を(eqではないが)equalとみなします。

(setq p (point-marker))
     => #<marker at 2139 in markers.texi>

(setq q (copy-marker p))
     => #<marker at 2139 in markers.texi>

(eq p q)
     => nil

(equal p q)
     => t


Node:Information from Markers, Next:, Previous:Creating Markers, Up:Markers

マーカの情報

本節では、マーカオブジェクトの構成要素を参照する関数について述べます。

marker-position marker Function
この関数は、markerが指す位置を返す。 あるいは、markerがどこも指していなければnilを返す。

marker-buffer marker Function
この関数は、markerが指すバッファを返す。 あるいは、markerがどこも指していなければnilを返す。
(setq m (make-marker))
     => #<marker in no buffer>
(marker-position m)
     => nil
(marker-buffer m)
     => nil

(set-marker m 3770 (current-buffer))
     => #<marker at 3770 in markers.texi>
(marker-buffer m)
     => #<buffer markers.texi>
(marker-position m)
     => 3770


Node:Marker Insertion Types, Next:, Previous:Information from Markers, Up:Markers

マーカの挿入型

マーカが指す箇所に直接テキストを挿入すると、 マーカの再配置方法には2つの可能性、つまり、 挿入したテキストのまえに留まるか、あとにくるかのどちらかです。 マーカの挿入型(insertion type)を設定することで、 あるマーカではどちらを選ぶか指定できます。 insert-before-markersを使うとマーカの挿入型は無視され、 マーカは挿入したテキストのうしろにつねに再配置されることに注意してください。

set-marker-insertion-type marker type Function
この関数は、マーカmarkerの挿入型をtypeとする。 typetであると、 テキストが挿入されるとmarkerはその位置へ進む。 typenilであると、 テキストが挿入されてもmarkerはその位置へ進まない。

marker-insertion-type marker Function
この関数は、markerの現在の挿入型を報告する。


Node:Moving Markers, Next:, Previous:Marker Insertion Types, Up:Markers

マーカ位置の移動

本節では、既存のマーカの位置を変更する方法について述べます。 これを行うときには、読者のプログラムの外側で 当該マーカが使われているかどうか、 使われているときには移動による効果はなにかを確実に理解してください。 さもないと、Emacsの別の部分で混乱を生じるかもしれません。

set-marker marker position &optional buffer Function
この関数は、bufferにおいてmarkerpositionへ移動する。 bufferを与えないと、デフォルトはカレントバッファである。

positionが1未満であると、 set-markermarkerをバッファの先頭へ移動する。 positionがバッファのサイズよりも大きいと、 set-markermarkerをバッファの末尾へ移動する。 positionnilであったりどこも指していないマーカであると、 markerはどこも指さないようにする。

戻り値はmarkerである。

(setq m (point-marker))
     => #<marker at 4714 in markers.texi>
(set-marker m 55)
     => #<marker at 55 in markers.texi>
(setq b (get-buffer "foo"))
     => #<buffer foo>
(set-marker m 0 b)
     => #<marker at 1 in foo>

move-marker marker position &optional buffer Function
これはset-markerの別名である。


Node:The Mark, Next:, Previous:Moving Markers, Up:Markers

マーク

各バッファの1つの特別なマーカをマーク(mark)として区別します。 これは、kill-regionindent-rigidlyなどのコマンド向けに ユーザーのために位置を記録するものです。 Lispプログラムでは、ユーザーが使う可能性のある値だけをマークに設定し、 プログラムの内部向けにはけっしてマークを使いません。 たとえば、コマンドreplace-regexpは、 置換を行うまえのポイント値をマークに設定します。 置換を完了したあとに、ユーザーが手軽にまえの位置に戻れるようにするためです。

多くのコマンドは、対話的に呼ばれるとポイントとマークのあいだの テキストに作用するように設計されています。 読者がそのようなコマンドを書くときには、 マークを直接検査しないでください。 そのかわりに、rを指定したinteractiveを使います。 こうすると、 対話的に呼ばれるとポイントとマークの値がコマンドの引数に与えられますが、 別のLispプログラムからは引数を明示できます。 See Interactive Codes

各バッファには、他のバッファのマークの値とは独立な 独自のマークの値があります。 バッファが作成されると、マークは存在しますがどこも指さない状態です。 これを『バッファのマークは欠如している』状態とみなします。

バッファでいったんマークが『存在』するようになれば、 マークが存在しなくなることは普通はありません。 しかし、暫定マーク(transient-mark)モードをオンにすると、 マークが不活性になることはあります。 すべてのバッファでつねにバッファローカルな変数mark-activeが マークが活性かどうかを表します。 その値がnil以外であるとマークは活性です。 コマンドでdeactivate-marknil以外の値を設定すると、 エディタコマンドループに戻ったときにマークを不活性にするようにできます (ただし、暫定マーク(transient-mark)モードがオンの場合に限る)。

暫定マーク(transient-mark)モードを使う主な目的は、 マークが活性であるとこのモードはリージョンを強調表示するからです。 See Display

マークに加えて、各バッファにはマークリング(mark ring)、 つまり、マークの以前の値を保持したリストがあります。 編集コマンドがマークを変更すると、 通常、編集コマンドはマークの古い値をマークリングに保存します。 変数mark-ring-maxで、マークリングに収める要素の最大個数を指定します。 リストがこの長さに達すると、新たな要素を加えるたびに古い要素を削除します。

mark &optional force Function
この関数は、カレントバッファのマーク位置を整数で返す。

マークが不活性であると、通常、markはエラーを通知する。 しかし、forcenil以外であるとmarkはマーク位置を返すが、 当該バッファでマークが設定されたことがなければnilを返す。

mark-marker Function
この関数は、カレントバッファのマークを返す。 これは、Emacs内部のマーク位置を記録したマーカそのものであり、コピーではない。 したがって、このマーカの位置を変更すると、マークの位置に直接影響する。 この効果を望まない限り、そのようにしないこと。
(setq m (mark-marker))
     => #<marker at 3420 in markers.texi>
(set-marker m 100)
     => #<marker at 100 in markers.texi>
(mark-marker)
     => #<marker at 100 in markers.texi>

他のマーカと同様に、このマーカは任意のバッファでポイントを指すようにできる。 マークが指しているバッファ以外のバッファ内位置を指すことは勧めない。 そのようにすると、一貫性はあるが妙な結果を生じる。

set-mark position Function
この関数は、位置positionにマークを設定し、マークを活性にする。 マークの古い値はマークリングに保存しない

注意: ユーザーにマークが移動したことを示し、かつ、 まえのマーク位置を破棄したい場合にのみこの関数を使うこと。 通常、新たにマークを設定したときには、 古いマークをmark-ringに入れるべきである。 この理由から、ほとんどのアプリケーションでは、 set-markではなくpush-markpop-markを使うべきである。

Emacs Lispの初心者プログラマは、誤った目的にマークを使いがちである。 マークはユーザーの便宜のための位置を保存する。 編集コマンドは、 コマンドのユーザーレベルの機能の一部としてマークを変更する以外には、 マークを変更してはならない。 (変更する場合には、その効果を明文化しておくべきである。) Lispプログラムの内部で使う位置を記録するには、Lisp変数に保存する。 たとえばつぎのようにする。

(let ((beg (point)))
  (forward-line 1)
  (delete-region beg (point))).

push-mark &optional position nomsg activate Function
この関数は、カレントバッファのマークをpositionとし、 以前のマークのコピーをmark-ringへ入れる。 positionnilであると、ポイントの値を使う。 push-marknilを返す。

関数push-markは、通常、マークを活性にしない。 活性にするには引数activatetを指定する。

nomsgnilであると、メッセージMark setを表示する。

pop-mark Function
この関数は、mark-ringから先頭要素を取り出し、 そのマークをカレントバッファの実際のマークとする。 バッファのポイントは移動しない。 また、mark-ringが空であるとなにもしない。 マークを不活性にする。

戻り値に意味はない。

transient-mark-mode User Option
この変数がnil以外であると 暫定マーク(transient-mark)モードがオンであるが、 バッファを変更する各基本関数はdeactivate-markに設定する。 つまり、バッファを変更するコマンドは、通常、マークを不活性にする。

mark-even-if-inactive User Option
これがnil以外であると、 LispプログラムやEmacsユーザーは、マークが不活性であってもマークを使える。 このオプションは、暫定マーク(transient-mark)モードのふるまいに影響する。 このオプションがnil以外であると、 マークが不活性になるとリージョンの強調表示を止めるが、 マークを使うコマンドはマークが活性であるものとして動作する。

deactivate-mark Variable
編集コマンドがこの変数にnil以外を設定すると、 エディタコマンドループは(暫定マーク(transient-mark)モードがオンであると) コマンドから戻るとマークを不活性にする。 コマンドが終了したらマークを不活性にするために、 バッファを変更するすべての基本関数はdeactivate-markに設定する。

deactivate-mark Function
この関数は、暫定マーク(transient-mark)モードが オンであるとマークを不活性にする。 さもなければなにもしない。

mark-active Variable
この変数がnil以外であると、マークは活性である。 この変数は各バッファにおいてつねにバッファローカルである。

activate-mark-hook Variable
deactivate-mark-hook Variable
これらのノーマルフックは、それぞれ、 マークが活性になったとき、不活性になったときに実行される。 マークが活性でありリージョンが変更されたときには、 フックactivate-mark-hookはコマンドの終りでも実行される。

mark-ring Variable
このバッファローカルな変数の値は、 カレントバッファで保存したマークを最新のものから順に並べたリストである。
mark-ring
=> (#<marker at 11050 in markers.texi>
    #<marker at 10832 in markers.texi>
    ...)

mark-ring-max User Option
この変数の値は、mark-ringの最大の大きさである。 これより多くのマークをmark-ringに積むと、 push-markは新しいものを追加するときに古いものを削除する。


Node:The Region, Previous:The Mark, Up:Markers

リージョン

ポイントとマークのあいだのテキストをリージョン(region)といいます。 さまざまな関数がポイントとマークで区切られたテキストに作用しますが、 リージョンそのものに特に関連した関数だけについてここで述べます。

region-beginning Function
この関数は、リージョンの先頭の位置を(整数で)返す。 これは、ポイントかマークの小さいほうの位置である。

マークがどこも指していなければ、エラーを通知する。

region-end Function
この関数は、リージョンの末尾の位置を(整数で)返す。 これは、ポイントかマークの大きいほうの位置である。

マークがどこも指していなければ、エラーを通知する。

関数region-beginningregion-endを使う必要がある プログラムはほとんどないはずです。 リージョンに作用するように設計されたコマンドは、 普通、rを指定したinteractiveを使って リージョンの先頭と末尾をみつけます。 これにより、Lispプログラムからは引数として境界を明示的に指定できます。 (See Interactive Codes。)


Node:Text, Next:, Previous:Markers, Up:Top

テキスト

本章では、バッファ内のテキストを扱う関数について述べます。 それらのほとんどは、カレントバッファ内のテキストを 調べたり挿入したり削除しますが、しばしばポイント付近で行います。 多くは対話的に使えます。 テキストを変更するすべての関数は、変更を取り消せます(see Undo)。

テキスト関連の多くの関数は、startendという名前の引数で渡された 2つのバッファ内位置で定義されるテキストの領域に作用します。 これらの引数は、マーカ(see Markers)であるか 文字の位置を表す数値(see Positions)である必要があります。 これらの引数の順番は関係なく、startが領域の終了位置で endが開始位置であってもまったく問題ありません。 たとえば、(delete-region 1 10)(delete-region 10 1)は同値です。 startendがバッファの参照可能部分の外側にあると エラーargs-out-of-rangeを通知します。 対話的な呼び出しでは、ポイントとマークをこれらの引数として使います。

本章では、バッファ内の文字を(関係あるときには) それらのテキスト属性を含めて『テキスト』と呼びます。


Node:Near Point, Next:, Up:Text

ポイント付近のテキストを調べる

多くの関数は、ポイント付近の文字を調べるためのものです。 ここでは、数個の単純な関数について述べます。 Regexp Searchlooking-atも参照してください。

char-after &optional position Function
この関数は、カレントバッファ内の位置positionにある (つまり直後の)文字を返す。 positionがバッファの先頭のまえや末尾のうしろにあるなどして この目的に適した範囲の外側にあると、値はnilである。 positionのデフォルトはポイントである。

つぎの例では、バッファの最初の文字は@であると仮定する。

(char-to-string (char-after 1))
     => "@"

char-before &optional position Function
この関数は、カレントバッファ内の位置positionのまえにある文字を返す。 positionがバッファの先頭のまえや末尾のうしろにあるなどして この目的に適した範囲の外側にあると、値はnilである。 positionのデフォルトはポイントである。

following-char Function
この関数は、カレントバッファのポイントのうしろにある文字を返す。 これは(char-after (point))と同様である。 しかし、ポイントがバッファの末尾にあると、 following-charは0を返す。

ポイントはつねに文字のあいだにあり、 端末のカーソルはポイントの直後の文字に重ねて表示されることに注意してほしい。 したがって、following-charが返す文字は、 カーソルが重なっている文字である。

つぎの例では、ポイントはacのあいだにある。

---------- Buffer: foo ----------
Gentlemen may cry ``Pea-!-ce! Peace!,''
but there is no peace.
---------- Buffer: foo ----------

(char-to-string (preceding-char))
     => "a"
(char-to-string (following-char))
     => "c"

preceding-char Function
この関数は、カレントバッファのポイントのまえの文字を返す。 例については上記のfollowing-charを参照。 ポイントがバッファの先頭にあると、preceding-charは0を返す。

bobp Function
この関数は、ポイントがバッファの先頭にあるとtを返す。 ナロイングしていると、これはバッファの参照可能部分の先頭を意味する。 Pointpoint-minも参照。

eobp Function
この関数は、ポイントがバッファの末尾にあるとtを返す。 ナロイングしていると、これはバッファの参照可能部分の末尾を意味する。 Pointpoint-maxも参照。

bolp Function
この関数は、ポイントが行頭にあるとtを返す。 see Text Lines。 バッファ(あるいはその参照可能部分)の先頭は、 つねに行頭とみなす。

eolp Function
この関数は、ポイントが行末にあるとtを返す。 see Text Lines。 バッファ(あるいはその参照可能部分)の末尾は、 つねに行末とみなす。


Node:Buffer Contents, Next:, Previous:Near Point, Up:Text

バッファの内容を調べる

本節では、Lispプログラムでバッファ内の任意の部分のテキストを文字列に変換する ための2つの関数について述べます。

buffer-substring start end Function
この関数は、カレントバッファのstartendの位置で定義される 領域のテキストのコピーを含んだ文字列を返す。 引数がバッファの参照可能部分の内側の位置でないと、 buffer-substringはエラーargs-out-of-rangeを通知する。

startendより小さい必要はなく、引数の順番はどちらでもよい。 しかし、ほとんどの場合、小さい引数を先に書く。

コピーされるテキストにテキスト属性がある場合、 テキスト属性もそれが属する文字とともに文字列へコピーされる。 see Text Properties。 しかし、バッファのオーバレイ(see Overlays)とそれらの属性は 無視されコピーされない。

---------- Buffer: foo ----------
This is the contents of buffer foo

---------- Buffer: foo ----------

(buffer-substring 1 10)
=> "This is t"
(buffer-substring (point-max) 10)
=> "he contents of buffer foo
"

buffer-substring-no-properties start end Function
この関数はbuffer-substringと同様であるが、 テキスト属性をコピーせずに文字だけをコピーする点が異なる。 see Text Properties

buffer-string Function
この関数は、カレントバッファの参照可能部分全体の内容を文字列として返す。 これは、つぎと等価である。
(buffer-substring (point-min) (point-max))
---------- Buffer: foo ----------
This is the contents of buffer foo

---------- Buffer: foo ----------

(buffer-string)
     => "This is the contents of buffer foo
"

thing-at-point thing Function
ポイントの周りやそのうしろにあるthingを文字列として返す。

引数thingは、構文上の要素の種類を指定するシンボルである。 可能な値は、symbollistsexpdefunfilenameurlwordsentencewhitespacelinepageなどである。

---------- Buffer: foo ----------
Gentlemen may cry ``Pea-!-ce! Peace!,''
but there is no peace.
---------- Buffer: foo ----------

(thing-at-point 'word)
     => "Peace"
(thing-at-point 'line)
     => "Gentlemen may cry ``Peace! Peace!,''\n"
(thing-at-point 'whitespace)
     => nil


Node:Comparing Text, Next:, Previous:Buffer Contents, Up:Text

テキストの比較

この関数により、バッファ内のテキストの部分同士を 文字列にコピーせずに比較できます。

compare-buffer-substrings buffer1 start1 end1 buffer2 start2 end2 Function
この関数は、同一バッファ内の2つの部分文字列、あるいは、 異なる2つのバッファの部分文字列を比較する。 始めの3つの引数は、バッファとそのバッファ内の2つの位置を与え、 1つの部分文字列を指定する。 残りの3つの引数も同様にして別の部分文字列を指定する。 カレントバッファを表すために、 buffer1buffer2のいずれか、あるいは、 両方にnilを指定できる。

始めの文字列のほうが小さければ値は負であり、 始めのほうが大きければ値は正であり、等しければ0である。 結果の絶対値は、部分文字列の中で最初に異なる文字の添字足す1である。

この関数は、case-fold-searchnil以外であると、 文字の比較では大文字小文字を区別しない。 テキスト属性はつねに無視する。

カレントバッファにはテキストfoobarbar haha!rara!があるとする。 すると、この例の2つの部分文字列はrbar rara!である。 2番目の文字で最初の文字列のほうが大きいので、結果は2である。

(compare-buffer-substring nil 6 11 nil 16 21)
     => 2


Node:Insertion, Next:, Previous:Comparing Text, Up:Text

テキストの挿入

挿入(insertion)とは、バッファに新たなテキストを追加することです。 挿入されたテキストはポイント位置に、つまり、 ポイントのまえの文字とポイントのあとの文字のあいだに入ります。 挿入されたテキストのまえにポイントを留める関数もあれば、 そのうしろに留める関数もあります。 前者をポイントのうしろへ挿入と呼び、 後者をポイントのまえへ挿入と呼びます。

挿入により、挿入箇所よりうしろの位置を指すマーカは再配置されて 同じ周りの文字に留まります(see Markers)。 マーカが挿入箇所を指している場合には、 マーカの挿入型(see Marker Insertion Types)に依存して、 挿入するとマーカが再配置されたりされなかったりします。 insert-before-markersなどの特定の特殊な関数は、 マーカの挿入型に関わらず、 挿入されたテキストのうしろを指すように そのようなすべてのマーカを再配置します。

カレントバッファが読み出し専用であると、挿入関数はエラーを通知します。

これらの関数は、テキストの文字群をそれらの属性とともに 文字列からバッファへコピーします。 挿入された文字群は、コピーされるまえとまったく同じ属性を持ちます。 対照的に、文字列やバッファの一部ではない孤立した引数として 指定された文字群は、周りのテキストからテキスト属性を継承します。

挿入関数は、文字列由来やバッファ由来のテキストの場合には、 マルチバイトバッファへ挿入するために ユニバイトからマルチバイトへテキストを変換し、逆向きの変換も行います。 しかし、カレントバッファがたとえマルチバイトバッファであっても、 128から255のユニバイト文字コードはマルチバイト文字には変換しません。 See Converting Representations

insert &rest args Function
この関数は、文字列や文字群argsをカレントバッファのポイント位置に挿入し、 ポイントを先へ進める。 いいかえれば、ポイントのまえにテキストを挿入する。 argsが文字列でも文字でもないと、エラーを通知する。 値はnilである。

insert-before-markers &rest args Function
この関数は、文字列や文字群argsをカレントバッファのポイント位置に挿入し、 ポイントを先へ進める。 argsが文字列でも文字でもないと、エラーを通知する。 値はnilである。

挿入箇所を指していたマーカを挿入されたテキストのうしろを指すように再配置 する点で、この関数は他の挿入関数と異なる。 挿入箇所でオーバレイが始まるときには、 挿入されたテキストはオーバレイの範囲外に出る。 空でないオーバレイが挿入箇所で終るときには、 挿入されたテキストはオーバレイの範囲内に入る。

insert-char character &optional count inherit Function
この関数は、カレントバッファのポイントのまえに 文字charactercount個挿入する。 引数countは数(nilは1を意味する)であり、 characterは文字であること。 値はnilである。

この関数は、カレントバッファがたとえマルチバイトバッファであっても、 128から255のユニバイト文字コードはマルチバイト文字には変換しない。 see Converting Representations

inheritnil以外であると、挿入された文字は、 挿入箇所の前後の2つの文字からスティッキテキスト属性を継承する。

insert-buffer-substring from-buffer-or-name &optional start end Function
この関数は、バッファfrom-buffer-or-name(既存であること)の部分を カレントバッファのポイントのまえへ挿入する。 挿入されるテキストはstartからendまでの領域である。 (これらの引数のデフォルトは、当該バッファの参照可能部分の先頭と末尾である。) この関数はnilを返す。

この例では、バッファbarをカレントバッファとしてフォームを実行する。 バッファbarは最初は空であると仮定する。

---------- Buffer: foo ----------
We hold these truths to be self-evident, that all
---------- Buffer: foo ----------

(insert-buffer-substring "foo" 1 20)
     => nil

---------- Buffer: bar ----------
We hold these truth-!-
---------- Buffer: bar ----------

挿入に加えて周りのテキストからテキスト属性を継承する他の関数については、 See Sticky Properties。 字下げ関数が挿入した白文字もテキスト属性を継承します。


Node:Commands for Insertion, Next:, Previous:Insertion, Up:Text

ユーザーレベルの挿入コマンド

本節では、テキストを挿入する上位レベルのコマンドについて述べます。 これらはLispプログラムでも有用ですが主にユーザー向けのコマンドです。

insert-buffer from-buffer-or-name コマンド
このコマンドは、from-buffer-or-name(既存であること)の全内容を カレントバッファのポイントのうしろに挿入する。 挿入されたテキストのうしろにマークを置く。 値はnilである。

self-insert-command count コマンド
このコマンドは、最後に打たれた文字を挿入する。 ポイントのまえにcount回挿入してnilを返す。 ほとんどの印字文字はこのコマンドにバインドされている。 普通の状況では、self-insert-commandは Emacsにおいてもっとも頻繁に呼び出される関数であるが、 プログラムではキーマップに登録する以外にはほとんど使わない。

対話的に呼ばれると、countは数値前置引数である。

このコマンドは、挿入した文字が空白や改行であると、 auto-fill-functionnil以外であると auto-fill-functionを呼び出す (see Auto Filling)。

このコマンドは、略語(abbrev)モードがオンであり、かつ、 挿入した文字が単語構成構文でないと、略語展開を行う。 (Abbrevsとsee Syntax Class Table。)

挿入した文字が閉じ括弧構文であるときに blink-paren-functionを呼び出す責任も持つ (see Blinking)。

newline &optional number-of-newlines コマンド
このコマンドは、カレントバッファのポイントのまえに改行を挿入する。 number-of-newlinesを指定すると、その個数だけ改行文字を挿入する。

この関数は、現在のコラム番号がfill-columnの値よりも大きく number-of-newlinesnilであると auto-fill-functionを呼び出す。 auto-fill-functionの典型的な仕事は改行を挿入することである。 ここでの全体としての効果は、改行を2つの異なる位置、つまり、 ポイント位置と行のまえの箇所に挿入することである。 newlineは、number-of-newlinesnil以外であると 自動詰め込みを行わない。

このコマンドは、左端の余白が0以外であるとその分だけ字下げする。 see Margins

戻り値はnilである。 対話的に呼ばれると、countは数値前置引数である。

split-line コマンド
このコマンドは、行のポイントのうしろの部分を垂直に降ろして 変更前の真下に行を移動することで現在行を分割する。 関数indent-toを用いて、降ろした行の先頭に必要に応じて白文字を挿入する。

プログラムではまったくこの関数を使わない。

overwrite-mode Variable
この変数は、上書き(overwrite)モードがオンかどうかを制御する。 この値は、overwrite-mode-textualoverwrite-mode-binarynilのいずれかであること。 overwrite-mode-textualは、テキストの上書きモード (改行とタブを特別に扱う)を指定し、 overwrite-mode-binaryは、バイナリの上書きモード (改行やタブも他の文字と同様に扱う)を指定する。


Node:Deletion, Next:, Previous:Commands for Insertion, Up:Text

テキストの削除

削除とは、バッファ内のテキストのある部分をキルリング (see The Kill Ring)に保存せずに取りさることです。 削除したテキストはヤンクはできませんが、 アンドゥ機構(see Undo)を使って再度挿入できます。 特別な場合にはキルリングにテキストを保存する削除関数もあります。

すべての削除関数はカレントバッファに作用し、nilの値を返します。

erase-buffer コマンド
この関数は、カレントバッファから全テキストを削除して空にする。 バッファが読み出し専用であると、エラーbuffer-read-onlyを通知する。 さもなければ、いっさい確認を取らずにテキストを削除する。 nilを返す。

バッファから多量のテキストを削除すると、通常、 『バッファが縮小した』としてそのバッファの自動保存を禁止する。 しかし、erase-bufferはこうしない。 これまでのテキストと将来のテキストには関連がなく、 これまでのテキストのサイズと比較すべきでないと考えるからである。

delete-region start end コマンド
このコマンドは、startendで定義されるカレントバッファの テキストを削除する。 戻り値はnilである。 削除された領域の内側にポイントがあると、 その値は削除後にはstartになる。 さもなければ、マーカと同様にポイントは 周りのテキストに留まるように再配置される。

delete-char count &optional killp コマンド
このコマンドは、ポイントの直後の、あるいは、 countが負であるとポイントの直前のcount個の文字を削除する。 killpnil以外であると、 削除した文字をキルリングに保存する。

対話的に呼ばれると、countは数値前置引数であり、 killpは未処理の前置引数である。 つまり、前置引数を指定すると、テキストをキルリングに保存する。 前置引数を指定しないと1文字だけを削除するが、 キルリングには保存しない。

戻り値はつねにnilである。

delete-backward-char count &optional killp コマンド
このコマンドは、ポイントの直前の、あるいは、 countが負であるとポイントの直後のcount個の文字を削除する。 killpnil以外であると、 削除した文字をキルリングに保存する。

対話的に呼ばれると、countは数値前置引数であり、 killpは未処理の前置引数である。 つまり、前置引数を指定すると、テキストをキルリングに保存する。 前置引数を指定しないと1文字だけを削除するが、 キルリングには保存しない。

戻り値はつねにnilである。

backward-delete-char-untabify count &optional killp コマンド
このコマンドは、タブを空白にかえながら後向きにcount個の文字を削除する。 つぎに削除する文字がタブであると、まずタブを配置を保つだけの等価な個数の 空白に置換してから、タブのかわりにそれらの空白を削除する。 killpnil以外であると、このコマンドは 削除した文字をキルリングに保存する。

countが正である場合に限って、タブを空白に変換する。 countが負であると、ポイントのうしろのちょうど -count個の文字を削除する。

対話的に呼ばれると、countは数値前置引数であり、 killpは未処理の前置引数である。 つまり、前置引数を指定すると、テキストをキルリングに保存する。 前置引数を指定しないと1文字だけを削除するが、 キルリングには保存しない。

戻り値はつねにnilである。

backward-delete-char-untabify-method User Option
このオプションは、backward-delete-char-untabifyでの 白文字の扱い方を指定する。 可能な値は、タブを空白に変換してから空白を削除することを意味する デフォルトのuntabify、 1回の呼び出しでポイントのまえにある白文字をすべて削除することを意味する hungry、 白文字に対して特別なことをしないことを意味するnilである。


Node:User-Level Deletion, Next:, Previous:Deletion, Up:Text

ユーザーレベルの削除コマンド

本節では、テキストを削除する上位レベルのコマンドについて述べます。 これらはLispプログラムでも有用ですが主にユーザー向けのコマンドです。

delete-horizontal-space コマンド
この関数は、ポイントの周りの空白やタブをすべて削除する。 nilを返す。

つぎの例では、毎回ポイントを2番目と3番目の文字のあいだに置いて、 各行につき1回ずつdelete-horizontal-spaceを計4回呼び出す。

---------- Buffer: foo ----------
I -!-thought
I -!-     thought
We-!- thought
Yo-!-u thought
---------- Buffer: foo ----------

(delete-horizontal-space)   ; Four times.
     => nil

---------- Buffer: foo ----------
Ithought
Ithought
Wethought
You thought
---------- Buffer: foo ----------

delete-indentation &optional join-following-p コマンド
この関数は、ポイントがある行をそのまえの行に連結する。 連結箇所の白文字は削除し、場合によっては空白1個に置き換える。 join-following-pnil以外であると、 delete-indentationは、この行を後続の行に連結する。 関数はnilを返す。

詰め込み接頭辞があり、かつ、連結対象の2番目の行が その接頭辞で始まっている場合には、 delete-indentationは連結するまえに詰め込み接頭辞を削除する。 see Margins

以下の例では、ポイントはeventsで始まる行にあり、 そのまえの行の行末に空白があっても違いはない。

---------- Buffer: foo ----------
When in the course of human
-!-    events, it becomes necessary
---------- Buffer: foo ----------

(delete-indentation)
     => nil

---------- Buffer: foo ----------
When in the course of human-!- events, it becomes necessary
---------- Buffer: foo ----------

行を連結したあと、 関数fixup-whitespaceには、 連結箇所に空白を置くかどうかを決定する責任がある。

fixup-whitespace Function
この関数は、文脈に応じて、 ポイントを囲む白文字すべてを1つの空白に置換するかまったくなくす。 nilを返す。

行の先頭や末尾では、空白の適切な量は0である。 閉じ括弧構文の文字のまえや、 開き括弧構文や式前置子構文の文字のうしろでも空白はないほうが適している。 それ以外では、空白1個が適している。 see Syntax Class Table

以下の例では、最初の行の単語spacesのまえにポイントがあるときに 最初にfixup-whitespaceが呼ばれる。 2度目に呼ばれるときには、ポイントは(の直後にある。

---------- Buffer: foo ----------
This has too many     -!-spaces
This has too many spaces at the start of (-!-   this list)
---------- Buffer: foo ----------

(fixup-whitespace)
     => nil
(fixup-whitespace)
     => nil

---------- Buffer: foo ----------
This has too many spaces
This has too many spaces at the start of (this list)
---------- Buffer: foo ----------

just-one-space コマンド
このコマンドは、ポイントの周りのすべての空白やタブを1個の空白に置き換える。 nilを返す。

delete-blank-lines コマンド
この関数は、ポイントを囲む空行を削除する。 前後に複数の空行がある空行にポイントがある場合、 1つの空行を残してそれ以外はすべて削除する。 孤立した1つの空行にポイントがある場合には、その行を削除する。 空行でない行にポイントがある場合には、 その行のうしろにある空行をすべて削除する。

空行とは、タブや空白のみから成る行と定義する。

delete-blank-linesnilを返す。


Node:The Kill Ring, Next:, Previous:User-Level Deletion, Up:Text

キルリング

キル関数は削除関数のようにテキストを削除しますが、 ユーザーがヤンク(yank)で再度挿入できるように保存します。 これらの関数の多くは、その名前にkill-があります。 対照的に、delete-で始まる名前の関数は、 ヤンクできるようにテキストを保存しません(アンドゥはできる)。 それらは『削除』関数です。

キルコマンドの多くは主に対話的に使うものであり、 ここではそれらについては述べません。 ここで述べるのは、そのようなコマンドを書くために使う関数についてです。 これらの関数は読者がテキストをキルするコマンドを書くために使えます。 Lisp関数において内部目的のためにテキストを削除する必要があるときには、 キルリングの内容を乱さないように普通は削除関数を用いるべきです。 See Deletion

キルしたテキストはあとでヤンクできるように キルリング(kill ring)に保存されます。 これは、最後にキルしたテキストだけでなく、 最近キルしたものを多数保持するリストです。 これを『リング』と呼ぶのは、 要素が循環しているようにヤンクが扱うからです。 このリストは変数kill-ringに保持されていて、 リスト向けの通常の関数で操作できますが、 本節で述べるように、それをリングとして扱う特別な関数もあります。

単語『キル』の使い方が不適当だと考える人々がいます。 『キル』したものを特に破壊しない操作を表すために使っているからです。 日常生活に照らしてみると、死は恒久的であり『キル』したものが 生き返ることはありません。 したがって、別の隠喩も提案されています。 たとえば、原稿を鋏で切り貼りすることに慣れていた前計算機世代の人々には 『カットリング』のほうが意味が通じるでしょう。 しかし、いまさら用語を変更するのは困難です。


Node:Kill Ring Concepts, Next:, Up:The Kill Ring

キルリングの概念

キルリングは、もっとも最近にキルされたものを先頭にして、 キルされたテキストを文字列としてリストに記録します。 たとえば、短いキルリングはつぎのようになります。

("some text" "a different piece of text" "even older text")

リストの長さがkill-ring-maxに達すると、 新たな項目を追加すると自動的に最後の項目を削除します。

キルコマンドが他のコマンドと混在する場合、 各キルコマンドはキルリングに新たな項目を追加します。 連続した複数のキルコマンドは、キルリングに1つの項目を作りあげ、 それを1個としてヤンクできます。 2番目以降の連続したキルコマンドは、最初のキルコマンドが作った 項目にテキストを追加していきます。

ヤンクでは、キルリングの1つの項目をリングの『先頭』として区別します。 リングの別の項目を『先頭』と指定することでリングを『回転』する コマンドもあります。


Node:Kill Functions, Next:, Previous:Kill Ring Concepts, Up:The Kill Ring

キル向けの関数

kill-regionは、テキストをキルするための普通のサブルーティンです。 この関数を呼び出す任意のコマンドは『キルコマンド』です (その名前にはkillがあるはず)。 kill-regionは、新たにキルされたテキストを キルリングの先頭に新たな項目として追加したり、 もっとも最近の項目に加えます。 まえのコマンドがキルコマンドであるかどうかを (last-commandを使って)自動的に判定し、 もしそうならば、キルされたテキストをもっとも最近の項目に加えます。

kill-region start end コマンド
この関数は、startendで定義される領域のテキストをキルする。 テキストは削除されるが、テキスト属性とともにキルリングに保存される。 値はつねにnilである。

対話的に呼ばれると、startendはポイントとマークである。

バッファが読み出し専用であると、 kill-regionはキルリングを同様に変更するが、 バッファを変更せずにエラーを通知する。 読み出し専用バッファからキルリングへテキストをコピーするために、 ユーザーはすべてのキルコマンドを使えるのでこれは便利である。

kill-read-only-ok User Option
このオプションがnil以外であると、 kill-regionは、バッファが読み出し専用であってもエラーとしない。 そのかわりに、キルリングを更新しバッファは変更せずに戻る。

copy-region-as-kill start end コマンド
このコマンドは、startendで定義される領域を (テキスト属性とともに)キルリングに保存するが、 バッファからテキストを削除しない。 nilを返す。 また、カーソルを一時的に移動してコピーしたテキストの範囲を示すか、 あるいは、エコー領域にメッセージを表示する。

このコマンドはthis-commandkill-regionを設定しないので、 これ以降のキルコマンドはキルリングの同じ項目には加えない。

Emacs 18版でも使うつもりがない限り、 Lispプログラムからはcopy-region-as-killを呼ばないこと。 Emacsの新しい版では、そのかわりにkill-newkill-appendを 使うほうがよい。 see Low-Level Kill Ring


Node:Yank Commands, Next:, Previous:Kill Functions, Up:The Kill Ring

ヤンク向けの関数

ヤンク(yank)とは、キルリングからまえにキルされたテキストの項目を 再度挿入することです。

yank &optional arg コマンド
このコマンドは、キルリングの先頭項目のテキストを ポイントのまえに挿入する。 そのテキストの先頭にマークを末尾にポイントを置く。

argがリスト(対話的な呼び出しではユーザーが数字文字なしに C-uを打ったとき)であると、yankは上に述べたように テキストを挿入するが、ヤンクしたテキストの先頭にポイントを 末尾にマークを置く。

argが数であると、yankarg番目のもっとも最近に キルされたテキスト、つまり、キルリングリストのarg番目の項目を 挿入する。

yankはキルリングの内容を変更したり回転しない。 nilを返す。

yank-pop arg コマンド
このコマンドは、キルリングからヤンクした項目を キルリングの別の項目で置き換える。

これはyankや別のyank-popの直後でのみ許される。 そのような場合、リージョンにはヤンクしたばかりのテキストが含まれる。 yank-popはそのテキストを削除し、 その位置にキルされた別のテキストを挿入する。 削除したテキストはすでにキルリングのどこかにあるので、 キルリングには追加しない。

argnilであると、キルリングの古い項目で置き換える。 argが数であると、arg番古いキルで置き換える。 argが負であると、より最近のキルで置き換える。

キルリング内でのキルの順番は、 最古のもののつぎに最新のものがあり、 最新のもののまえに最古のものがあるように折り返されている。

戻り値はつねにnilである。


Node:Low-Level Kill Ring, Next:, Previous:Yank Commands, Up:The Kill Ring

下位レベルのキルリング

これらの関数と変数は、下位レベルでキルリングを参照するためのものですが、 Lispプログラムで使っても便利です。 これらはウィンドウシステムのセレクション(see Window System Selections) との相互作用の面倒をみてくれるからです。

current-kill n &optional do-not-move Function
関数current-killは、キルリングの『先頭』として区別する ヤンクポインタを(新しいキルから古いキルへ向けて)n個分回転し、 リングのその位置のテキストを返す。

省略可能な第2引数do-not-movenil以外であると、 current-killは、ヤンクポインタは変更せずに、 現在のヤンクポインタから数えてn番目のキルを返す。

nが0であると、もっとも最近のキルを要求することを表し、 current-killは、キルリングを調べるまえに (以下に述べる)interprogram-paste-functionの値を呼び出す。

kill-new string Function
この関数は、テキストstringを新たな項目として キルリングの先頭に置く。 必要ならば最古の項目を破棄する。 interprogram-cut-function(下記参照)の値も起動する。

kill-append string before-p Function
この関数は、キルリングの先頭項目にテキストstringを追加する。 通常、stringはその項目の末尾に加わるが、 before-pnil以外であるとその項目の先頭に加わる。 この関数は、interprogram-cut-function(下記参照)の値も起動する。

interprogram-paste-function Variable
この変数は、ウィンドウシステムを使っているときに 別のプログラムからキルされたテキストを転送する方法を提供する。 その値は、nilであるか、引数なしの関数であること。

値が関数であると、 『もっとも最近のキル』を得るためにcurrent-killが呼び出す。 関数がnil以外の値を返すと、 その値は『もっとも最近のキル』として使われる。 nilを返せば、kill-ringの先頭項目が使われる。

このフックの普通の用途は、 セレクションが別のアプリケーションに属する場合であっても、 ウィンドウシステムの一次セレクションを もっとも最近のキルとして得ることである。 see Window System Selections

interprogram-cut-function Variable
この変数は、ウィンドウシステムを使っているときに キルされたテキストを別のプログラムへ転送する方法を提供する。 その値は、nilであるか、引数なしの関数であること。

値が関数であると、kill-newkill-appendが キルリングの新たな先頭項目を引数として呼び出す。

このフックの普通の用途は、 新たにキルされたテキストを ウィンドウシステムの一次セレクションにすることである。 see Window System Selections


Node:Internals of Kill Ring, Previous:Low-Level Kill Ring, Up:The Kill Ring

キルリングの内部

変数kill-ringは、文字列のリストの形でキルリングの内容を保持します。 もっとも最近のキルがつねにリストの先頭にあります。

変数kill-ring-yank-pointerは、 CARがつぎにヤンクすべきテキストであるような キルリングリストの項目を指しています。 この変数がリングの『先頭』を識別するといいます。 kill-ring-yank-pointerを別の項目へ動かすことを キルリングを回転すると呼びます。 ヤンクポインタを動かす関数は、 リストの末尾からリストの先頭へ折り返しその逆も行うので、 キルリングを『リング』と呼ぶのです。 リングの回転は仮想的なものであり、 kill-ringの値は変更しません。

kill-ringkill-ring-yank-pointerもLisp変数であり、 それらの値は普通のリストです。 kill-ring-yank-pointerの名前の単語『ポインタ』は、 つぎのヤンクコマンドで使うリストの項目を識別することが 変数の目的であることを表します。

kill-ring-yank-pointerの値は、キルリングリストの 1つの項目とつねにeqです。 これが識別する項目は、その項目のCARです。 キルリングを変更するキルコマンドも、 kill-ringの値をこの変数の値とします。 その効果は、新たにキルされたテキストが先頭にくるように リングを回転することです。

キルリング("some text" "a different piece of text" "yet older text")の 第2項目を変数kill-ring-yank-pointerが指しているようすをつぎに示します。

kill-ring                  ---- kill-ring-yank-pointer
  |                       |
  |                       v
  |     --- ---          --- ---      --- ---
   --> |   |   |------> |   |   |--> |   |   |--> nil
        --- ---          --- ---      --- ---
         |                |            |
         |                |            |
         |                |             -->"yet older text"
         |                |
         |                 --> "a different piece of text"
         |
          --> "some text"

C-yyank)の直後にM-yyank-pop)を使うと この状態になります。

kill-ring Variable
この変数は、もっとも最近にキルされたものを最初にして キルされたテキストを順に並べたリストを保持する。

kill-ring-yank-pointer Variable
この変数の値は、キルリングのどの要素が ヤンクするためのリングの『先頭』であるかを表す。 より正確には、その値はkill-ringのリストの一部であり、 そのCARC-yがヤンクするキルされた文字列である。

kill-ring-max User Option
この変数の値は、末尾の要素が破棄されるまでに キルリングが増大できる最大の長さである。 kill-ring-maxのデフォルト値は30である。


Node:Undo, Next:, Previous:The Kill Ring, Up:Text

アンドゥ

ほとんどのバッファには、バッファのテキストに対する変更をアンドゥ(もとに戻す) できるようにすべての変更を記録する アンドゥリスト(undo list)があります。 (アンドゥリストのないバッファは、 Emacsがアンドゥは有用ではないと仮定する特殊目的のバッファである。) バッファのテキストを変更するすべての基本関数は、 変数buffer-undo-listに収めたアンドゥリストの先頭に 自動的に要素を追加します。

buffer-undo-list Variable
この変数の値は、カレントバッファのアンドゥリストである。 値tはアンドゥ情報の記録を禁止する。

アンドゥリストの要素として可能なものをつぎに示します。

position
この種の要素は、まえのポイント値を記録する。 この要素をアンドゥするとポイントをpositionへ移動する。 通常のカーソル移動では、いかなる種類のアンドゥ記録も作らないが、 削除操作ではコマンド実行前のポイント位置を記録するためにこの項目を作る。
(beg . end)
この種の要素は、挿入されたテキストを削除する方法を表す。 挿入されたテキストはバッファのbegからendまでの範囲を占める。
(text . position)
この種の要素は、削除されたテキストを再度挿入する方法を表す。 削除されたテキストそのものは文字列textである。 再度挿入する位置は(abs position)である。
(t high . low)
この種の要素は、未変更のバッファが変更されたことを表す。 highlowは2つの整数であり、それぞれ、 まえに訪問したときや保存したときの訪問しているファイルの更新時刻の 16ビットを記録している。 primitive-undoはこれらの値を用いて、 バッファを再度未変更と印を付けるかどうか判定する。 ファイルの更新時刻がこれに一致するときにのみ再度未変更とする。
(nil property value beg . end)
この種の要素は、テキスト属性の変更を記録する。 変更をアンドゥするにはつぎのようにする。
(put-text-property beg end property value)

(marker . adjustment)
この種の要素は、周りのテキストが削除されたために マーカmarkerを再配置し adjustment文字分位置を移動したことを記録する。 この要素をアンドゥすると、 marker - adjustment文字に移動する。
nil
この要素は境界である。 2つの境界のあいだの要素群を変更グループ(change group)と呼ぶ。 通常、各変更グループは1つのキーボードコマンドに対応し、 アンドゥコマンドはグループ全体を1個としてアンドゥする。

undo-boundary Function
この関数は、アンドゥリストに境界要素を置く。 アンドゥコマンドはそのような境界で停止し、 連続したアンドゥコマンドはよりまえの境界までアンドゥする。 この関数はnilを返す。

エディタコマンドループは、 各キー列を実行するまえにアンドゥの境界を自動的に作る。 したがって、各アンドゥは、1つのコマンドの効果を普通は取り消す。 自己挿入の入力文字は例外である。 コマンドループはそのような最初の文字に境界を作り、 つぎの19個の連続する自己挿入の入力文字では境界を作らず、 20番目で境界を作るということを自己挿入の入力文字が続く限り行う。

別のバッファでアンドゥ可能な変更を行うたびに バッファのすべての変更で境界を追加する。 これは、各コマンドが変更した箇所で各バッファに境界を作ることを 保証するためである。

1つのコマンドの効果を複数に分けるためにこの関数を直接呼ぶことは有用である。 たとえば、query-replaceは各置換のあとでundo-boundaryを呼び出し、 ユーザーが個々の置換を1つ1つアンドゥできるようにする。

primitive-undo count list Function
これは、アンドゥリストの要素をアンドゥする基本的な関数である。 listの先頭のcount個の要素をアンドゥし、listの残りを返す。 この関数をLispで書くこともできるが、Cで書いたほうが便利である。

primitive-undoは、バッファを変更すると バッファのアンドゥリストに要素を追加する。 アンドゥコマンドは一連のアンドゥ操作を始めるときに アンドゥリストを保存して混乱を避ける。 アンドゥ操作では、保存しておいた値を使い更新する。 アンドゥによって追加される新たな要素はこの保存された値の一部ではないので、 それらはアンドゥを続行しても干渉しない。


Node:Maintaining Undo, Next:, Previous:Undo, Up:Text

アンドゥリストの管理

本節では、指定されたバッファでアンドゥ情報の記録をオン/オフする 方法について述べます。 また、アンドゥリストが大きくなりすぎないように 自動的に切り詰める方法についても説明します。

新たに作成されたバッファのアンドゥ情報の記録は普通は始めオンですが、 バッファ名が空白で始まる場合は最初からオフです。 つぎの2つの関数を使うか、読者自身がbuffer-undo-listに設定すれば、 アンドゥ記録を明示的にオン/オフできます。

buffer-enable-undo &optional buffer-or-name コマンド
このコマンドは、バッファbuffer-or-nameでのアンドゥ記録をオンにし、 以降の変更を取り消せるようにする。 引数を指定しないと、カレントバッファを使う。 当該バッファでアンドゥ記録がすでにオンであると、 この関数はなにもしない。 nilを返す。

対話的に呼ばれると、buffer-or-nameはカレントバッファである。 他のバッファを指定できない。

buffer-disable-undo &optional buffer コマンド
buffer-flush-undo &optional buffer コマンド
この関数はバッファbufferのアンドゥリストを破棄し、 以降のアンドゥ情報の記録をオフにする。 その結果、これ以前の変更も以降の変更も取り消すことはできない。 bufferのアンドゥリストがすでにオフであると、 この関数にはなんの効果もない。

この関数はnilを返す。

名前buffer-flush-undoは廃れているとはみなさないが、 好ましい名前はbuffer-disable-undoである。

編集を続けるにしたがってアンドゥリストはどんどん長くなります。 これらがメモリを使い尽くさないように、 読者が設定した上限サイズにガベッジコレクションが切り詰めます。 (この目的においてアンドゥリストの『サイズ』は、 リストを構成するコンスセルの個数と削除された文字列の和である。) 2つの変数undo-limitundo-strong-limitは、 許容できるサイズの範囲を制御します。

undo-limit Variable
これはアンドゥリストの許容できるサイズの緩い制限である。 このサイズを越える位置にある変更グループは保持される最古のものである。

undo-strong-limit Variable
これはアンドゥリストの許容できるサイズの上限である。 このサイズを越える位置にある変更グループは (これより古いものも含めて)削除される。 例外が1つあり、最新の変更グループは それがどれほど大きくてもけっして破棄しない。


Node:Filling, Next:, Previous:Maintaining Undo, Up:Text

詰め込み

詰め込み(fill)とは、指定されている最大幅 (を越えず)にほぼ収まるように(行分け位置を移動して) 行の長さを調整することです。 さらに、行を幅揃え(justify)することもできます。 つまり、左右の両端や片側の余白をきちんと揃えるため 空白を挿入することです。 幅は変数fill-columnで制御します。 読みやすいように、行は70コラム程度に収めるべきです。

テキストを挿入するにつれて自動的にテキストを詰め込むには、 自動詰め込み(auto-fill)モード(see Auto Filling)を使いますが、 既存のテキストを変更しても正しくない詰め込み状態のまま放置されます。 したがって、そのようなテキストは明示的に詰め込む必要があります。

本節のほとんどの関数が返す値には意味はありません。 詰め込みを行うすべての関数は、現在の左端余白、現在の右端余白、 現在の幅揃えスタイルに注意をはらいます(see Margins)。 現在の幅揃えスタイルがnoneであると、 詰め込み関数は実際にはなにもしません。

詰め込み関数には引数justifyを取るものもあります。 それがnil以外であると、幅揃えの種類を指示します。 特定の幅揃えスタイルを指示するものは、 leftrightfullcenterです。 それがtであると、 テキストの当該部分には現在の幅揃えスタイルを用いることを意味します (下記のcurrent-justificationを参照)。 これ以外の値はfullとして扱います。

対話的に詰め込み関数を呼ぶときに前置引数を使うと、 justifyとして値fullを暗に指示します。

fill-paragraph justify コマンド
このコマンドは、ポイントがある段落、あるいは、ポイントのあとの段落を詰め込む。 justifynil以外であると、各行の幅揃えも行う。 段落の境界を探すために普通の段落移動コマンドを用いる。 see Paragraphs

fill-region start end &optional justify nosqueeze to-eop コマンド
このコマンドは、startからendの領域内の各段落を詰め込む。 justifynil以外であれば、幅揃えも行う。

nosqueezenil以外であると、 行分け以外の白文字にはふれないことを意味する。 to-eopnil以外であると、 段落の末尾まで、あるいは、 use-hard-newlinesがオンならばつぎのハード改行(下記参照)までを 詰め込むことを意味する。

変数paragraph-separateは、段落の区別方法を制御する。 see Standard Regexps

fill-individual-paragraphs start end &optional justify mail-flag コマンド
このコマンドは、領域内の各段落を各段落の詰め込み接頭辞に従って詰め込む。 したがって、段落の行が空白で字下げされていると、 詰め込んだあとの段落も同じように字下げされる。

最初の2つの引数startendは、 詰め込むべき範囲の先頭と末尾である。 3番目と4番目の引数、justifymail-flagは省略できる。 justifynil以外であると、 段落の詰め込みに加えて幅揃えも行う。 mail-flagnil以外であると、 メイルメッセージなのでヘッダ行を詰め込まないことを意味する。

通常、fill-individual-paragraphsは、 字下げが変わると新しい段落の開始とみなす。 fill-individual-varying-indentnil以外であると、 区切り行のみが段落を区切るとみなす。 これは段落の先頭行と後続の行で字下げが異なる段落を処理できる。

fill-individual-varying-indent User Option
この変数は、上に述べたように fill-individual-paragraphsの動作を変える。

fill-region-as-paragraph start end &optional justify nosqueeze squeeze-after コマンド
このコマンドは、テキストの領域を1つの段落とみなして詰め込む。 領域に複数の段落があると、段落のあいだの空行は取りさる。 justifynil以外であると幅揃えも行う。

対話的な呼び出しでは、前置引数で幅揃えを指示する。

nosqueezenil以外であると、 行分け以外の白文字にはふれないことを意味する。 squeeze-afternil以外であると、 それは領域内の位置を表し、 その位置よりまえにある空白を変更しないように指示する。

適応型詰め込み(adaptive-fill)モードでは、 デフォルトの詰め込み接頭辞を選ぶために このコマンドはfill-context-prefixを呼び出す。 see Adaptive Fill

justify-current-line how eop nosqueeze コマンド
このコマンドは、現在行の単語のあいだに空白を挿入し、 ちょうどfill-columnコラムで行が終るようにする。 nilを返す。

引数hownil以外であると、 幅揃えスタイルを指定する。 可能な値は、leftrightfullcenter、または、noneである。 tであると、指定されている幅揃えスタイルに従うことを意味する (下記のcurrent-justificationを参照)。 nilは、幅揃えしないことを意味する。

eopnil以外であると、 current-justificationが両端揃えを指定しているときには 左端揃えを行うことを意味する。 これは段落の最後の行に適用される。 段落全体として両端揃えであっても、最後の行はそうすべきではない。

nosqueezenil以外であると、 内側の白文字を変更しないことを意味する。

default-justification User Option
この変数の値は、テキスト属性で幅揃えスタイルを指定していない テキストに対して用いる幅揃えスタイルを指定する。 可能な値は、leftrightfullcenternoneである。 デフォルト値はleftである。

current-justification Function
この関数は、ポイントの周りのテキストを詰め込むときに使う 正しい幅揃えスタイルを返す。

sentence-end-double-space User Option
この変数がnil以外であると、 直後に1つの空白を従えたピリオドを文末とみなさず、 詰め込み関数はそのような箇所で行分けしない。

fill-paragraph-function Variable
この変数は、段落の詰め込みに優先する方法をメジャーモードに与える。 値がnil以外であると、 fill-paragraphは詰め込み処理のためにこの関数を呼び出す。 関数がnil以外の値を返すと、 fill-paragraphは処理が完了したとみなして戻り値をただちに返す。

この機能の普通の用途は、 プログラム言語向けのモードでコメントを詰め込むためである。 この関数で普通の方法で詰め込む必要がある場合には、つぎのようにする。

(let ((fill-paragraph-function nil))
  (fill-paragraph arg))

use-hard-newlines Variable
この変数がnil以外であると、 詰め込み関数は、テキスト属性hardを持つ改行を削除しない。 これらの『ハード改行』は段落の区切りとして働く。


Node:Margins, Next:, Previous:Filling, Up:Text

詰め込みのための余白

fill-prefix User Option
このバッファローカルな変数は、普通のテキスト行の先頭に現れ、 詰め込み時には無視すべきテキストの文字列(詰め込み接頭辞)を指定する。 詰め込み接頭辞で始まらない行は段落の開始行とみなすため、 詰め込み接頭辞のあとに余分に白文字があるとそれらも段落の開始行とみなす。 詰め込み接頭辞で始まりそのあとに余分な白文字がない行は、 いっしょに詰め込める普通のテキスト行である。

左端余白がある場合には、左端余白のあとに詰め込み接頭辞が続く。

fill-column User Option
このバッファローカルな変数は、詰め込んだ行の最大幅を指定する。 この値は整数であり、コラム数であること。 自動詰め込み(auto-fill)モード(see Auto Filling)を含めて すべての詰め込み/幅揃え/中央揃えを行うコマンドは、 この変数に影響される。

特に他人のために書いているテキストでは、 fill-columnを70未満にするべきである。 さもないと、人によっては快適に読むには行が長すぎて、 テキストが不恰好に見える。

default-fill-column Variable
この変数の値は、バッファでfill-columnの値を設定していない場合の fill-columnのデフォルト値である。 これは(default-value 'fill-column)と同じである。

default-fill-columnのデフォルト値は70である。

set-left-margin from to margin コマンド
fromからtoまでのテキストの 属性left-marginを値marginにする。 自動詰め込み(auto-fill)モードがオンであると、 このコマンドは、当該領域を再詰め込みして新たな余白に適合するようにする。

set-right-margin from to margin コマンド
fromからtoまでのテキストの 属性right-marginを値marginにする。 自動詰め込み(auto-fill)モードがオンであると、 このコマンドは、当該領域を再詰め込みして新たな余白に適合するようにする。

current-left-margin Function
この関数は、ポイントの周りのテキストを詰め込むときに使う 正しい左端余白の値を返す。 その値は、現在行の最初の文字の属性left-marginの値(なければ0) と変数left-marginの値の和である。

current-fill-column Function
この関数は、ポイントの周りのテキストを詰め込むときに使う 正しい詰め込み幅を返す。 その値は、変数fill-columnの値から ポイント直後の文字の属性right-marginの値を引いたものである。

move-to-left-margin &optional n force コマンド
この関数は、ポイントを現在行の左端余白へ移動する。 移動先のコラム位置は関数current-left-marginを呼び出して決定する。 引数nnil以外であると、 move-to-left-marginn-1先の行へまず移動する。

forcenil以外であると、 行の字下げが左端余白の値に一致しないときには、 字下げを修正することを指示する。

delete-to-left-margin from to Function
この関数は、fromからtoまでのテキストから 左端余白分の字下げを取りさる。 削除する字下げ量は、current-left-marginを呼び出して決定する。 この関数が白文字以外を削除することは絶対にない。

indent-to-left-margin Function
これは、基本(fundamental)モード、テキスト(text)モードなどが使う デフォルトのindent-line-functionである。 その効果は、変数left-marginの値で指定した位置から 現在行が始まるように字下げを調整することである。 それには白文字の挿入や削除が伴う。

left-margin Variable
この変数は、左端余白コラムの起点を指定する。 基本(fundamental)モードでは、C-jがこのコラム位置に字下げする。 この変数に設定すると自動的にバッファローカルになる。

fill-nobreak-predicate Variable
この変数は、特定の箇所では行分けしない方法をメジャーモードに提供する。 その値は関数であること。 この関数は、引数なしで行分け予定箇所にポイントを置いて呼び出される。 この関数がnil以外を返すと、当該箇所では行分けしない。


Node:Adaptive Fill, Next:, Previous:Margins, Up:Text

適応型詰め込み(adaptive-fill)モード

適応型詰め込みモード(adaptive-fill)では、 詰め込むべき各段落のテキストから自動的に詰め込み接頭辞を選びます。

adaptive-fill-mode User Option
この変数がnil以外であると、 適応型詰め込みモード(adaptive-fill)がオンである。 デフォルトではtである。

fill-context-prefix from to Function
この関数は適応型詰め込みモード(adaptive-fill)の中核を実装するものであり、 fromからtoのあいだのテキストに基づいて詰め込み接頭辞を選ぶ。 以下に述べる変数に基づいて、段落の最初の2行を調べてこれを行う。

adaptive-fill-regexp User Option
この変数は、適応型詰め込みモード(adaptive-fill)を制御する 正規表現を保持する。 適応型詰め込みモード(adaptive-fill)では、 行の(あれば)左端余白の白文字のうしろから始まるテキストに対して この正規表現の一致を試みる。 一致した文字群が当該行の詰め込み接頭辞の候補になる。

adaptive-fill-first-line-regexp User Option
1行だけの段落において、詰め込み接頭辞の候補がこの正規表現に一致するか、 comment-start-skipに一致すると、その候補を使う。 さもなければ、同じ幅に相当する白文字をかわりに使う。

1行だけの段落から選んだ詰め込み接頭辞が後続の行の段落の始まりである場合には、 1行だけの段落からはけっして詰め込み接頭辞を選ばない。

adaptive-fill-function User Option
この変数に関数を指定することで、 詰め込み接頭辞のより複雑な自動選択方法を指定できる。 この関数は、adaptive-fill-regexpの一致に失敗したときに、 行の左端余白のうしろにポイントを置いて呼び出され、 当該行に基づいて適切な詰め込み接頭辞を返すこと。 それがnilを返すと、当該行には詰め込み接頭辞がないことを意味する。


Node:Auto Filling, Next:, Previous:Adaptive Fill, Up:Text

自動詰め込み(auto-filling)モード

自動詰め込み(auto-filling)モードは、テキストを挿入するにつれて 自動的に行を詰め込むマイナモードです。 本節では、自動詰め込み(auto-filling)モードが使うフックについて述べます。 既存のテキストを詰め込んだり幅揃えするために 明示的に呼び出す関数については、Fillingを参照してください。

自動詰め込み(auto-filling)モードでは、 テキストの一部を再詰め込む際の 余白や幅揃えスタイルを変更するための関数も使えるようにします。 See Margins

auto-fill-function Variable
この変数の値は、 自己挿入される空白や改行のあとで呼び出されるべき (引数なしの)関数であること。 これがnilであると、そのような場合に特別なことを行わない。

自動詰め込み(auto-filling)モードがオンであると、 auto-fill-functionの値はdo-auto-fillである。 この関数の目的は、行分けの通常の方針を実装することである。

Emacsの古い版では、この変数をauto-fill-hookと命名していたが、 フックの標準的な慣習に従って呼ばれないため 19版でauto-fill-functionと改名した。

normal-auto-fill-function Variable
この変数は、自動詰め込み(auto-filling)モードがオンになったとき/であるときに auto-fill-functionとして用いる関数を指定する。 メジャーモードでは、この変数のバッファローカルな値に設定することで 自動詰め込み(auto-filling)モードのふるまいを変更できる。


Node:Sorting, Next:, Previous:Auto Filling, Up:Text

テキストのソート

本節で述べるソート関数すべては、バッファ内のテキストを並べ替えます。 これは、リスト内の要素の順番を並べ替える関数sort (see Rearrangement)と対照的です。 これらの関数が返す値には意味はありません。

sort-subr reverse nextrecfun endrecfun &optional startkeyfun endkeyfun Function
この関数は、バッファ内のテキストをレコードに分割してソートする 汎用のテキストソートルーティンである。 本節のコマンドのほとんどは、この関数を用いる。

sort-subrの動作方法を理解するためは、 バッファの参照可能部分全体が ソートレコード(sort record)と呼ばれる 重なり合いのない断片に分割されていると考える。 レコードは連続しているかもしれないし、そうでないかもしれないが、 けっして重なり合わない。 各ソートレコードの一部分(あるいは全体)をソートキーとして区別する。 ソートでは、ソートキーの順に並ぶようにレコードを並び替える。

通常、レコードをソートキーの昇順に並べ替える。 関数sort-subrの第1引数reversenil以外であると、 ソートキーの降順にレコードを並べ替える。

sort-subrのつぎの4つの引数は、 ソートレコードをまたいでポイントを移動するために呼ばれる関数である。 それらは、sort-subrで多数回呼び出される。

  1. nextrecfunは、レコードの末尾にポイントを置いて呼び出される。 この関数は、つぎのレコードの先頭にポイントを移動する。 最初のレコードの先頭は、 sort-subrを呼び出したときのポイント位置であると仮定する。 したがって、sort-subrを呼び出すまえには、普通、 バッファの先頭にポイントを移動しておくこと。

    この関数は、バッファの末尾にポイントを置いておくことで、 ソートレコードがなくなったことを表せる。

  2. endrecfunは、レコード内にポイントを置いて呼び出される。 レコードの末尾にポイントを移動する。
  3. startkeyfunは、レコードの先頭からソートキーの先頭へ ポイントを移動するために呼び出される。 この引数は省略可能であり、省略するとレコード全体をソートキーとする。 指定した場合、その関数は、ソートキーとして用いるnil以外の値を返すか、 バッファのポイント位置からソートキーが始まることを表すnilを返すこと。 後者の場合、ソートキーの末尾を探すためにendkeyfunが呼ばれる。
  4. endkeyfunは、ソートキーの先頭からソートキーの末尾に ポイントを移動するために呼び出される。 この引数は省略可能である。 startkeyfunnilを返しこの引数が省略されている (あるいはnilである)と、ソートキーはレコードの末尾までである。 startkeyfunnil以外の値を返すのであれば、 endkeyfunは必要ない。

sort-subrの例として、 sort-linesの完全な関数定義を示す。

;; 説明文字列の始めの2行は、ユーザーが見るときには
;; 実質的には1行であることに注意
(defun sort-lines (reverse beg end)
  "Sort lines in region alphabetically;\
 argument means descending order.
Called from a program, there are three arguments:
REVERSE (non-nil means reverse order),\
 BEG and END (region to sort).
The variable `sort-fold-case' determines\
 whether alphabetic case affects
the sort order.
  (interactive "P\nr")
  (save-excursion
    (save-restriction
      (narrow-to-region beg end)
      (goto-char (point-min))
      (sort-subr reverse 'forward-line 'end-of-line))))

ここで、forward-lineはつぎのレコードの先頭にポイントを移動し、 end-of-lineはレコードの末尾にポイントを移動する。 レコード全体をソートキーとして用いるため、 引数startkeyfunendkeyfunは指定しない。

関数sort-paragraphsもほぼ同様であるが、 つぎのようにsort-subrを呼び出す点が異なる。

(sort-subr reverse
           (function
             (lambda ()
               (while (and (not (eobp))
                      (looking-at paragraph-separate))
                 (forward-line 1))))
           'forward-paragraph)

sort-subrから戻ったあとでは、 ソートレコードを指しているマーカは意味のある位置を指していない。

sort-fold-case User Option
この変数がnil以外であると、 sort-subrや他のバッファソート関数は、 文字列の比較において大文字小文字を区別しない。

sort-regexp-fields reverse record-regexp key-regexp start end コマンド
このコマンドは、startendのあいだの領域を record-regexpkey-regexpの指定に従って アルファベット順にソートする。 reverseが負の整数であると、逆順にソートする。

アルファベット順のソートとは、 最初の文字同士、2番目の文字同士といった具合に 2つのソートキーを比較することである。 不一致がみつかると、ソートキーが等しくないことを意味し、 最初の不一致箇所の文字が小さいほうのソートキーが小さい。 個々の文字は、Emacsの文字集合における文字コードの数値に従って比較する。

引数record-regexpの値は、バッファをソートレコードに 分割する方法を指定する。 各レコードの末尾において、この正規表現を探索し それに一致したテキストをつぎのレコードとする。 たとえば、正規表現^.+$は、 少なくとも1つの文字のあとに改行があるような行に一致し、 そのような行をソートレコードとする。 正規表現の構文と意味については、see Regular Expressions

引数key-regexpの値は、 レコードのどの部分がソートキーであるかを指定する。 key-regexpは、レコード全体かその一部分に一致する。 後者の場合、レコードの残りの部分は、レコードの並び替え順序には影響しないが、 レコードをその新たな位置に移動するときにいっしょに移動される。

引数key-regexprecord-regexpの部分式に一致したテキストを参照してもよいし、 独立した正規表現でもよい。

key-regexpにはつぎの可能性がある。

\digit
record-regexpdigit番目の 括弧によるグループ化\(...\)に一致したテキストがソートキーである。
\&
レコード全体がソートキーである。
正規表現
sort-regexp-fieldsはレコード内でこの正規表現に一致するものを探す。 一致がみつかれば、それがソートキーになる。 レコード内でkey-regexpに対する一致がみつからなければ、 レコードを無視する。 つまり、バッファ内での当該レコードの位置を変更しない。 (別のレコードが周りに移動してくるかもしれない。)

たとえば、領域内のすべての行を各行のfで始まる最初の単語で ソートするには、record-regexp^.*$key-regexp\<f\w*\>を指定する。 つまり、つぎのような式になる。

(sort-regexp-fields nil "^.*$" "\\<f\\w*\\>"
                    (region-beginning)
                    (region-end))

sort-regexp-fieldsを対話的に呼び出すと、 ミニバッファでrecord-regexpkey-regexpを問い合わせる。

sort-lines reverse start end コマンド
このコマンドは、startendのあいだの領域の行を アルファベット順にソートする。 reversenil以外であると、逆順にソートする。

sort-paragraphs reverse start end コマンド
このコマンドは、startendのあいだの領域の段落を アルファベット順にソートする。 reversenil以外であると、逆順にソートする。

sort-pages reverse start end コマンド
このコマンドは、startendのあいだの領域のページを アルファベット順にソートする。 reversenil以外であると、逆順にソートする。

sort-fields field start end コマンド
このコマンドは、startendのあいだの領域の行を 各行のfield番目のフィールド同士をアルファベット順に比較してソートする。 フィールドは白文字で区切られ、1から数える。 fieldが負であると、 行末から-field番目のフィールドでソートする。 このコマンドは、表をソートするのに有用である。

sort-numeric-fields field start end コマンド
このコマンドは、startendのあいだの領域の行を 各行のfield番目のフィールド同士を数値として比較してソートする。 領域内の各行の指定したフィールドには数があること。 フィールドは白文字で区切られ、1から数える。 fieldが負であると、 行末から-field番目のフィールドでソートする。 このコマンドは、表をソートするのに有用である。

sort-columns reverse &optional beg end コマンド
このコマンドは、startendのあいだの領域の行を 特定範囲のコラムをアルファベット順に比較してソートする。 begendのコラム位置は、ソート対象のコラムの範囲を区切る。

reversenil以外であると、逆順にソートする。

このコマンドの普通でない点は、 位置begを含む行全体と位置endを含む行全体も ソート対象の領域に含まれることである。

sort-columnsは、ユーティリティプログラムsortを使うため、 タブ文字を含むテキストを正しく扱えない。 ソートするまえにM-x untabifyを使ってタブを空白に変換すること。


Node:Columns, Next:, Previous:Sorting, Up:Text

コラムを数える

コラム関数は、(バッファの先頭から文字を数えた)文字位置を (スクリーンの行頭から文字を数えた)コラム位置に変換します。

これらの関数は、各文字をそれがスクリーン上で占めるコラム数を基に数える。 つまり、ctl-arrowの値に依存してコントロール文字は、 2コラムか4コラム占めると数え、 タブ文字は、タブの開始コラムとtab-widthの値に依存する コラム数を占めると数えることを意味します。 See Usual Display

コラム番号の計算では、ウィンドウの幅や水平スクロール量を無視します。 その結果、コラム値は任意の大きさになりえます。 最初の(スクリーン左端の)コラムの番号は0です。

current-column Function
この関数は、左端を0としてコラム数で数えたポイントの水平位置を返す。 コラム位置は、現在行の先頭からポイント位置までの文字すべての 表示上の表記の幅の総和である。

current-columnの使用例については、 Text Linescount-linesを参照。

move-to-column column &optional force Function
この関数は、ポイントを現在行のcolumnへ移動する。 columnの計算では、現在行の先頭からポイント位置までの 文字すべての表示上の表記の幅を考慮する。

コラムcolumnが行末を越える場合、ポイントを行末へ移動する。 columnが負であると、ポイントを行頭へ移動する。

コラムcolumnがタブなどの複数コラムを占める文字の中ほどにあるために そこへ移動できない場合には、 ポイントを当該文字の末尾へ移動する。 しかし、forcenil以外であり columnがタブの中ほどであると、 コラムcolumnに正確に移動できるようにタブを空白に変換する。 複数コラムを占めるその他の文字では、それらを分割する方法がないため、 forceを指定しても変則的になる。

コラムcolumnに到達できるほど行が長くない場合にも 引数forceには効果がある。 そのような場合、指定コラムに達するように行末に白文字を追加する。

columnが整数でないと、エラーを通知する。

戻り値は、実際の移動先のコラム番号である。


Node:Indentation, Next:, Previous:Columns, Up:Text

字下げ

字下げ関数は、行頭の空白を調べたり、そこへ移動したり、 変更するために使います。 行の他の白文字を変更するものもあります。 コラム関数と字下げ関数は左端を0と数えます。


Node:Primitive Indent, Next:, Up:Indentation

字下げ基本関数

本節では、字下げを数えたり挿入するために使われる基本関数について述べます。 後続の節の関数群は、これらの基本関数を使っています。 関連する関数については、See Width

current-indentation Function
この関数は、現在行の字下げを返す。 これは最初の白文字以外の文字の水平位置である。 行全体が白文字や空である場合には、行末の水平位置を返す。

indent-to column &optional minimum コマンド
この関数は、ポイント位置からcolumnに達するまでタブや空白で字下げする。 minimumを指定しnil以外であると、 columnを越える場合であっても最低minimum個の空白を挿入する。 さもなければ、ポイントがcolumnを越えている場合には、 この関数はなにもしない。 戻り値は、挿入した字下げが終る箇所のコラムである。

挿入された白文字は周りの文字(普通は、まえの文字)からテキスト属性を継承する。 see Sticky Properties

indent-tabs-mode User Option
この変数がnil以外であると、 字下げ関数は空白に加えてタブも挿入する。 さもなければ、空白のみを挿入する。 この変数に設定すると、カレントバッファでバッファローカルになる。


Node:Mode-Specific Indent, Next:, Previous:Primitive Indent, Up:Indentation

メジャーモードの制御による字下げ

各メジャーモードの重要な機能は、 キー<TAB>を編集対象の言語に適した字下げにカスタマイズすることです。 本節では、キー<TAB>の機構とそれを制御する方法について述べます。 本節の関数は、予測できない値を返します。

indent-line-function Variable
この変数の値は、現在行を字下げするために <TAB>(やさまざまなコマンド)が使う関数である。 コマンドindent-according-to-modeは、 この関数を呼ぶこと以上のことはしない。

lispモードでは値はシンボルlisp-indent-line、 Cモードではc-indent-line、 fortranモードではfortran-indent-lineである。 標準的な字下げがない基本(fundamental)モード、 テキスト(text)モード、他の多くのモードでは、 値はindent-to-left-margin(デフォルト値)である

indent-according-to-mode コマンド
このコマンドは、現在のメジャーモードに適した方法で現在行を字下げするために indent-line-functionで指定される関数を呼び出す。

indent-for-tab-command コマンド
このコマンドは、現在行を字下げするために indent-line-functionで指定される関数を呼び出すが、 その関数がindent-to-left-marginであると、 かわりにinsert-tabを呼び出す。 (これはタブ文字を挿入する単純なコマンドである。)

newline-and-indent コマンド
この関数は、改行を挿入してから、 (改行を挿入したばかりの行に続く)新たな行を メジャーモードに基づいて字下げする。

現在のindent-line-functionを呼び出して字下げを行う。 プログラム言語向けのモードでは、これは<TAB>が行うことと同じであるが、 <TAB>がタブを挿入するテキスト向けのモードの一部では、 newline-and-indentleft-marginで指定されたコラムに字下げする。

reindent-then-newline-and-indent コマンド
このコマンドは、現在行を字下げし直し、ポイント位置に改行を挿入し、 (改行を挿入したばかりの行に続く)新たな行を字下げする。

このコマンドは、indent-line-functionの現在の値を呼び出すことで、 どちらの行も現在のメジャーモードに基づいて字下げする。 プログラム言語向けのモードでは、これは<TAB>が行うことと同じであるが、 <TAB>がタブを挿入するテキスト向けのモードの一部では、 reindent-then-newline-and-indentは、 left-marginで指定されるコラムに字下げする。


Node:Region Indent, Next:, Previous:Mode-Specific Indent, Up:Indentation

領域全体の字下げ

本節では、領域内のすべての行を字下げするコマンドについて述べます。 これらは予測できない値を返します。

indent-region start end to-column コマンド
このコマンドは、start(を含めて)と end(を含めない)のあいだで始まる空でない各行を字下げする。 to-columnnilであると、 indent-regionは、現在のモードの字下げ関数、 つまり、indent-line-functionの値を呼び出して、 空でない各行を字下げする。

to-columnnil以外であると、 それは字下げ先のコラム番号を指定する整数であること。 すると、この関数は、白文字を追加するか削除して、 各行を指定どおりに字下げする。

詰め込み接頭辞がある場合、 indent-regionは詰め込み接頭辞で行を始めることで各行を字下げする。

indent-region-function Variable
この変数の値は、indent-regionの短縮版として利用可能な関数である。 領域の開始位置と終了位置の2つの引数をとる。 領域の行を1つ1つ字下げする場合と同じ結果を生じるが、 より速く動作することを意図してこの関数を設計するべきである。

値がnilであると短縮版はなく、 indent-regionが実際に1行ずつ処理する。

短縮版関数はCモードやlispモードのようなモードで有用である。 そのようなモードでは、indent-line-functionで関数定義の始まりを 走査する必要があり、これを各行に適用すると自乗の時間がかかる。 短縮版では、字下げし終えた関数定義を通過するたびに 走査情報を更新でき、これには線形時間かかるだけである。 個々の行を高速に字下げできるモードでは、短縮版は必要ない。

引数to-columnnil以外を指定したindent-regionには 別の意味があり、この変数を使わない。

indent-rigidly start end count コマンド
このコマンドは、start(を含めて)と end(を含めない)のあいだで始まる行すべてを コラム数countだけ字下げする。 これは、領域を1つの塊として動かしてその領域の『形を保つ』。 このコマンドは、字下げしていないテキストの領域だけでなく、 整形済みの領域を字下げするためにも有用である。

たとえば、countが3であると、 このコマンドは指定した領域内の各行の行頭に3コラムの字下げを追加する。

メイル(mail)モードでは、C-c C-ymail-yank-original)が 返信対象のメッセージからコピーしたテキストを字下げするために indent-rigidlyを使っている。

indent-code-rigidly start end columns &optional nochange-regexp Function
この関数はindent-rigidlyと同様であるが、 文字列やコメントで始まる行を変更しない点が異なる。

さらに、(nochange-regexpnil以外のとき) 行の先頭がnochange-regexpに一致する場合にも行を変更しない。


Node:Relative Indent, Next:, Previous:Region Indent, Up:Indentation

先行行相対の字下げ

本節では、先行する行の内容に基づいて現在行を字下げする2つの コマンドについて述べます。

indent-relative &optional unindented-ok コマンド
このコマンドは、空白でないまえの行のつぎの字下げ位置のコラムに 達するまで、ポイント位置に白文字を挿入する。 字下げ位置とは、白文字に続く白文字以外の文字である。 つぎの字下げ位置とは、現在行のポイントのコラム位置より大きな 最初の字下げ位置のことである。 たとえば、テキスト行の白文字以外の最初の文字より左側で、 その下の行にポイントがあると、 白文字を挿入してそのコラム位置にポイントを移動する。

空白でないまえの行に、つぎの字下げ位置(つまり、ポイント位置より 大きなコラム)がないと、indent-relativeは、 (unindented-oknil以外であれば)なにもしないか、 tab-to-tab-stopを呼び出す。 したがって、まえのテキスト行が短くてその行末より右側で、 その下の行にポイントがあると、このコマンドは、通常どおり、 白文字を挿入してつぎのタブ位置へポイントを移動する。

indent-relativeの戻り値は予測できない。

つぎの例では、ポイントは2行目の行頭にある。

            This line is indented twelve spaces.
-!-The quick brown fox jumped.

(indent-relative nil)を評価すると、つぎのようになる。

            This line is indented twelve spaces.
            -!-The quick brown fox jumped.

つぎの例では、ポイントはjumpedmpのあいだにある。

            This line is indented twelve spaces.
The quick brown fox jum-!-ped.

(indent-relative nil)を評価すると、つぎのようになる。

            This line is indented twelve spaces.
The quick brown fox jum  -!-ped.

indent-relative-maybe コマンド
このコマンドは、引数unindented-oktを指定して indent-relativeを呼び出すことで、 まえの行と同様に字下げする。 戻り値は予測できない。

空行でないまえの行に現在のコラム位置を越える字下げ位置がなければ、 このコマンドはなにもしない。


Node:Indent Tabs, Next:, Previous:Relative Indent, Up:Indentation

調整可能な『タブストップ』

本節では、ユーザー指定の『タブストップ』の機構と、 それを使ったり設定するための機構について説明します。 『タブストップ』という名前を使うのは、 この機構がタイプライタのタブストップに似た機能だからです。 この機能は、適切な個数の空白とタブ文字を挿入して つぎのタブストップのコラムへ到達しますが、 バッファ内のタブ文字の表示に影響することはありません (see Usual Display)。 テキスト(text)モードなどの少数のメジャーモードでのみ、 入力としての文字<TAB>がこのタブストップ機能を使います。

tab-to-tab-stop コマンド
このコマンドは、tab-stop-listで定義されたつぎのタブストップコラムまで、 ポイントのまえに空白やタブを挿入する。 このリストで現在のコラム番号より大きな要素を探し、 その要素を字下げ位置のコラムとして使う。 そのような要素がなければ、このコマンドはないもしない。

tab-stop-list User Option
この変数は、tab-to-tab-stopsが使うタブストップコラムのリストである。 それらの要素は、昇順の整数であること。 タブストップコラムの間隔は、等間隔である必要はない。

タブストップを対話的に編集するにはM-x edit-tab-stopsを使う。


Node:Motion by Indent, Previous:Indent Tabs, Up:Indentation

字下げに基づく移動コマンド

これらのコマンドは、主に対話的に使うもので、 テキストの字下げに基づいて動作します。

back-to-indentation コマンド
このコマンドは、現在行(ポイントが位置する行)の 白文字でない最初の文字へポイントを移動する。 nilを返す。

backward-to-indentation arg コマンド
このコマンドは、arg行だけポイントを後方へ移動してから、 当該行の白文字でない最初の文字へポイントを移動する。 nilを返す。

forward-to-indentation arg コマンド
このコマンドは、arg行だけポイントを前方へ移動してから、 当該行の白文字でない最初の文字へポイントを移動する。 nilを返す。


Node:Case Changes, Next:, Previous:Indentation, Up:Text

大文字小文字の変更

ここに述べる大文字小文字の変更コマンドは、 カレントバッファのテキストに作用します。 文字列や文字の大文字小文字を変換する関数については、 See Case Conversion。 どの文字が大文字でどの文字が小文字であり、それらをどのように変換するかを カスタマイズする方法については、See Case Tables

capitalize-region start end コマンド
この関数は、startendで定義される領域内の すべての単語をキャピタライズ(大文字で始まるように)する。 つまり、各単語の最初の文字を大文字に、残りの文字を小文字に変換する。 この関数はnilを返す。

領域の端が単語の途中にあると、 その単語の領域内の部分を1つの単語とみなす。

capitalize-regionを対話的に呼び出すと、 startendはポイントとマークであり、小さいほうがさきにくる。

---------- Buffer: foo ----------
This is the contents of the 5th foo.
---------- Buffer: foo ----------

(capitalize-region 1 44)
=> nil

---------- Buffer: foo ----------
This Is The Contents Of The 5th Foo.
---------- Buffer: foo ----------

downcase-region start end コマンド
この関数は、startendで定義される領域内の すべての文字を小文字に変換する。 この関数はnilを返す。

downcase-regionを対話的に呼び出すと、 startendはポイントとマークであり、小さいほうが先にくる。

upcase-region start end コマンド
この関数は、startendで定義される領域内の すべての文字を大文字に変換する。 この関数はnilを返す。

upcase-regionを対話的に呼び出すと、 startendはポイントとマークであり、小さいほうが先にくる。

capitalize-word count コマンド
この関数は、ポイントのうしろのcount個の単語を キャピタライズ(大文字で始まるように)し、ポイントをそれらの末尾に移動する。 つまり、各単語の最初の文字を大文字に、残りの文字を小文字に変換する。 countが負であると、まえの-count個の単語を 大文字で始まるようにするが、ポイントは移動しない。 値はnilである。

ポイントが単語の途中にあると、単語を前方へ移動するときには ポイントよりまえにある単語の部分を無視する。 単語の残りの部分を1つの単語として扱う。

capitalize-wordを対話的に呼び出すと、 countは数値前置引数である。

downcase-word count コマンド
この関数は、ポイントのうしろのcount個の単語を すべて小文字に替え、ポイントをそれらの末尾に移動する。 countが負であると、まえの-count個の単語を 変換するが、ポイントは移動しない。 値はnilである。

downcase-wordを対話的に呼び出すと、 countは数値前置引数である。

upcase-word count コマンド
この関数は、ポイントのうしろのcount個の単語を すべて大文字に替え、ポイントをそれらの末尾に移動する。 countが負であると、まえの-count個の単語を 変換するが、ポイントは移動しない。 値はnilである。

upcase-wordを対話的に呼び出すと、 countは数値前置引数である。


Node:Text Properties, Next:, Previous:Case Changes, Up:Text

テキスト属性

シンボルの属性リスト(see Property Lists)のように、 バッファや文字列の各文字にはテキスト属性リスト (text property list)を持てます。 この属性は、(本節の原文のタイトルの)文字Tfooの最初のoのような特定の箇所の特定の文字に属します。 同じ文字が異なる箇所に現れるとき、 一般にはそれぞれに異なる属性を持てます。

各属性には、名前と値があります。 どちらも任意のLispオブジェクトでかまいませんが、 名前は普通はシンボルです。 属性リストを参照する普通の方法では、 名前を指定してそれに対応する値を問い合わせます。

文字に属性categoryがあるとき、 それを文字のカテゴリ(category)といいます。 それはシンボルであるべきです。 そのシンボルの属性が、文字の属性のデフォルトとして働きます。

文字列とバッファのあいだでテキストをコピーすると、 文字とともにその属性も保たれます。 substringinsertbuffer-substringなどの さまざまな関数がそうします。


Node:Examining Properties, Next:, Up:Text Properties

テキスト属性を調べる

テキスト属性を調べるもっとも簡単な方法は、 特定の文字の特定の属性の値を問い合わせることです。 それには、get-text-propertyを使います。 文字の属性リスト全体を取得するにはtext-properties-atを使います。 複数の文字の属性を一度に調べるための関数については、 See Property Search

これらの関数は、文字列とバッファの両方を扱えます。 文字列内の位置は0から始まり、 バッファ内の位置は1から始まることに注意してください。

get-text-property pos prop &optional object Function
この関数は、object(バッファか文字列)内の位置posの うしろの1文字の属性propの値を返す。 引数objectは省略でき、 デフォルトはカレントバッファである。

その文字に属性propがなくてもシンボルであるカテゴリがあれば、 get-text-propertyは当該シンボルの属性propを返す。

get-char-property pos prop &optional object Function
この関数はget-text-propertyに似ているが、 まずオーバレイを調べてからテキスト属性を調べる。 see Overlays

引数objectは、文字列、バッファ、ウィンドウのいずれかである。 ウィンドウであると、そのウィンドウに表示しているバッファの テキスト属性とオーバレイを対象にするが、 対象となるオーバレイはそのウィンドウに対して活性なものだけである。 objectがバッファであると、テキスト属性に加えて そのバッファのすべてのオーバレイを対象にする。 objectが文字列であると、 文字列にはオーバレイはないので、テキスト属性のみを対象にする。

text-properties-at position &optional object Function
この関数は、文字列やバッファであるobject内の 位置positionにある1文字の属性リスト全体を返す。 objectnilであると、デフォルトはカレントバッファである。

default-text-properties Variable
この変数は、テキスト属性のデフォルト値を与える属性リストを保持する。 直接的にもカテゴリシンボルを介して間接的にも 文字に属性の値が指定されていないと、 このリストに収めた値をかわりに使う。 つぎに例を示す。
(setq default-text-properties '(foo 69))
;; 位置1の文字に属性がないことを保証する
(set-text-properties 1 2 nil)
;; 問い合わせたときに見えるのはデフォルト値である
(get-text-property 1 'foo)
     => 69


Node:Changing Properties, Next:, Previous:Examining Properties, Up:Text Properties

テキスト属性の変更

属性を変更する基本関数は、バッファや文字列の指定した範囲に作用します。 関数set-text-properties(本節の最後)は、 その範囲のテキストの属性リスト全体を設定します。 これは、名前で指定した特定の属性のみを追加/変更/削除するのに しばしば有用です。

テキスト属性はバッファ(や文字列)の一部分であるとみなされ、 スクリーン上でのバッファの見た目に影響するので、 バッファのテキスト属性を変更すると、 バッファには変更済みの印を付けます。 バッファのテキスト属性の変更もアンドゥ(see Undo)できます。

put-text-property start end prop value &optional object Function
この関数は、文字列やバッファであるobject内の startendのあいだのテキストの属性propの値を valueとする。 objectnilであると、デフォルトはカレントバッファである。

add-text-properties start end props &optional object Function
この関数は、文字列やバッファであるobject内の startendのあいだのテキストの テキスト属性に追加/上書きする。 objectnilであると、デフォルトはカレントバッファである。

引数propsで追加する属性を指定する。 これは属性リスト(see Property Lists)の形であること。 つまり、属性名とその値を交互に並べたリストであること。

この関数が属性の値をどれか実際に変更したならば、戻り値はtである。 さもなければ(propsnilだったり、 テキスト内の値と同じ値であると)nilである。

たとえば、テキストのある範囲の属性commentfaceを 設定するにはつぎのようにする。

(add-text-properties start end
                     '(comment t face highlight))

remove-text-properties start end props &optional object Function
この関数は、文字列やバッファであるobject内の startendのあいだのテキストから 指定したテキスト属性を削除する。 objectnilであると、デフォルトはカレントバッファである。

引数propsで削除する属性を指定する。 これは属性リスト(see Property Lists)の形であること。 つまり、属性名とその値を交互に並べたリストであること。 ただし、意味があるのは名前のみであり、その値は無視する。 たとえば、属性faceを削除するにはつぎのようにする。

(remove-text-properties start end '(face nil))

この関数が属性の値をどれか実際に変更したならば、戻り値はtである。 さもなければ(propsnilだったり、 指定したテキスト内の文字にそれらのいずれの属性もなければ) nilである。

特定のテキストからすべてのテキスト属性を削除するには、 新たな属性リストとしてnilを指定して set-text-propertiesを使う。

set-text-properties start end props &optional object Function
この関数は、文字列やバッファであるobject内の startendのあいだのテキストのテキスト属性を完全に置き換える。 objectnilであると、 デフォルトはカレントバッファである。

引数propsは新たな属性リストである。 これは、属性名とその値を交互に並べたリストであること。

set-text-propertiesから戻ると、 指定した範囲のすべての文字は同一の属性を持つことになる。

propsnilであると、 テキストの指定した範囲からすべての属性を削除する効果がある。 たとえば、つぎのようにする。

(set-text-properties start end nil)

バッファからテキストをコピーするがその属性はコピーしない 関数buffer-substring-no-properties(see Buffer Contents)も 参照してください。


Node:Property Search, Next:, Previous:Changing Properties, Up:Text Properties

テキスト属性を探す関数

テキスト属性の典型的な用途では、 ほとんどの場合多くの連続した文字の1つの属性には同じ値があります。 1つずつ文字を調べるようにプログラムするよりは、 同じ属性値を持つテキストの塊を処理するほうがとても速いです。

このために使える関数をここで説明します。 これらは属性値の比較にeqを使います。 objectのデフォルトは、すべての場合でカレントバッファです。

高い効率のためには、これらの関数に引数limitを使うことが重要であり、 1つの属性を探す関数には特にあてはまります。 さもないと、読者が望む属性が変更されないような場合、 それらの関数はバッファの末尾まで走査して長い時間を費すことになります。

これらの関数はポイントを移動しませんが、そのかわりに 位置(あるいはnil)を返します。 位置はつねに2つの文字のあいだにあることに注意してください。 これらの関数が返す位置は、異なる属性を持つ2つの文字のあいだです。

next-property-change pos &optional object limit Function
この関数は、文字列やバッファであるobject内の位置posから テキスト属性のいずれかが異なるまでテキストを走査し、その変化する位置を返す。 いいかえれば、posの直後の文字のテキスト属性とは異なる 属性を持つposのあとにある最初の文字の位置を返す。

limitnil以外であると、limitの位置で走査を終える。 その箇所まで異なる属性がないと、 next-property-changelimitを返す。

limitnilでありobjectの末尾まで属性に変化がないと、 値はnilである。 値がnil以外であると、それはposより大きいか等しい位置である。 値がposに等しいのは、limitposに等しい場合のみである。

バッファからすべての属性が同じであるテキストの塊を 走査する方法の例をつぎに示す。

(while (not (eobp))
  (let ((plist (text-properties-at (point)))
        (next-change
         (or (next-property-change (point) (current-buffer))
             (point-max))))
    ポイントからnext-changeまでのテキストを処理する...
    (goto-char next-change)))

next-single-property-change pos prop &optional object limit Function
この関数は、文字列やバッファであるobject内の位置posから 属性propが異なるまでテキストを走査し、その変化する位置を返す。 いいかえれば、posの直後の文字の属性propとは異なる 属性propをもつposのあとにある最初の文字の位置を返す。

limitnil以外であると、limitの位置で走査を終える。 その箇所まで異なる属性がないと、 next-single-property-changelimitを返す。

limitnilでありobjectの末尾まで属性に変化がないと、 値はnilである。 値がnil以外であると、それはposより大きいか等しい位置である。 値がposに等しいのは、limitposに等しい場合のみである。

previous-property-change pos &optional object limit Function
これはnext-property-changeと同様であるが、 前方へではなくposから後方へ走査する。 値がnil以外であると、それはposより小さいか等しい位置である。 値がposに等しいのは、limitposに等しい場合のみである。

previous-single-property-change pos prop &optional object limit Function
これはnext-single-property-changeと同様であるが、 前方へではなくposから後方へ走査する。 値がnil以外であると、それはposより小さいか等しい位置である。 値がposに等しいのは、limitposに等しい場合のみである。

next-char-property-change position &optional limit Function
これはnext-property-changeと同様であるが、 テキスト属性に加えてオーバレイも対象にする。 この関数はカレントバッファにのみ作用するため、 objectを表す引数はない。 どちらかの属性が異なるつぎの位置を返す。

previous-char-property-change position &optional limit Function
これはnext-char-property-changeと同様であるが、 前方へではなくposから後方へ走査する。

text-property-any start end prop value &optional object Function
startendのあいだに属性propの値がvalueである 文字が1つでもあれば、この関数はnil以外を返す。 より正確には、そのような最初の文字の位置を返す。 さもなければnilを返す。

省略可能な5番目の引数objectは、走査すべき文字列やバッファを指定する。 位置はobjectに相対である。 objectのデフォルトはカレントバッファである。

text-property-not-all start end prop value &optional object Function
startendのあいだに属性propの値がvalueでない 文字が1つでもあれば、この関数はnil以外を返す。 より正確には、そのような最初の文字の位置を返す。 さもなければnilを返す。

省略可能な5番目の引数objectは、走査すべき文字列やバッファを指定する。 位置はobjectに相対である。 objectのデフォルトはカレントバッファである。


Node:Special Properties, Next:, Previous:Property Search, Up:Text Properties

特別な意味を持つ属性

特別な組み込みの意味を持つテキスト属性名の一覧を以下に示します。 以降の節では、詰め込みや属性の継承を制御する特別な属性名も示します。 それ以外の名前には標準的な意味はないので、 読者はそれらを好きなように使ってかまいません。

category
文字に属性categoryがあるとき、 これを文字のカテゴリ(category)と呼ぶ。 これはシンボルであること。 そのシンボルの属性が、文字の属性のデフォルトとして働く。
face
テキストのフォントと表示色を制御するために属性faceを使う。 その値はフェイス名かフェイス名のリストである。 詳しくは、see Faces

属性値がリストであると、その要素は、 (foreground-color . color-name)(background-color . color-name)の形でもよい。 これらの要素は、前景色だけや背景色だけを指定する。 したがって、使用する各色を表すフェイスを作成する必要はない。

テキストの内容に基づいて属性faceを自動的に更新する方法に関しては、 see Font Lock Mode

mouse-face
マウスが文字の上やその近くにあると、属性faceのかわりに 属性mouse-faceが使われる。 この目的において『近く』とは、 文字とマウスの位置のあいだの 属性mouse-faceの値が同じであるすべてのテキストである。
local-map
属性local-mapを用いることで、 バッファ内のテキストの一部分に対して別のキーマップを指定できる。 ポイントのうしろの文字のこの属性の値がnil以外であると、 バッファのローカルマップのかわりにその値をキー探索に使う。 属性値がシンボルであると、シンボルの関数定義をキーマップとして使う。 see Active Keymaps
syntax-table
属性syntax-tableは、構文テーブルがこの文字に指定するものに優先する。 see Syntax Properties
read-only
文字に属性read-onlyがあると、その文字を変更できない。 変更するどのようなコマンドもエラーになる。

挿入されるテキストがスティッキ性のために属性read-onlyを 継承する場合には、読み出し専用文字のつぎにテキストを挿入するとエラーになる。 したがって、スティッキ性を制御することで、 読み出し専用テキストのつぎへのテキスト挿入を許すかどうかを制御できる。 see Sticky Properties

属性を変更するとバッファを変更したとみなすため、 特別なトリックを知らない限り、属性をread-onlyを削除できない。 つまり、inhibit-read-onlynil以外の値を束縛して、 属性を削除する。 see Read Only Buffers

invisible
属性invisiblenil以外であると、 その文字はスクリーンに表示されない。 詳しくは、see Invisible Text
intangible
連続する文字に属性intangiblenilでない同じ値があると、 それらのあいだにポイントを置けなくなる。 前方に向けてこれらの文字の中にポイントを移動しようとすると、 ポイントは実際にはそれらの末尾へ移動する。 後方に向けてこれらの文字の中にポイントを移動しようとすると、 ポイントは実際にはそれらの先頭へ移動する。

変数inhibit-point-motion-hooksnil以外であると、 属性intangibleは無視される。

modification-hooks
文字に属性modification-hooksがある場合、それは関数のリストであること。 その文字の変更にはそれらの関数すべてが呼び出される。 各関数は2つの引数、つまり、バッファの変更対象部分の先頭と末尾を受け取る。 1つの操作で変更される一連の文字に同じ変更フック関数が現れる場合、 関数が実際に何回呼ばれるか予測できないことに注意してほしい。
insert-in-front-hooks
insert-behind-hooks
バッファにテキストを挿入する操作でも、 挿入箇所のうしろの文字の属性insert-in-front-hooksと まえの文字の属性insert-behind-hooksに指定されている 関数群を呼び出す。 これらの関数は2つの引数、つまり、挿入されたテキストの先頭と末尾を受け取る。 これらの関数が呼ばれるのは、実際の挿入操作を終えてからである。

バッファ内のテキストを変更するときに呼び出される他のフックについては、 Change Hooksも参照。

point-entered
point-left
特別な属性point-enteredpoint-leftは、 ポイント移動を報告するフック関数を保持する。 ポイントが動くたびに、Emacsはこれらの2つの属性値、つまり、

を比較する。 これら2つの値が異なれば、 ポイントの古い値と新しい値の2つの引数で(nilでなければ) それぞれを呼び出す。

同じことを移動前後のポイントのまえの文字についても行う。 その結果、(同じかもしれない)point-leftの関数を2回、かつ/あるいは、 (同じかもしれない)point-enteredの関数を2回実行する。 いずれにしても、point-leftの関数が最初に呼ばれ、 そのあとでpoint-enteredの関数が呼ばれる。

これらの関数では、char-afterを使って ポイントを移動せずにさまざまな箇所の文字を調べられる。 ポイントの値が実際に変わったときにのみ、これらのフック関数が実行される。

inhibit-point-motion-hooks Variable
この変数がnil以外であると、 point-leftpoint-enteredのフック関数は実行されなくなり、 属性intangibleの効果もなくなる。 この変数はグローバルに設定せずに、letで束縛すること。


Node:Format Properties, Next:, Previous:Special Properties, Up:Text Properties

整形済みテキストの属性

これらのテキスト属性は、詰め込みコマンドのふるまいに影響します。 これらは整形済みのテキストを表現するために使われます。 FillingとSee Margins

hard
改行文字にこの属性があると、『ハード』改行である。 詰め込みコマンドは『ハード』改行を変更せず、 それらをまたがって単語を移動しない。 しかし、この属性はuse-hard-newlinesnil以外の場合にのみ効果を持つ。
right-margin
テキストのこの部分を詰め込むための余分な右端余白を指定する。
left-margin
テキストのこの部分を詰め込むための余分な左端余白を指定する。
justification
テキストのこの部分を詰め込むための幅揃えスタイルを指定する。


Node:Sticky Properties, Next:, Previous:Format Properties, Up:Text Properties

テキスト属性のスティッキ性

自己挿入文字は、通常、先行する文字と同じ属性を持ちます。 これを属性の継承(inheritance)と呼びます。

Lispプログラムでは、挿入基本関数を選べば、 継承して挿入したり継承せずに挿入できます。 insertなどの普通のテキスト挿入関数は、 いかなる属性も継承しません。 これらは、挿入する文字列の属性をそのまま持ったテキストを挿入し、 それ以外の属性はありません。 キルリングなどのある文脈から別の文脈へテキストをコピーするプログラムには、 これは正しい動作です。 継承して挿入するには、本節で述べる特別な基本関数を使います。 自己挿入文字はこれらの基本関数を使っているので、属性を継承します。

継承して挿入するとき、どの属性を継承するかは、 2つの特別な属性front-stickyrear-nonstickyに依存します。

文字のうしろに挿入すると、その文字の後続スティッキ(rear-sticky) である属性を継承します。 文字のまえに挿入すると、その文字の先行スティッキ(front-sticky) である属性を継承します。 デフォルトでは、テキスト属性は先行スティッキではなく後続スティッキです。 したがって、デフォルトでは、まえの文字のすべての属性を継承して、 うしろの文字からはなにも継承しません。 特定の属性のスティッキ性を指定することで、異なるふるまいを指定できます。

文字の属性front-stickytであると、 その文字のすべての属性は先行スティッキです。 属性front-stickyがリストであると、 リストに現れる名前のその文字の属性は先行スティッキです。 たとえば、文字の属性front-stickyの値が(face read-only)であると、 この文字のまえに挿入するとこの文字の属性faceread-onlyを 継承しますが、それ以外には継承しません。

rear-nonstickyは反対の働きをします。 すべての属性はデフォルトでは後続スティッキですから、 属性rear-nonstickyはどの属性が 後続スティッキでないかを指定します。 文字の属性rear-nonstickytであると、 その文字には後続スティッキである属性はありません。 属性rear-nonstickyがリストであると、 リストに名前が現れない限り、 属性は後続スティッキです。

継承するようにテキストを挿入すると、 まえの文字からは後続スティッキであるすべての属性を継承し、 うしろの文字からは先行スティッキであるすべての属性を継承します。 両側の文字に異なるスティッキ性の同じ属性がある場合には、 まえの文字の属性が優先します。

属性を継承してテキストを挿入する関数はつぎのとおりです。

insert-and-inherit &rest strings Function
関数insertと同様に文字列stringsを挿入するが、 前後のテキストから任意のスティッキ性の属性を継承する。

insert-before-markers-and-inherit &rest strings Function
関数insert-before-markersと同様に文字列stringsを挿入するが、 前後のテキストから任意のスティッキ性の属性を継承する。

継承しない普通の挿入関数については、See Insertion


Node:Saving Properties, Next:, Previous:Sticky Properties, Up:Text Properties

テキスト属性をファイルへ保存する

つぎの2つのフックを使って、 テキスト属性を(テキストそのものとともに)ファイルに保存しておき、 ファイルを訪問したり挿入するときに同じテキスト属性を復元できます。

write-region-annotate-functions Variable
この変数の値は、ファイルへ書き込むテキストに対する注記の形で テキスト属性を符号化するためにwrite-regionが呼び出す関数の リストである。 see Writing to Files

リスト内の各関数は2つの引数、つまり、 書き込む領域の先頭と末尾で呼び出される。 これらの関数はバッファの内容を変更しないこと。 そのかわりに、バッファのテキストに加えてファイルに書き込むべき 注記を表すリストを返すべきである。

各関数は、(position . string)の形の要素から成る リストを返すべきである。 ここで、positionは書き込まれるテキスト内の相対位置を指定する整数、 stringはそこへ追加する注記である。

これらの関数が返す各リストは、positionの昇順になっている必要がある。 複数の関数があると、write-regionは リストを破壊的に併合して1つのソートしたリストにする。

write-regionがバッファからファイルにテキストを実際に書くときに、 指定された注記を対応する位置に混在させる。 バッファを変更せずにこれらすべてを行う。

after-insert-file-functions Variable
この変数は、insert-file-contentsがファイルの内容を挿入してから 呼び出す関数のリストを保持する。 これらの関数は挿入されたテキストで注記を走査し、 それらが表すテキスト属性にそれらを変換する。

各関数は1つの引数、つまり、挿入されたテキストの長さで呼ばれ、 ポイントは挿入されたテキストの先頭を表す。 関数は当該テキストで注記を走査して注記を削除し、 注記が指定するテキスト属性を作成する。 関数は、変更を反映した挿入されたテキストの更新された長さを返すこと。 関数が返した値がつぎの関数の引数になる。

これらの関数は、挿入されたテキストの先頭にポイントをつねに戻すこと。

after-insert-file-functionsの意図された用途は、 テキスト表現の注記を実際のテキスト属性に変換することである。 しかし、別の使い方も可能である。

これらのフックを使ってファイルにテキスト属性を保存したり復元する Lispプログラムを書いて、さまざまなデータ書式を試して よいものをみつけるようにお願いします。 最終的には、Emacsに取り込める良質で汎用の拡張を ユーザーが作り出すことを願っています。

テキスト属性の名前や値として任意のLispオブジェクトを 処理しないように忠告しておきます。 そのような汎用のプログラムは書くのが難しく動作が遅くなりがちです。 そのかわりに、適当に柔軟性があり符号化が難しくないデータ型の集合を選びます。

関連する機能については、See Format Conversion


Node:Lazy Properties, Next:, Previous:Saving Properties, Up:Text Properties

テキスト属性の遅延計算

バッファ内のすべてのテキストのテキスト属性を計算するかわりに、 必要になった時点でテキストの一部分のテキスト属性を計算するようにできます。

バッファからテキスト属性とともにテキストを取り出す基本関数は、 buffer-substringです。 属性を調べるまえに、この関数はアブノーマルフック buffer-access-fontify-functionsを実行します。

buffer-access-fontify-functions Variable
この変数は、テキスト属性を計算する関数のリストを保持する。 buffer-substringがバッファの一部分からテキストとテキスト属性を コピーするまえに、この関数はこのリスト内の関数すべてを呼び出す。 各関数は、バッファの参照される範囲を指定する2つの引数を受け取る。 (バッファはつねにカレントバッファである。)

関数buffer-substring-no-propertiesは テキスト属性を無視するので、これらの関数を呼び出しません。

バッファの同じ部分に対してフック関数が複数回呼び出されるのを防ぐには、 変数buffer-access-fontified-propertyを使います。

buffer-access-fontified-property Variable
この変数の値がnil以外であると、 それはテキスト属性の名前として使われるシンボルである。 そのテキスト属性に対するnil以外の値は、 『この文字の他のテキスト属性はすでに計算済みである』ことを意味する。

buffer-substringに指定された範囲のすべての文字において、 この属性に対してnil以外の値があると、 buffer-substringbuffer-access-fontify-functionsの関数を呼び出さない。 それらの文字にはすでに正しいテキスト属性があるとみなし、 それらにすでにある属性をコピーする。

この機能を使う普通の方法は、 buffer-access-fontify-functionsの関数が 他の属性ととともにこの属性をそれらが操作した文字に追加する。 そうすれば、同じテキストに対して何回も呼び出されるのを防ぐことができる。


Node:Clickable Text, Next:, Previous:Lazy Properties, Up:Text Properties

クリック可能なテキストを定義する

バッファ内にクリック可能なテキスト(clickable text)を設定するには 2つの方法があります。 これは典型的には2つの部分から成ります。 つまり、マウスが重なるとテキストを強調表示し、 テキストのその部分をクリックすると マウスボタンがなんらかの処理を行うようにします。

強調表示はテキスト属性mouse-faceで行います。 diredでの方法を例として示します。

(condition-case nil
    (if (dired-move-to-filename)
        (put-text-property (point)
                           (save-excursion
                             (dired-move-to-end-of-filename)
                             (point))
                           'mouse-face 'highlight))
  (error nil))

put-text-propertyの最初の2つの引数は、 テキストの先頭と末尾を指定します。

このテキストをクリックしたときにマウスになにかをさせるようにする 普通の方法は、メジャーモードのキーマップでmouse-2を定義することです。 クリック可能なテキストをクリックしたかどうかの検査は、 コマンド定義で行われます。 diredではつぎのようにしています。

(defun dired-mouse-find-file-other-window (event)
  "In dired, visit the file or directory name you click on."
  (interactive "e")
  (let (file)
    (save-excursion
      (set-buffer (window-buffer (posn-window (event-end event))))
      (save-excursion
        (goto-char (posn-point (event-end event)))
        (setq file (dired-get-filename))))
    (select-window (posn-window (event-end event)))
    (find-file-other-window (file-name-sans-versions file t))))

外側のsave-excursionは、カレントバッファが変わることを防ぎます。 内側のは、クリックしたバッファのポイントを恒久的に変更することを防ぎます。 この例では、diredは関数dired-get-filenameを用いて、 イベントの位置に基づいて訪問すべきファイルを決定します。

メジャーモードのマウスコマンドを定義するかわりに、 テキスト属性local-mapを使って、 クリック可能なテキストそのものにキーバインディングを定義することもできます。

(let ((map (make-sparse-keymap)))
  (define-key-binding map [mouse-2] 'operate-this-button)
  (put-text-property (point)
                     (save-excursion
                       (dired-move-to-end-of-filename)
                       (point))
                     'local-map map))

この方法では、テキストのさまざまなクリック可能な部分に 異なるコマンドを定義できます。 さらに、バッファの残りの部分に対しては、 メジャーモードの定義(やグローバルな定義)がそのまま有効です。


Node:Not Intervals, Previous:Clickable Text, Up:Text Properties

テキスト属性が範囲でない理由

バッファ内のテキストに属性を付加できるエディタのなかには、 ユーザーにテキスト内の『範囲』を指定させ、 その範囲に属性を付加するものがあります。 このようなエディタでは、ユーザーやプログラマが 個々の範囲の先頭と末尾を決定できます。 テキスト変更に伴うある種の矛盾するようなふるまいを避けるために、 熟考の結果Emacs Lispでは別の種類のインターフェイスを提供することにしました。

複数の範囲に細分することが意味を持つならば、 ある属性の1つの範囲があるだけのバッファと、 その同じテキストをその同じ属性の2つの範囲にしてあるバッファとを 区別できるはずです。

1つの範囲だけを持つバッファにおいて、そのテキストの一部をキルしたとします。 バッファに残っているテキストは1つの範囲であり、 キルリング(とアンドゥリスト)内のコピーは1つの別の範囲になります。 そしてキルされたテキストをヤンクして戻すと、 同じ属性を持つ2つの範囲ができます。 つまり、編集すると、1つの範囲と2つの範囲の区別を保存できなくなります。

テキストを挿入すると2つの範囲を融合することで この問題を『修正』したとします。 バッファにもともと1つの範囲しかなければ、うまくいきます。 しかし、同じ属性の範囲が連続して2つある場合に、 一方の範囲をキルしてからヤンクして戻したとします。 別の場面では救いになる同じ属性の範囲を融合する機能が、 ここではトラブルを引き起こします。 つまり、ヤンクすると1つの範囲になってしまいます。 ここでも、編集すると、1つの範囲と2つの範囲の区別を保存できなくなります。

2つの範囲の境界にテキストを挿入する場合でも、 満足できる解決方法がない問題を提起します。

しかし、『この文字の属性はなにか』といった形の問いに対して 一貫したふるまいをするような編集にするのは簡単です。 そのために、これらが唯一の意味ある問いかけであると判断したのです。 範囲の先頭と末尾を問うようなものは実装してありません。

実用上は、明示的な範囲の境界のかわりに、 テキスト属性を探索する関数を普通は使えます。 それらの関数は、可能な場合にはつねに範囲は融合されると仮定して 範囲の境界を探すと考えることができます。 See Property Search

Emacsには表示機能として明示的な範囲もあります。 Overlaysを参照してください。


Node:Substitution, Next:, Previous:Text Properties, Up:Text

文字コードの置換

つぎの関数は、指定した領域内の文字をそれらの文字コードに基づいて置き換えます。

subst-char-in-region start end old-char new-char &optional noundo Function
この関数は、カレントバッファのstartendで定義される領域の すべての文字old-charを文字new-charに置き換える。

noundonil以外であると、 subst-char-in-regionはアンドゥ用の変更を記録せず、 バッファに変更済みの印も付けない。 この機能は、選択表示(see Selective Display)の制御に使われている。

subst-char-in-regionはポイントを移動せず、 nilを返す。

---------- Buffer: foo ----------
This is the contents of the buffer before.
---------- Buffer: foo ----------

(subst-char-in-region 1 20 ?i ?X)
     => nil

---------- Buffer: foo ----------
ThXs Xs the contents of the buffer before.
---------- Buffer: foo ----------

translate-region start end table Function
この関数は、バッファのstartendのあいだの文字に変換表を適用する。

変換表tableは文字列であり、 (aref table ochar)は、 ocharに対応する変換した文字を与える。 tableの長さが256未満であると、 tableの長さより大きなコードの文字は変換によっては変更されない。

translate-regionの戻り値は、 変換によって実際に変更した文字の個数を返す。 これには、変換表で自分自身に変換された文字は数えない。


Node:Registers, Next:, Previous:Transposition, Up:Text

レジスタ

レジスタは、Emacsの編集においてさまざまな種類の値を保持できる変数の一種です。 各レジスタには1文字の名前が付いています。 すべてのASCII文字とそれらのメタ変種(ただしC-gを除く)を レジスタの名前に使えます。 したがって、255個のレジスタを使えます。 Emacs Lispでは、レジスタ名でレジスタを区別します。

register-alist Variable
この変数は、(name . contents)の形の要素の連想リストである。 通常、使用中のEmacsの各レジスタに対して1つの要素がある。

オブジェクトnameは、レジスタを識別する文字(整数)である。

レジスタの内容(contents)に可能な型はいくつかあります。

数そのものを表す。 insert-registerがレジスタ内で数をみつけると10進数に変換する。
マーカ
マーカはジャンプ先のバッファ内位置を表す。
文字列
文字列はレジスタに保存されたテキストである。
矩形領域
矩形領域は文字列のリストで表現される。
(window-configuration position)
これは、1つのフレームに復元するウィンドウ構成と カレントバッファでのポイントの移動先を表す。
(frame-configuration position)
これは、復元するフレーム構成とカレントバッファでのポイントの移動先を表す。
(file filename)
訪問すべきファイルを表す。 この値にジャンプするとファイルfilenameを訪問する。
(file-query filename position)
これは、訪問すべきファイルとその中での位置を表す。 この値にジャンプするとファイルfilenameを訪問し バッファ内位置positionへ移動する。 この種の位置を復元すると、まずユーザーに確認を取る。

本節の関数は、明記してない場合には予測できない値を返します。

get-register reg Function
この関数は、レジスタregの内容、 あるいは、内容がなければnilを返す。

set-register reg value Function
この関数は、レジスタregの内容をvalueとする。 レジスタには任意の値を設定できるが、他のレジスタ関数は 特定のデータ型を期待する。 戻り値はvalueである。

view-register reg コマンド
このコマンドは、レジスタregになにが入っているかを表示する。

insert-register reg &optional beforep コマンド
このコマンドはレジスタregの内容をカレントバッファに挿入する。

通常、このコマンドは挿入したテキストのまえにポイントを置き、 そのあとにマークを置く。 しかし、省略可能な2番目の引数beforepnil以外であると、 まえにマークを置きあとにポイントを置く。 この関数を対話的に呼び出すときに前置引数を指定すれば、 2番目の引数beforepnil以外を渡せる。

レジスタに矩形領域が含まれる場合、 ポイント位置に矩形領域の左上隅がくるように挿入される。 つまり、テキストは現在行とそのしたの連続する行に挿入される。

保存したテキスト(文字列)や矩形領域(リスト)以外がレジスタに入っていると、 現状では有用なことは起こらない。 将来これは変更されるであろう。


Node:Transposition, Next:, Previous:Substitution, Up:Text

テキストの転置

つぎのサブルーティンは転置コマンドで使われます。

transpose-regions start1 end1 start2 end2 &optional leave-markers Function
この関数は、バッファの重なり合わない2つの部分を入れ換える。 引数start1end1で一方の部分の境界を指定し、 引数start2end2で他方の部分の境界を指定する。

通常、transpose-regionsは転置したテキスト内のマーカを再配置する。 つまり、2つの転置部分の一方の内側を指していたマーカは その部分とともに移動して、新しい位置で同じ2つの文字のあいだに留まる。 しかし、leave-markersnil以外であると、 transpose-regionsはこれを行わず、 すべてのマーカは再配置されない。


Node:Change Hooks, Previous:Registers, Up:Text

変更フック

これらのフックにより、すべてのバッファ (それらをバッファローカルにしておけば特定のバッファ)における すべての変更を知るようにできます。 テキストの特定部分の変更を検出する方法については、 Special Propertiesも参照してください。

これらのフックに使う関数において正規表現を使う場合には、 マッチデータを保存し復元する必要があります。 さもないと、それらを呼び出す編集操作と奇妙な干渉を引き起こします。

before-change-functions Variable
この変数は、バッファを変更するまえに呼び出すべき関数のリストを保持する。 各関数は2つの引数、つまり、整数で表した変更対象の領域の先頭と末尾を受け取る。 変更対象のバッファはつねにカレントバッファである。

after-change-functions Variable
この変数は、バッファを変更したあとに呼び出すべき関数のリストを保持する。 各関数は3つの引数、つまり、変更されたばかりの領域の先頭と末尾、 変更前に存在していたテキストの長さを受け取る。 3つの引数はすべて整数である。 変更対象のバッファはつねにカレントバッファである。

古いテキストの長さは、変更前のそのテキストの先頭と末尾の バッファ内位置の差である。 変更済みのテキストの長さは、単純に始めの2つの引数の差である。

combine-after-change-calls body... Macro
このマクロは通常どおりbodyを実行するが、 一連の変更に対して安全と思えるときには、 after-change-functionsの関数を一度だけ呼び出す。

プログラムからバッファの同じ部分でテキスト変更を複数回行う場合、 プログラムの当該部分の周りでマクロcombine-after-change-callsを使うと、 フックafter-change-functionsを使用してるときには 動作がかなり速くなりうる。 最終的にフックafter-change-functionsが呼ばれると、 combine-after-change-callsの本体で行った変更すべてを含むような バッファ部分が引数に指定される。

警告: フォームcombine-after-change-callsの本体の内側では after-change-functionsafter-change-functionの値を 変更しないこと。

注意: 変更がバッファの広く分散した部分に行われるときにもこれは動作するが、 推奨できない。 非効率なふるまいをするようなフック関数があるからである。

before-change-function Variable
この廃れた変数は、任意のバッファの変更を行うまえに 呼ばれる1つの関数を保持する (nilならばそのような関数はなし)。 before-change-functionsの関数と同様に呼ばれる。

after-change-function Variable
この廃れた変数は、任意のバッファの変更を行ったあとに 呼ばれる1つの関数を保持する (nilならばそのような関数はなし)。 after-change-functionsの関数と同様に呼ばれる。

上の4つの変数は、これらの関数が実行中には一時的にnilに束縛されます。 つまり、これらの関数の1つがバッファを変更しても、 その変更ではこれらの関数を呼び出しません。 フック関数においてこれらの関数を実行するような変更を行いたい場合には、 フック関数でこれらの変数をそれらの通常の値に束縛し直します。

この保護的な機構の1つの不便な帰結は、 after-change-functionsbefore-change-functionsには、 その変数の値を変更する関数を持てないことです。 しかし、これは本当の制限ではありません。 それらの関数で実行すべき関数のリストを変更したければ、 単純に1つの定まった関数をフックに追加し、 その関数では呼び出すべき別の関数を指定する別の変数を調べます。 つぎのようにします。

(setq my-own-after-change-functions nil)
(defun indirect-after-change-function (beg end len)
  (let ((list my-own-after-change-functions))
    (while list
      (funcall (car list) beg end len)
      (setq list (cdr list)))))

(add-hooks 'after-change-functions
           'indirect-after-change-function)

first-change-hook Variable
この変数は、未変更状態のバッファを変更するたびに実行される ノーマルフックである。


Node:Non-ASCII Characters, Next:, Previous:Text, Up:Top

非ASCII文字

本章では、非ASCIIに関連する特別なことがらと それらが文字列やバッファにどのように保存されるかについて述べます。


Node:Text Representations, Next:, Up:Non-ASCII Characters

テキスト表現

Emacsには2つのテキスト表現、つまり、 文字列やバッファでテキストを表す方法が2つあります。 これらは、ユニバイト(unibyte)と マルチバイト(multibyte)と呼ばれます。 各文字列や各バッファでは、これらの2つの表現の一方を使います。 ほとんどの目的には、Emacsがこれらのあいだで適切に変換するので、 読者はこれらの表現に関しては無視できます。 Lispプログラムでは、これらの違いに注意する必要がしばしばあります。

ユニバイト表現では、各文字は1バイトを占め、 そのため、可能な文字コードの範囲は0から255です。 コード0から127はASCII文字です。 コード128から255は非ASCII文字集合の1つ (変数nonascii-insert-offsetに設定して文字集合を選べる) に使われます。

マルチバイト表現では、1文字は1バイト以上を占め、 そのため、Emacsの文字コードの範囲全体を格納できるのです。 マルチバイト文字の最初のバイトはつねに128から159(8進数で0200から0237)の 範囲にあります。 これらの値をリーディングコード(leading code)と呼びます。 マルチバイト文字の2バイト以降はつねに160から255(8進数で0240から0377)の 範囲にあります。 これらの値をトレイリングコード(trailing code)と呼びます。

バッファでは、変数enable-multibyte-charactersの バッファローカルな値が使用する表現を指定します。 文字列の表現は、文字列を作成するときの文字列の内容に基づいて決定されます。

enable-multibyte-characters Variable
この変数は、バッファのテキスト表現を指定する。 これがnil以外であると、バッファはマルチバイトテキストを保持する。 さもなければユニバイトテキストを保持する。

この変数に直接設定することはできない。 そのかわりに、バッファの表現を変更するには、 関数set-buffer-multibyteを使う。

default-enable-multibyte-characters Variable
この変数の値は、 (default-value 'enable-multibyte-characters)に完全に等価であり、 この変数に設定するとデフォルト値を変更する。 バッファのenable-multibyte-charactersのローカルな束縛に設定することは 許されていないが、デフォルト値を変更することは可能であり、 そうしても既存のバッファには影響しないので理にかなっている。

コマンド行オプション--unibyteは、 起動時の早い段階でデフォルト値にnilを設定することで役目を果たす。

multibyte-string-p string Function
文字列stringにマルチバイト文字が含まれるとtを返す。


Node:Converting Representations, Next:, Previous:Text Representations, Up:Non-ASCII Characters

テキスト表現の変換

Emacsはユニバイトテキストをマルチバイトに変換できます。 マルチバイトテキストをユニバイトにも変換できますが、 この変換では情報が欠落します。 バッファにテキストを挿入するとき、あるいは、 複数の文字列から1つの文字列にテキストを収めるときに、 一般にこれらの変換が行われます。 文字列の内容をどちらかの表現に明示的にも変換できます。

Emacsは、文字列を作成するときにはその内容に基づいて 文字列の表現を選びます。 一般則は、ユニバイトテキストを他のマルチバイトテキストに組み入れるときには ユニバイトテキストをマルチバイトテキストに変換します。 マルチバイト表現のほうが汎用であり、 ユニバイトテキストのどんな文字でも保持できるからです。

バッファにテキストを挿入するときには、Emacsは、 当該バッファのenable-multibyte-charactersの指定に従った バッファの表現にテキストを変換します。 特に、ユニバイトバッファにマルチバイトテキストを挿入するときには、 マルチバイトテキスト内のすべての文字を一般には保存できなくても、 Emacsはテキストをユニバイトに変換します。 自然な代替案はバッファ内容をマルチバイトに変換することですが、 これは受け入れられません。 バッファの表現はユーザーが選択したものであり自動的には無視できないからです。

ユニバイトテキストをマルチバイトテキストに変換しても ASCII文字は無変更であり、128から159も同様です。 160から255の非ASCIIについては、 各文字にnonascii-insert-offsetの値を加算することで変換します。 この変数に設定すると、ユニバイト文字がどの文字集合に対応するかを指定できます (see Character Sets)。 たとえば、nonascii-insert-offset(- (make-char 'latin-iso8859-1) 128)の2048であると、 非ASCIIのユニバイトはLatin 1に対応します。 (- (make-char 'greek-iso8859-7) 128)の2688であると、 ギリシャ文字に対応します。

マルチバイトテキストをユニバイトに変換するのは簡単で、 各文字コードと255の論理積をとります。 nonascii-insert-offsetに 文字集合の始まりに対応する合理的な値が設定されていれば、 この変換は逆変換になります。 つまり、ユニバイトテキストをマルチバイトに変換し、 それをユニバイトに戻すともとのユニバイトテキストになります。

nonascii-insert-offset Variable
この変数は、ユニバイトテキストをマルチバイトに変換するときに 非ASCII文字に加算する値を指定する。 これは、128から255のユニバイトの非ASCIIの範囲の文字を挿入する self-insert-commandにも適用される。 しかし、関数insert-charはこの変換を行わない。

文字集合csを選択する正しい値は、 (- (make-char cs) 128)である。 nonascii-insert-offsetの値が0であると、 実際の変換には0ではなくLatin 1文字集合に対する値を使う。

nonascii-translation-table Variable
この変数は、nonascii-insert-offsetのより一般的な代替を提供する。 128から255の範囲の各コードをマルチバイト文字に変換する方法を 独立して指定するために使える。 その値はベクトルかnilであること。 これがnil以外であると、nonascii-insert-offsetに優先する。

string-make-unibyte string Function
この関数は、stringのテキストがすでにユニバイトでなければ ユニバイト表現に変換してから結果を返す。 stringがユニバイトであれば無変更で返す。

string-make-multibyte string Function
この関数は、stringのテキストがすでにマルチバイトでなければ マルチバイト表現に変換してから結果を返す。 stringがマルチバイトであれば無変更で返す。


Node:Selecting a Representation, Next:, Previous:Converting Representations, Up:Non-ASCII Characters

表現の選択

既存のバッファや文字列がユニバイトであるときに マルチバイトとして調べたり、その逆のように調べるのが 有用なこともあります

set-buffer-multibyte multibyte Function
カレントバッファの表現方法を設定する。 multibytenil以外であると、バッファはマルチバイトになる。 multibytenilであると、バッファはユニバイトになる。

この関数は、バイト列としてみたバッファ内容を変更しない。 その結果、文字として見たときの内容を変更できる。 マルチバイト表現では1文字とみなされる2バイトの列は、 ユニバイト表現では2文字になる。

この関数は、enable-multibyte-charactersに どちらの表現を使用しているかを記録する。 さらに(オーバレイ、テキスト属性、マーカなどの)バッファ内のさまざまな データを調整して、それ以前と同様に同じテキストに及ぶようにする。

string-as-unibyte string Function
この関数は、各バイトを1文字とみなして stringと同じバイトの文字列を返す。 つまり、値にはstringより多くの文字が含まれることがある。

stringがすでにユニバイトであると、 値はstringそのものである。

string-as-multibyte string Function
この関数は、マルチバイトの各列を1文字とみなして stringと同じバイトの文字列を返す。 つまり、値にはstringより少ない文字が含まれることがある。

stringがすでにマルチバイトであると、 値はstringそのものである。


Node:Character Codes, Next:, Previous:Selecting a Representation, Up:Non-ASCII Characters

文字コード

ユニバイトとマルチバイトのテキスト表現では、 異なる文字コードを使っています。 ユニバイト表現において正しい文字コードは0から255の範囲であり、 これらの値は1バイトに収まります。 マルチバイト表現において正しい文字コードは0から524287の範囲ですが、 この範囲のすべての値が正しいとは限りません。 特に、値128から255は (『生のバイト』にはありうる。see Explicit Encoding)、 マルチバイトテキストでは正しくありません。 0から127のASCIIコードのみが、どちらの表現でも完全に正しいのです。

char-valid-p charcode Function
この関数は、charcodeが2つのテキスト表現のどちらか一方で 正しければtを返す。
(char-valid-p 65)
     => t
(char-valid-p 256)
     => nil
(char-valid-p 2248)
     => t


Node:Character Sets, Next:, Previous:Character Codes, Up:Non-ASCII Characters

文字集合

Emacsは文字をさまざまな文字集合(character set)に分類します。 文字集合にはシンボルである名前があります。 各文字はたった1つの文字集合に属します。

一般に、異なる文字体系ごとに1つの文字集合があります。 たとえば、latin-iso8859-1は1つの文字集合であり、 greek-iso8859-7は別の文字集合であり、 asciiも別の文字集合です。 Emacsの1つの文字集合には最大9025個の文字を保持できます。 したがって、論理的には1つの文字集合にまとめられる文字群を、 複数の文字集合に分割する場合もあります。 たとえば、Big 5として一般には知られている中国文字の1つの集合は、 Emacsの2つの文字集合、chinese-big5-1chinese-big5-2に 分割されます。

charsetp object Function
objectが文字集合の名前のシンボルであればtを返す。 さもなければnilを返す。

charset-list Function
この関数は、定義されているすべての文字集合の名前のリストを返す。

char-charset character Function
この関数は文字characterが属する文字集合の名前を返す。


Node:Chars and Bytes, Next:, Previous:Character Sets, Up:Non-ASCII Characters

文字とバイト

マルチバイト表現では、各文字は1バイトかそれ以上のバイトを占めます。 各文字集合には、通常は1バイト長か2バイト長の 導入列(introduction sequence)があります (例外:ASCIIの導入列は0バイト長である)。 導入列は、文字集合の任意の文字のバイト列の始まりです。 文字のバイト列の残りの部分は、同じ文字集合内で他の文字とその文字を区別します。 文字集合に依存して、区別するためのバイトは1バイトか2バイトです。 そのようなバイト数を文字集合の次元(dimension)と呼びます。

charset-dimension charset Function
この関数は、文字集合charsetの次元を返す。 現在、次元はつねに1か2である。

文字集合の導入列のバイト長を判定するもっとも簡単な方法はつぎのとおりです。

(- (char-bytes (make-char charset))
   (charset-dimension charset))


Node:Splitting Characters, Next:, Previous:Chars and Bytes, Up:Non-ASCII Characters

文字の分割

本節の関数は、文字とそれを表現するために用いられるバイト値のあいだの 変換を行います。 ほとんどの目的に関しては、Emacsが必要に応じて自動的に行うため、 文字を表現するためのバイト列を扱う必要はありません。

char-bytes character Function
この関数は、文字characterを表現するために必要なバイト数を返す。 これは、文字characterが属する文字集合だけに依存し、 その文字集合(see Character Sets)の次元とその導入列の和に等しい。
(char-bytes 2248)
     => 2
(char-bytes 65)
     => 1
(char-bytes 192)
     => 1

マルチバイト表現とユニバイト表現のどちらに対しても この関数で正しい結果を得られるのは、 2つの表現で用いられる非ASCII文字コードに重なりがないからである。

split-char character Function
文字characterの文字集合の名前に続けて、 その文字集合でcharacterを識別する1バイトか2バイトの値(整数)から 成るリストを返す。 バイト値の個数はその文字集合の次元である。
(split-char 2248)
     => (latin-iso8859-1 72)
(split-char 65)
     => (ascii 65)

ユニバイトの非ASCII文字は、 文字集合asciiの一部とみなす。

(split-char 192)
     => (ascii 192)

make-char charset &rest byte-values Function
この関数は、文字集合charsetにおいて byte-valuesで識別される文字を返す。 これは、split-charのほぼ逆関数にあたる。 通常、文字集合charsetの次元に応じて、 1つか2つのbyte-valuesを指定する。 たとえばつぎのとおり。
(make-char 'latin-iso8859-1 72)
     => 2248

byte-valuesを指定せずにmake-charを呼び出すと、 その結果は文字集合charsetを代表する 汎用文字(generic character)である。 汎用文字は整数であるが、文字としてバッファに挿入するには 正しくないものである。 1つの文字集合全体を表すためにchar-table-rangeで使える (see Char-Tables)。 char-valid-pは汎用文字に対してはnilを返す。 たとえばつぎのとおり。

(make-char 'latin-iso8859-1)
     => 2176
(char-valid-p 2176)
     => nil
(split-char 2176)
     => (latin-iso8859-1 0)


Node:Scanning Charsets, Next:, Previous:Splitting Characters, Up:Non-ASCII Characters

文字集合の走査

バッファや文字列の一部分にどの文字集合が現れるかを 調べられると有用なことがあります。 その1つの用途は、当該テキストすべてを表現する能力がある コーディングシステム(see Coding Systems)を探すことです。

find-charset-region beg end &optional translation Function
この関数は、カレントバッファのbegendのあいだに 現れる文字集合のリストを返す。

省略可能な引数translationは、 テキストを走査するときに使用する変換表を指定する (see Translation of Characters)。 これがnil以外であると、領域内の各文字をこの表を介して変換し、 戻り値は、バッファ内の実際の文字のかわりに変換した文字に関する情報を与える。

find-charset-string string &optional translation Function
この関数は、文字列stringに現れる文字集合のリストを返す。

省略可能な引数translationは変換表を指定する。 上記のfind-charset-regionを参照。


Node:Translation of Characters, Next:, Previous:Scanning Charsets, Up:Non-ASCII Characters

文字の変換

変換表(translation table)は、文字群を文字群へ対応付けます。 これらの表は、符号化と復号化、他の目的に使われます。 独自の変換表を指定するコーディングシステムもあります。 他のすべてのコーディングシステムに適用される デフォルトの変換表もあります。

make-translation-table translations Function
この関数は、引数translationsに基づいた変換表を返す。 引数translationsの各要素は、 (from . to)の形であり、 文字fromtoへ変換することを意味する。

1つの文字集合全体を同じ次元の別の文字集合へ対応付けることも可能である。 それには、fromに(文字集合を表す)汎用文字を指定する (see Splitting Characters)。 この場合、toも、同じ次元の別の文字集合の汎用文字であること。 こうすると、この変換表は、fromの文字集合の各文字を toの文字集合の対応する文字へ変換する。

復号化では、もとの復号化結果の文字に変換表による変換を適用します。 コーディングシステムに属性character-translation-table-for-decodeが あれば、これは使用する変換表を指定します。 さもなければ、standard-character-translation-table-for-decodenil以外であれば、復号化ではその表を使います。

符号化では、バッファ内の文字に変換表による変換を適用し、 変換結果を実際に符号化します。 コーディングシステムに属性character-translation-table-for-encodeが あれば、これは使用する変換表を指定します。 さもなければ、変数standard-character-translation-table-for-encodeが 使用する変換表を指定します。

standard-character-translation-table-for-decode Variable
これは、変換表を指定しないコーディングシステムに対する 復号化時のデフォルトの変換表である。

standard-character-translation-table-for-encode Variable
これは、変換表を指定しないコーディングシステムに対する 符号化時のデフォルトの変換表である。


Node:Coding Systems, Next:, Previous:Translation of Characters, Up:Non-ASCII Characters

コーディングシステム

Emacsがファイルを読み書きしたり、 Emacsがサブプロセスへテキストを送ったり サブプロセスからテキストを受け取るときには、 コーディングシステム(coding system)で指定される 文字コード変換と行末変換を行います。


Node:Coding System Basics, Next:, Up:Coding Systems

コーディングシステムの基本概念

文字コード変換(character code conversion)とは、 Emacsの内部で使用する符号と他の符号とのあいだでの変換のことです。 Emacsでは、相互に変換できる多くの異なる符号を扱えます。 たとえば、Emacsは、Latin 1、Latin 2、Latin 3、Latin 4、Latin 5、 ISO 2022のいくつかの変種を相互に変換できます。 同じ文字集合に対する異なる符号を扱うこともできます。 たとえば、キリル(ロシア語)文字に対しては ISO、Alternativnyj、KOI8の3つのコーディングシステムがあります。

ほとんどのコーディングシステムでは変換する文字コードを特定しますが、 指定せずにデータに基づいて発見的手法で選ぶものもあります。

行末変換(end of line conversion)は、 ファイル内の行の終りを表すさまざまなシステムで 使われている3つの異なる慣習を扱います。 UNIXの慣習では、行送り文字(改行文字とも呼ぶ)を使います。 DOSの慣習では、行末には復帰と行送りの2文字の列を使います。 Macの慣習では、復帰のみを使います。

latin-1のような基底コーディングシステム(base coding system) では、行末変換を指定せずにデータに基づいて選びます。 latin-1-unixlatin-1-doslatin-1-macのような 変種コーディングシステム(variant coding system)では、 明示的に行末変換も指定します。 ほとんどの基底コーディングシステムには、 -unix-dos-macを付加して作られる名前の 対応する3つの変種があります。

コーディングシステムraw-textは 文字コード変換を行わない特別なもので、 このコーディングシステムで訪問したバッファはユニバイトバッファになります。 行末変換も指定しないので内容に基づいて決定でき、 行末変換を指定する3つの変種もあります。 no-conversionraw-text-unixに等価であり、 文字コードも行末も変換しないことを指定します。

コーディングシステムemacs-muleは、 Emacs内部での符号でデータを表現することを指定します。 これは、コード変換を行わないという意味ではraw-textに似ていますが、 結果がマルチバイトデータになる点が異なります。

coding-system-get coding-system property Function
この関数は、コーディングシステムcoding-systemの指定した属性を返す。 コーディングシステムのほとんどの属性は内部目的用であるが、 読者が有用と思うものが1つ、mime-charsetがある。 この属性の値は、当該コーディングシステムで読み書きする 文字コード向けのMIMEに使用する名前である。
(coding-system-get 'iso-latin-1 'mime-charset)
     => iso-8859-1
(coding-system-get 'iso-2022-cn 'mime-charset)
     => iso-2022-cn
(coding-system-get 'cyrillic-koi8 'mime-charset)
     => koi8-r

属性mime-charsetの値は、 コーディングシステムの別名としても定義されている。


Node:Encoding and I/O, Next:, Previous:Coding System Basics, Up:Coding Systems

符号化と入出力

コーディングシステムの主目的は、ファイルの読み書きに使うことです。 関数insert-file-contentsはファイルのデータを復号化するために コーディングシステムを使い、 write-regionはバッファ内容を符号化するために コーディングシステムを使います。

使用するコーディングシステムを明示する(see Specifying Coding Systems) こともできるし、 デフォルトの機構(see Default Coding Systems)を暗に使うこともできます。 しかし、これらの方式ではすべきことを完全に指定しきれないこともあります。 たとえば、undefinedのようなコーディングシステムを選んで、 データに基づいて文字コード変換を行うようにするかもしれません。 そのような場合、コーディングシステムの選択は 入出力操作によって完了します。 しばしば、選択されたコーディングシステムをあとで知りたくなります。

buffer-file-coding-system Variable
この変数は、カレントバッファで訪問するときに使用した コーディングシステムを記録する。 これは、バッファを保存したり、 write-regionでバッファの一部を書くときに使われる。 これらの操作において、ユーザーに別のコーディングシステムを指定するように 問い合わせた場合には、buffer-file-coding-systemは 指定された別のコーディングシステムに更新される。

save-buffer-coding-system Variable
この変数は、write-regionには使わないが、 バッファを保存するために使うコーディングシステムを指定する。 バッファを保存する際に、ユーザーに別のコーディングシステムを指定するように 問い合わせ、かつ、save-buffer-coding-systemを用いている場合には、 これは指定された別のコーディングシステムに更新される。

last-coding-system-used Variable
ファイルやサブプロセスに対する入出力操作では、 使用したコーディングシステム名をこの変数に設定する。 明示的に符号化/復号化する関数(see Explicit Encoding)も この変数に設定する。

警告: サブプロセスから出力を受け取るとこの変数が設定されるため、 Emacsが待つたびに変化する可能性がある。 したがって、読者の興味がある値を保存するような関数を呼び出した直後に その値をコピーして使うこと。

変数selection-coding-systemは、 ウィンドウシステムのセレクションを符号化する方法を指定します。 See Window System Selections


Node:Lisp and Coding Systems, Next:, Previous:Encoding and I/O, Up:Coding Systems

Lispにおけるコーディングシステム

コーディングシステムを扱うLispの機能について述べます。

coding-system-list &optional base-only Function
この関数は、すべてのコーディングシステム名(シンボル)のリストを返す。 base-onlynil以外であると、 値には基底コーディングシステムのみを含める。 さもなければ、値には変種コーディングシステムも含まれる。

coding-system-p object Function
この関数は、objectがコーディングシステム名であるとtを返す。

check-coding-system coding-system Function
この関数は、coding-systemの正当性を調べる。 正しいものならばcoding-systemを返す。 さもなければ、条件coding-system-error付きのエラーを通知する。

coding-system-change-eol-conversion coding-system eol-type Function
この関数は、coding-systemに類似のコーディングシステムを返すが、 eol-typeで指定された行末変換のものである。 eol-typeは、unixdosmacnilの いずれかであること。 nilであると、返されたコーディングシステムは、 データから行末変換を決定する。

coding-system-change-text-conversion eol-coding text-coding Function
この関数は、行末変換にeol-codingを使い、 テキストの変換にtext-codingを使っているコーディングシステムを返す。 text-codingnilであると、 undecidedeol-codingに応じたundecidedの変種の1つを返す。

find-coding-systems-region from to Function
この関数は、fromtoのあいだのテキストの符号化に使用できる コーディングシステムのリストを返す。 リスト内のすべてのコーディングシステムは、当該部分のテキストの どんなマルチバイト文字も安全に符号化できる。

テキストにマルチバイト文字が含まれない場合、 関数はリスト(undecided)を返す。

find-coding-systems-string string Function
この関数は、文字列stringのテキストの符号化に使用できる コーディングシステムのリストを返す。 リスト内のすべてのコーディングシステムは、stringの どんなマルチバイト文字も安全に符号化できる。 テキストにマルチバイト文字が含まれない場合、 これはリスト(undecided)を返す。

find-coding-systems-for-charsets charsets Function
この関数は、リストcharsets内のすべての文字集合の符号化に使用できる コーディングシステムのリストを返す。

detect-coding-region start end &optional highest Function
この関数は、startからendまでのテキストを復号化する もっともらしいコーディングシステムを選ぶ。 このテキストは『生のバイト』(see Explicit Encoding)であること。

この関数は、通常、走査したテキストの復号化を扱える コーディングシステムのリストを返す。 それらは優先順位の降順に並ぶ。 しかし、highestnil以外であると、 戻り値はもっとも順位の高い1つのコーディングシステムである。

領域にASCII文字だけが含まれる場合、 値はundecided(undecided)である。

detect-coding-string string highest Function
この関数はdetect-coding-regionと同様であるが、 バッファ内のバイトのかわりに文字列stringの内容に作用する。

サブプロセスとの入出力に使用されるコーディングシステムを 調べたり設定する方法については、See Process Information


Node:User-Chosen Coding Systems, Next:, Previous:Lisp and Coding Systems, Up:Coding Systems

ユーザー指定のコーディングシステム

select-safe-coding-system from to &optional preferred-coding-system Function
この関数はfromtoのあいだのテキストを符号化する コーディングシステムを選ぶが、 必要ならばユーザーに問い合わせる。

省略可能な引数preferred-coding-systemは、 最初に試すコーディングシステムを指定する。 それが指定領域のテキストを処理できるならば、それを使う。 この引数を省略すると、 buffer-file-coding-systemのカレントバッファでの値をまず試す。

領域内にpreferred-coding-systemで符号化できない マルチバイト文字がある場合、 この関数は、当該テキストを符号化可能なコーディングシステム一覧から ユーザーに選択してもらい、ユーザーが選択したものを返す。

特殊機能: fromが文字列であると、 文字列を調べる対象とし、toは無視する。

補完を用いてユーザーにコーディングシステムを指定させるために使える 2つの関数はつぎのとおりです。 See Completion

read-coding-system prompt &optional default Function
この関数は、文字列promptをプロンプトとして ミニバッファを使ってコーディングシステムを読み取り、 コーディングシステム名をシンボルとして返す。 ユーザーの入力が空であると、 defaultは返すべきコーディングシステムを指定する。 それはシンボルか文字列であること。

read-non-nil-coding-system prompt Function
この関数は、文字列promptをプロンプトとして ミニバッファを使ってコーディングシステムを読み取り、 コーディングシステム名をシンボルとして返す。 ユーザーが空を入力しようとすると再度問い合わせる。 see Coding Systems


Node:Default Coding Systems, Next:, Previous:User-Chosen Coding Systems, Up:Coding Systems

デフォルトのコーディングシステム

本節では、特定のファイルや特定のサブプログラムを実行するときの デフォルトのコーディングシステムを指定する変数と、 それらを使った入出力操作を行う関数について述べます。

これらの変数の目的は、読者が望むデフォルトをいったんこれらに設定しておけば、 再度変更する必要がないようにすることです。 Lispプログラムの特定の操作向けに特定のコーディングシステムを指定するには、 これらの変数を変更しないでください。 かわりに、coding-system-for-readcoding-system-for-writeを 使って上書きします(see Specifying Coding Systems)。

file-coding-system-alist Variable
この変数は、特定のファイルの読み書きに使用する コーディングシステムを指定する連想リストである。 各要素は(pattern . coding)の形であり、 patternは特定のファイル名に一致する正規表現である。 patternに一致するファイル名に当該要素を適用する。

要素のCDRcodingはコーディングシステムであるか、 2つのコーディングシステムを収めたコンスセルであるか、 関数シンボルであること。 codingがコーディングシステムであると、 ファイルの読み書きの両方にそのコーディングシステムを使う。 codingが2つのコーディングシステムを収めたコンスセルであると、 そのCARは復号化に使うコーディングシステムを指定し、 そのCDRは符号化に使うコーディングシステムを指定する。

codingが関数シンボルであると、 その関数は、コーディングシステムか、 2つのコーディングシステムを収めたコンスセルを返すこと。 その値は上に述べたように使われる。

process-coding-system-alist Variable
この変数は、サブプロセスで実行しているプログラムに依存して サブプロセスに使うコーディングシステムを指定する連想リストである。 file-coding-system-alistと同様に働くが、 patternはサブプロセスを始めるために用いたプログラム名に対して 一致を取る点が異なる。 この連想リストに指定したコーディングシステムは、 サブプロセスとの入出力に使用するコーディングシステムの初期化に用いれるが、 set-process-coding-systemを使って、 あとで別のコーディングシステムを指定できる。

警告: データからコーディングシステムを決定するundecidedのような コーディングシステムは、非同期サブプロセスの出力に対しては 完全に信頼性のある動作はできない。 これは、Emacsが非同期サブプロセスの出力が 到着するたびに一塊で処理するからである。 コーディングシステムが文字コード変換や行末変換を未指定にしていると、 Emacsは1つの塊から正しい変換を検出しようと試みるが、 これがつねに動作するとは限らない。

したがって、非同期サブプロセスでは、可能な限り 文字コード変換と行末変換の両方を指定したコーディングシステムを使います。 つまり、undecidedlatin-1などではなく、 latin-1-unixのようなものを使います。

network-coding-system-alist Variable
この変数は、ネットワークストリームに使用するコーディングシステムを 指定する連想リストである。 file-coding-system-alistと同様に働くが、 要素内のpatternはポート番号か正規表現である点が異なる。 それが正規表現であると、ネットワークストリームを開くために 使用したネットワークサービス名に対して一致をとる。

default-process-coding-system Variable
この変数は、なにも指定されていないサブプロセス(やネットワークストリーム) の入出力に使用するコーディングシステムを指定する。

値は、(input-coding . output-coding)の形の コンスセルであること。 ここで、input-codingはサブプロセスからの入力に適用され、 output-codingはそれへの出力に適用される。

find-operation-coding-system operation &rest arguments Function
この関数は、argumentsを指定してoperationを行うときに (デフォルトで)使用されるコーディングシステムを返す。 その値はつぎの形である。
(decoding-system encoding-system)

第1要素decoding-systemは (operationが復号化を行う場合には)復号化に用いる コーディングシステムであり、 encoding-systemは (operationが符号化を行う場合には)符号化に用いる コーディングシステムである。

引数operationは、Emacsの入出力基本関数の insert-file-contentswrite-regioncall-processcall-process-regionstart-processopen-network-streamのいずれかであること。

残りの引数は、これらの入出力基本関数に指定するであろう引数と同じであること。 基本関数に依存して、引数の1つを対象として選ぶ。 たとえば、operationがファイル入出力を行う場合、 ファイル名を指定する引数が対象である。 サブプロセスの基本関数では、プロセス名が対象である。 open-network-streamでは、サービス名やポート番号が対象である。

この関数は、operationに応じて当該対象を file-coding-system-alistprocess-coding-system-alistnetwork-coding-system-alistで探す。 see Default Coding Systems


Node:Specifying Coding Systems, Next:, Previous:Default Coding Systems, Up:Coding Systems

1つの操作向けにコーディングシステムを指定する

変数coding-system-for-readと/やcoding-system-for-writeを 束縛することで、特定の1つの操作向けのコーディングシステムを指定できます。

coding-system-for-read Variable
この変数がnil以外であると、 ファイルを読むときや同期プロセスからの入力に用いる コーディングシステムを指定する。

これは非同期プロセスやネットワークストリームにも適用されるが、 異なった方法で適用される。 サブプロセスを開始したりネットワークストリームを開いたときの coding-system-for-readの値は、 そのサブプロセスやネットワークストリームの入力の復号化方法を指定する。 変更されない限り、そのサブプロセスやネットワークストリームに 対して使われ続ける。

この変数の正しい使い方は、特定の入出力操作に対して letで束縛することである。 そのグローバルな値は通常はnilであり、 グローバルにこれ以外の値を設定するべきではない。 この変数の正しい使い方の例をつぎに示す。

;; 文字コード変換せずにファイルから読む
;; CRLFが行末を表すと仮定する
(let ((coding-system-for-write 'emacs-mule-dos))
  (insert-file-contents filename))

その値がnil以外であると、 coding-system-for-readは、 file-coding-system-alistprocess-coding-system-alistnetwork-coding-system-alist、 を含めて入力に用いるコーディングシステムの 他のすべての指定方法に優先する。

coding-system-for-write Variable
これはcoding-system-for-readと同様に働くが、 入力ではなく出力に適用される点が異なる。 ファイル、サブプロセス、ネットワーク接続へ書くことに影響する。

call-process-regionstart-processのように、 1つの操作で入力と出力を行うときには、 coding-system-for-readcoding-system-for-writeの 両方が影響する。

inhibit-eol-conversion Variable
この変数がnil以外であると、 コーディングシステムでなにが指定されていようと行末変換を行わない。 これは、Emacsの入出力とサブプロセスのすべての基本関数、 明示的な符号化/復号化関数(see Explicit Encoding)に適用される。


Node:Explicit Encoding, Next:, Previous:Specifying Coding Systems, Up:Coding Systems

明示的な符号化と復号化

Emacsへ/からテキストを転送するすべての操作には、 テキストを符号化したり復号化するコーディングシステムを使う能力があります。 本節に述べる関数を用いてテキストを明示的に符号化したり復号化できます。

符号化の結果と復号化する入力は、通常のEmacsのテキストではありません。 それらは『生のバイト』、つまり、外部ファイルと同じ方法で テキストを表現するバイト列です。 バッファに生のバイトが収められている場合、 set-buffer-multibyte(see Selecting a Representation)を用いて バッファはユニバイト表現であると印を付けるのがもっとも自然ですが、 これは必須ではありません。 バッファの内容が単に一時的に生のバイトであるときには、 バッファはマルチバイトのままにしておきます。 バッファ内容を復号化すれば正しくなります。

明示的に復号化するためにバッファに生のバイトを入れる普通の方法は、 insert-file-contents-literally(see Reading from Files)で ファイルから読むか、 find-file-noselectでファイルを訪問するときに引数rawfilenil以外を指定します。

テキストの明示的な符号化で得た結果である生のバイトを使う普通の方法は、 ファイルやプロセスへそれらをコピーします。 たとえば、write-region(see Writing to Files)でそれらを書くには、 coding-system-for-writeno-conversionを束縛して write-regionの符号化を抑制します。

生のバイトには、正しいマルチバイト文字に 余分なトレイリングコードが付いたように見える長すぎるバイト列が 含まれる場合があります。 ほとんどの目的には、バッファや文字列のそのような列をEmacsは1文字として扱い、 その文字コードを調べるとマルチバイト文字の列に対応した値を得るはずです。 余分なバイト列は無視されます。 このふるまいは透明性がよくありませんが、 生のバイトはEmacsの限定された場面でのみ使われ、実用上の問題は回避できます。

encode-coding-region start end coding-system Function
この関数は、コーディングシステムcoding-systemに従って startからendのテキストを符号化する。 符号化結果はバッファ内のもとのテキストを置き換える。 符号化結果は『生のバイト』であるが、 マルチバイトであったバッファはマルチバイトのままである。

encode-coding-string string coding-system Function
この関数は、コーディングシステムcoding-systemに従って 文字列stringのテキストを符号化する。 符号化したテキストを含む新たな文字列を返す。 符号化結果は『生のバイト』のユニバイト文字列である。

decode-coding-region start end coding-system Function
この関数は、コーディングシステムcoding-systemに従って startからendのテキストを復号化する。 復号化結果はバッファ内のもとのテキストを置き換える。 明示的な復号化が有用であるためには、 復号化前のテキストは『生のバイト』であること。

decode-coding-string string coding-system Function
この関数は、コーディングシステムcoding-systemに従って 文字列stringのテキストを復号化する。 復号化したテキストを含む新たな文字列を返す。 明示的な復号化が有用であるためには、 復号化前のstringの内容は『生のバイト』であること。


Node:Terminal I/O Encoding, Next:, Previous:Explicit Encoding, Up:Coding Systems

端末入出力の符号化

Emacsは、コーディングシステムを用いてキーボード入力を復号化したり、 端末出力を符号化できます。 Latin-1などの特定の符号を用いてテキストを送信したり表示する 端末に対しては、これは有用です。 Emacsは、端末に対する符号化や復号化では last-coding-system-usedに設定しません。

keyboard-coding-system Function
この関数は、キーボード入力の復号化に用いている コーディングシステムを返す。 コーディングシステムを使用していなければnilを返す。

set-keyboard-coding-system coding-system Function
この関数は、キーボード入力の復号化に使用するコーディングシステムとして coding-systemを指定する。 coding-systemnilであると、 キーボード入力に復号化を用いないことを意味する。

terminal-coding-system Function
この関数は、端末出力の符号化に用いている コーディングシステムを返す。 コーディングシステムを使用していなければnilを返す。

set-terminal-coding-system coding-system Function
この関数は、端末出力の符号化に使用するコーディングシステムとして coding-systemを指定する。 coding-systemnilであると、 端末出力に符号化を用いないことを意味する。


Node:MS-DOS File Types, Previous:Terminal I/O Encoding, Up:Coding Systems

MS-DOSのファイル型

MS-DOSやMS-Windows上のEmacsは、 特定のファイル名をテキストファイルやバイナリファイルとして認識します。 『バイナリファイル』とは、必ずしも文字を意味しないバイト値のファイルです。 Emacsは、バイナリファイルに対しては行末変換や文字コード変換を行いません。 一方、その名前から『テキストファイル』と印が付いた 新規ファイルを作成すると、EmacsはDOSの行末変換を行います。

buffer-file-type Variable
この変数は、各バッファで自動的にバッファローカルになり、 バッファで訪問したファイルのファイル型を記録する。 バッファがbuffer-file-coding-systemで コーディングシステムを指定しない場合、 バッファ内容を書き出すときに用いるコーディングシステムを この変数を用いて決定する。 テキストに対してはnil、バイナリに対してtであること。 これがtであると、コーディングシステムはno-conversionである。 さもなければ、undecided-dosを用いる。

通常、この変数はファイルを訪問すると設定される。 いかなる変換も行わずにファイルを訪問するとnilに設定される。

file-name-buffer-file-type-alist User Option
この変数は、テキスト/バイナリファイルを認識するための連想リストを保持する。 各要素は(regexp . type)の形である。 ここで、regexpはファイル名に対して一致をとり、 typeは、テキストファイルではnil、 バイナリファイルではt、あるいは、 どちらであるかを計算するために呼び出す関数である。 それが関数であると、1つの引数(ファイル名)で呼ばれ、 tnilを返すこと。

MS-DOSやMS-Windowsで動作しているEmacsは、 この連想リストを調べて、ファイルを読む際に使用する コーディングシステムを決定する。 テキストファイルではundecided-dosが使われる。 バイナリファイルではno-conversionが使われる。

指定したファイルがこの連想リストの要素に一致しないと、 default-buffer-file-typeがファイルの扱い方を指定する。

default-buffer-file-type User Option
この変数は、file-name-buffer-file-type-alistが指定しない型の ファイルの扱い方を指定する。

この変数がnil以外であると、そのようなファイルはバイナリとして扱われ、 コーディングシステムno-conversionを用いる。 さもなければそれらに対して特別なことを行わずに、 Emacsの通常のとおりにファイル内容からコーディングシステムを決定する。


Node:Input Methods, Previous:Coding Systems, Up:Non-ASCII Characters

入力方式

入力方式(input method)は、 キーボードから非ASCII文字を入力する簡便な方法を提供します。 プログラムが読み取るための非ASCII文字の符号変換を行う コーディングシステムと異なり、 入力方式は人間向けのコマンドを提供します。 (テキストを入力するための入力方式の使い方については、 see Input Methods。) 入力方式の定義方法については本書ではまだ明文化してありませんが、 ここではそれらの使い方について述べます。

各入力方式には名前があります。 それは現在のところ文字列ですが、 将来は入力方式名としてシンボルも使えるようになります。

current-input-method Variable
この変数は、カレントバッファで現在活性な入力方式の名前を保持する。 (この変数に設定すると自動的にバッファローカルになる。) nilであると、バッファでは入力方式が活性ではない。

default-input-method Variable
この変数は、入力方式を選ぶコマンド向けのデフォルトの入力方式を保持する。 current-input-methodと異なり、この変数は通常はグローバルである。

set-input-method input-method Function
この関数は、カレントバッファにおいて 入力方式input-methodを活性にする。 default-input-methodにもinput-methodを設定する。 input-methodnilであると、 この関数はカレントバッファの入力方式を不活性にする。

read-input-method-name prompt &optional default inhibit-null Function
この関数は、プロンプトpromptを用いてミニバッファで入力方式名を読む。 defaultnil以外であると、 ユーザーが空の入力をするとデフォルトでこれを返す。 しかし、inhibit-nullnil以外であると、 空の入力はエラーを通知する。

戻り値は文字列である。

input-method-alist Variable
この変数は、使用可能なすべての入力方式を定義する。 各要素は1つの入力方式を定義し、つぎの形であること。
(input-method language-env activate-func
 title description args...)

ここで、input-methodは入力方式名であり文字列である。 language-envも別の文字列であり当該入力方式を 推奨する言語環境の名前である。 (これは説明文目的のためだけである。)

titleは、この入力方式が活性である場合に モード行に表示される文字列である。 descriptionはこの入力方式と何向きであるかを 説明する文字列である。

activate-funcは、この入力方式を活性にするために呼び出す関数である。 argsがあればactivate-funcへの引数として渡される。 つまり、activate-funcの引数はinput-methodargsである。

入力方式に対する基本的なインターフェイスは 変数input-method-functionを介して行います。 See Reading One Event


Node:Searching and Matching, Next:, Previous:Non-ASCII Characters, Up:Top

探索と一致

GNU Emacsにはバッファから指定したテキストを探す方法が2つあります。 文字列そのものを正確に探索するのと正規表現の探索です。 正規表現の探索のあとでは、 正規表現全体やそのさまざまな部分に一致したテキストを表す マッチデータ(match data)を調べることができます。

skip-chars...などの関数もある種の探索を行います。 See Skipping Characters


Node:String Search, Next:, Up:Searching and Matching

文字列の探索

これらは、バッファ内のテキストを探索するための基本関数です。 これらはプログラムで使うことを意図していますが、 対話的に呼び出すこともできます。 その場合、探索文字列を問い合わせてきますが、 limitnoerrornilに、repeatは1に設定されます。

これらの探索関数は、バッファがマルチバイトであると 探索文字列をマルチバイトに変換します。 バッファがユニバイトであると探索文字列をユニバイトに変換します。 See Text Representations

search-forward string &optional limit noerror repeat コマンド
この関数は、ポイントから前方へ向けて文字列stringに ちょうど一致するものを探す。 それに成功すれば、ポイントをみつけた出現箇所の末尾に移動し、 ポイントの新たな値を返す。 一致がみつからなければ、戻り値と副作用はnoerrorに依存する(下記参照)。

つぎの例では、ポイントは始めは行頭にある。 そして(search-forward "fox")foxの最後の文字のうしろに ポイントを移動する。

---------- Buffer: foo ----------
-!-The quick brown fox jumped over the lazy dog.
---------- Buffer: foo ----------

(search-forward "fox")
     => 20

---------- Buffer: foo ----------
The quick brown fox-!- jumped over the lazy dog.
---------- Buffer: foo ----------

引数limitは探索の上限を指定する。 (カレントバッファ内の位置であること。) その位置を越える箇所での一致は受け入れない。 limitを省略したりnilであると、 デフォルトは、バッファの参照可能部分の末尾である。

探索に失敗した場合の動作は、noerrorの値に依存する。 noerrornilであると、 エラーsearch-failedを通知する。 noerrortであると、 search-forwardnilを返しなにもしない。 noerrornilでもtでもないと、 search-forwardはポイントを上限位置へ移動してnilを返す。 (この場合にもポイントの新たな値を返すほうが一貫性があるが、 値nilに依存しているプログラムがある。)

repeatを指定してあると(正の数であること)、 その回数だけ探索を繰り返す(一致箇所の末尾を新たな探索の開始位置とする)。 連続してこれらの探索に成功すると関数は成功し、 ポイントを移動してその新たな値を返す。 さもなければ探索は失敗である。

search-backward string &optional limit noerror repeat コマンド
この関数は、ポイントから後方へ向けてstringを探索する。 search-forwardと同様であるが、後方へ向けて探索し 一致箇所の先頭にポイントを置く点が異なる。

word-search-forward string &optional limit noerror repeat コマンド
この関数は、ポイントから前方へ向けてstringに一致する『単語』を探索する。 一致をみつけると、一致箇所の末尾にポイントを設定し ポイントの新たな値を返す。

単語の一致では、stringを単語の列とみなし、 それらを区切る句読点は無視する。 バッファ内の同じ単語の列を探す。 バッファ内の各単語は別々になっている必要があるが (単語ballを探索すると単語ballsには一致しない)、 句読点や空白の詳細は無視される (ball boyを探索するとball. Boy!に一致する)。

つぎの例では、ポイントは始めはバッファの先頭にある。 探索するとポイントはy!のあいだに移動する。

---------- Buffer: foo ----------
-!-He said "Please!  Find
the ball boy!"
---------- Buffer: foo ----------

(word-search-forward "Please find the ball, boy.")
     => 35

---------- Buffer: foo ----------
He said "Please!  Find
the ball boy-!-!"
---------- Buffer: foo ----------

limitnil以外(カレントバッファ内の位置)であると、 それは探索の上限を指定する。 みつかった一致箇所はその位置を越えてはならない。

noerrornilであると、 探索に失敗するとエラーword-search-failedを通知する。 noerrortであると、 エラーを通知するかわりにnilを返す。 noerrornilでもtでもないと、 ポイントをlimit(あるいはバッファの末尾)へ移動してnilを返す。

repeatnil以外であると、 その回数だけ探索を繰り返す。 ポイントは最後の一致箇所の末尾へ置かれる。

word-search-backward string &optional limit noerror repeat コマンド
この関数はポイントから後方へ向けてstringに一致する単語を探索する。 この関数はword-search-forwardと同様であるが、 後方へ向けて探索し一致箇所の先頭にポイントを置く点が異なる。


Node:Regular Expressions, Next:, Previous:String Search, Up:Searching and Matching

正規表現

正規表現(regular expression、略してregexp)は、 文字列の(無限の可能性もある)集合を表すパターンです。 正規表現への一致を探すことは、非常に強力な操作です。 本節では、正規表現の書き方を説明します。 続く節では、それらを探索する方法を説明します。


Node:Syntax of Regexps, Next:, Up:Regular Expressions

正規表現の構文

正規表現では、数個の文字が特別な構成であり、残りは普通です。 普通の文字は、その文字だけに一致する単純な正規表現です。 特別な文字は、.*+?[]^$\であり、 将来新たな文字が定義されることはありません。 正規表現に現れるこれら以外の文字は、 まえに\がない限り普通の文字です。

たとえば、fは特別な文字ではないので普通の文字です。 ですから、fは文字列fだけに一致する正規表現です。 (これは文字列ffには一致しない。) 同様に、ooだけに一致する正規表現です。

任意の2つの正規表現abを連結できます。 その結果は、aが文字列の始めの部分に一致し、かつ、 bがその文字列の残りに一致するときにその文字列に一致する 正規表現になります。

簡単な例として、正規表現 foを連結して 正規表現foを得られます。 これは文字列foだけに一致します。 これは明らかですね。 より強力なことをするには、特別な文字の1つを使う必要があります。 それらの一覧を以下に示します。

. (ピリオド)
特別な文字であり、改行以外の任意の1文字に一致する。 連結を使ってa.bのような正規表現を作れる。 これは、aで始まりbで終る任意の3文字の文字列に一致する。
*
単独では構成要素ではない。 直前の正規表現を可能な限り反復することを意味する後置演算子である。 すなわち、o*は(oが存在しない場合も含めて) 任意個のoに一致する。

*はつねに先行する最小の正規表現に適用される。 したがって、fo*foを繰り返すのではなく、 oを繰り返す。 この正規表現はffofooなどに一致する。

*を用いた構成の一致を処理するときには、 ただちに得られる限りの反復回数に展開される。 そうしてから、残りのパターンを処理する。 一致に失敗するとバックトラック(後戻り)が発生して、 *を用いた構成の反復回数を減らして パターンの残りの部分が一致できるようにする。 たとえば、文字列caaarに対して ca*arを一致させることを考えてみる。 始めに、a*を3つのaすべてに一致させようとする。 しかし、残りのパターンがarなのにrしか残っていないため、 この試みは失敗する。 そこで、つぎはa*a2つだけに一致させる。 こうすると、残りの正規表現も正しく一致する。

入れ子にした反復演算子がバックトラックのループを指定する場合、 それはとても遅くなる。 たとえば、正規表現\(x+y*\)*axxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxzの列に一致させると 最終的に失敗するまで何時間も費してしまう。 遅さの原因は、Emacsは35個のxをグループに分ける各方法を すべて試してからでないとそれらが一致しないことを結論できないからである。 読者の正規表現が素早く動作することを保証するために、 入れ子になった繰り返しを注意深く調べること。

+
*に似た後置演算子だが、 直前の正規表現に1回以上一致する必要がある。 たとえば、ca+rは、文字列carcaaaarには一致するが、 文字列crには一致ない。 一方、ca*rの場合は、上記の3つすべてに一致する。
?
*に似た後置演算子だが、 直前の正規表現に1回だけ一致するか、あるいは、1回も一致しない。 たとえば、ca?rは、carcrに一致するが、 他のものには一致しない。
[ ... ]
[で始まり]で終る文字選択を表す。 もっとも単純な場合は、 この2つの中括弧のあいだにある文字の1つ1つがこの文字選択に一致する。

したがって、[ad]は、a1文字かd1文字のどちらにも一致する。 [ad]*は、adだけから成る (空の文字列を含む)任意の文字列に一致する。 このことから、c[ad]*rは、 crcarcdrcaddaarなどに一致することがわかる。

文字選択には、文字範囲の指定を含めることもでき、 始めの文字と終りの文字のあいだに-を書く。 つまり、[a-z]はすべてのASCII小英文字に一致する。 範囲指定と個々の文字を自由に織り混ぜてよく、 [a-z$%.]のように書ける。 これは、任意のASCII小英文字、$%、ピリオドに一致する。

正規表現[\200-\377]で すべての非ASCII文字につねに一致するとは限らない。 ユニバイト(see Text Representations)のバッファや文字列を 探索するときにはうまく働くが、マルチバイトのバッファや文字列では 多くの非ASCII文字のコードは8進数0377より大きいために働かない。 しかし、正規表現[^\000-\177]は、 ASCII文字のみを除外しているため、 マルチバイト表現でもユニバイト表現でもすべての非ASCII文字に一致する。

範囲指定の始めと終りは同じ文字集合(see Character Sets)に 属している必要がある。 したがって、[a-\x8e0]は正しくない。 aASCII文字集合に属し、 文字0x8e0(グレーブアクセント付きa)は EmacsのLatin-1の文字集合に属しているからである。

正規表現の普通の特別な文字は、文字選択の内側では特別ではないことに注意。 文字選択の内側では、まったく別の文字の集まり、 ]-^が特別である。

文字選択に]を含めるには、 ]を最初の文字として指定する必要がある。 たとえば、[]a]は、]aに一致する。 -を含めるには、-を文字選択の最初の文字か 最後の文字として書くか、範囲指定のあとに置く。 したがって、[]-]は、]-の両方に一致する。

文字選択に^を含めるには、^を文字選択の2番目以降に置く。

[^ ... ]
[^文字選択の補集合の始まりを意味し、 指定した文字を除く任意の文字に一致する。 すなわち、[^a-z0-9A-Z]は、 英文字と数字文字を除くすべての文字に一致する。

^は文字選択の先頭になければ文字選択では特別な意味を持たない。 ^に続く文字は先頭にあるものとして扱われる (いいかえれば、ここでは-]は特別な意味を持たない)。

文字選択の補集合は、一致しない文字として改行を指定しない限り、 改行にも一致する。 この点は、grepのようなプログラムでの正規表現の扱い方と対照的である。

^
空の文字列に一致する特別な文字であり、 一致を取る対象のテキストの行頭のみに一致する。 それ以外では、一致に失敗する。 したがって、^fooは、行頭にあるfooに一致する。

バッファのかわりに文字列と一致を取るときには、 ^は文字列の先頭や改行文字\nのうしろに一致する。

$
^と同様だが行末のみに一致する。 したがって、x+$は、 行末にある1文字以上のxから成る文字列に一致する。

バッファのかわりに文字列と一致を取るときには、 $は文字列の末尾や改行文字\nのまえに一致する。

\
2つの機能がある。 (\を含む)特別な文字をクォートする(意味を抑える)ことと、 特別な構成を導入することである。

\は特別な文字をクォートするので、 \$は文字$だけに一致する正規表現、 \[は文字[だけに一致する正規表現、 といった具合になる。

\にはLisp文字列の入力構文(see String Type)でも 特別な意味があり、\でクォートする必要があることに注意してほしい。 たとえば、文字\に一致する正規表現は\\である。 文字群\\を含むLisp文字列を書くには、各\をクォートするために \が必要である。 したがって、\に一致する正規表現の入力構文は"\\\\"である。

注意: 従来との互換性のために、 特別な文字がそれらの特別な意味をなしえない文脈で使われた場合には、 普通の文字として扱われる。 たとえば、*fooでは、*の対象となる正規表現が直前にないため、 *は普通の文字として扱われる。 このようなふるまいに依存することはよいことではない。 特別な文字は書く位置に関係なくクォートするべきである。

多くの場合、任意の文字を伴う\はその文字だけに一致します。 しかし、いくつか例外があって、 \で始まる2文字列が特別な意味を持つ場合があります。 (2文字目にくる文字は、 単独で使った場合にはつねに普通の文字として扱われる。) 以下に\の構成を示します。

\|
選択肢を指定する。 \|をあいだに伴った2つの正規表現abは、 abのいずれかに一致する文字列に一致する正規表現となる。

したがって、foo\|barは、foobarに一致するが、 それ以外の文字列には一致しない。

\|は、周囲にある適用しうる正規表現の中でも最大のものに適用される。 \|によるグループ化を制限するのは、 これを囲む\( ... \)によるグループ化だけである。

何度\|を使っても処理できるだけの十分なバックトラック能力がある。

\( ... \)
以下の3つの目的を果たすグループ化のための構成。

  1. 他の操作に使うために一連の選択肢\|を括る。 したがって、\(foo\|bar\)xは、 fooxbarxのいずれかに一致する。
  2. 後置演算子、*+?を適用できるように、 複雑な正規表現を括る。 したがって、ba\(na\)*は、 banananaのように、(0個以上の)任意個の 文字列naに一致する。
  3. あとで参照できるように、一致した部分文字列を記録する。

最後の使い方は、括弧によるグループ化という考え方から 派生したものではない。 同一の\( ... \)構成に与えた2つめの別の機能である。 実用上、これら2つの意味が混同されることはないからである。 この機能をつぎに説明する。

\digit
d番目に現れた\( ... \)に一致したテキストと 同じテキストに一致する。

いいかえれば、一致を処理するときには、 \( ... \)構成の末尾に達すると、 この構成に一致したテキストの始めと終りを記録する。 そして、正規表現のそれよりうしろでは、 『d番目に現れた\( ... \)に一致したテキスト』という意味で それがなんであろうと\に続けて数字dを使える。

1つの正規表現内に現れる最初の9個の\( ... \)に一致する文字列には、 正規表現中で開き括弧が現れた順に、1から9までの番号を割り振る。 そのため、\1から\9で、 対応する\( ... \)に一致したテキストを参照できる。

たとえば、\(.*\)\1は、改行を含まない文字列で、かつ、 前半と後半が同一である文字列に一致する。 \(.*\)は前半部分に一致し、それはどのようなものでもかまわない。 一方、それに続く\1は、 前半部分とまったく同じテキストに一致しなければならない。

\w
任意の単語構成文字に一致する。 エディタの構文テーブルによってこの文字が決まる。 see Syntax Tables
\W
単語構成文字以外の文字に一致する。
\scode
構文コードがcodeである文字だけに一致する。 ここで、codeは構文コードを表す文字である。 つまり、wは単語構成要素を、 -は白文字を、(は開き括弧を表すといった具合である。 白文字の構文を表すには、-か空白のいずれかを使う。 構文コードとそれらを表す文字の一覧については、 see Syntax Class Table
\Scode
構文がcodeでない任意の文字に一致する。

つぎの正規表現は空の文字列に一致します。 つまりこれらは文字を使用しませんが、 これらが一致するかどうか文脈に依存します。

\`
空の文字列に一致するが、 一致対象であるバッファや文字列の先頭に限る。
\'
空の文字列に一致するが、 一致対象であるバッファや文字列の末尾に限る。
\=
空の文字列に一致するが、ポイント位置に限る。 (文字列に対する一致ではこの構文は定義されない。)
\b
空の文字列に一致するが、単語の先頭や末尾に限る。 したがって、\bfoo\bは、単語として独立して現れるfooに一致する。 \bballs?\bは、単語として独立して現れる ballballsに一致する。

\bは、 バッファの先頭や末尾にあるテキストとは無関係に、 バッファの先頭や末尾にも一致する。

\B
空の文字列に一致するが、単語の先頭や末尾以外に限る。
\<
空の文字列に一致するが、単語の先頭に限る。 \<はバッファの先頭にも一致するが、単語構成文字が続く場合に限る。
\>
空の文字列に一致するが、単語の末尾に限る。 \>はバッファの末尾にも一致するが、 単語構成文字で終了している場合に限る。

任意の文字列が正しい正規表現ではありません。 たとえば、([]]のような少数の例外を除けば) 角括弧が対応していない文字列は正しくありませんし、 1つの\で終る文字列も正しくありません。 不正な正規表現を探索関数に渡すと、 エラーinvalid-regexpが通知されます。

regexp-quote string Function
この関数は、stringだけに正確に一致する正規表現の文字列を返す。 これにより、正規表現を必要とする関数を呼び出すときに この文字列だけに正確に一致できる。
(regexp-quote "^The cat$")
     => "\\^The cat\\$"

regexp-quoteの用途の1つは、 正規表現で記述された文脈に正確に一致する文字列を組み合わせることである。 たとえば、つぎは、白文字で囲まれたstringの値で表される文字列を探索する。

(re-search-forward
 (concat "\\s-" (regexp-quote string) "\\s-"))

regexp-opt strings &optional paren Function
この関数は、文字列stringsのいずれかに一致する 効率よい正規表現を返す。 これは、たとえばフォントロック(font-lock)モードなどで、 可能な限り高速な一致や探索を行う必要がある場合に有用である。

省略可能な引数parennil以外であると、 返される正規表現はつねに少なくとも1つの括弧によるグループ構文で囲まれる。

つぎのregexp-optの簡略版定義は、 実際の値に等価な(ただしそれほど効率よくない)正規表現を生成する。

(defun regexp-opt (strings paren)
  (let ((open-paren (if paren "\\(" ""))
        (close-paren (if paren "\\)" "")))
    (concat open-paren
            (mapconcat 'regexp-quote strings "\\|")
            close-paren)))

regexp-opt-depth regexp Function
この関数は、varregexp内のグループ化構文(括弧で括った式)の 総個数を返す。


Node:Regexp Example, Previous:Syntax of Regexps, Up:Regular Expressions

複雑な正規表現の例

ここでは、任意個数の白文字を伴った文末を認識するために Emacsで使われている複雑な正規表現について述べます。 それは変数sentence-endの値です。

まず、タブ文字と空白を区別するためにLisp構文の文字列として 正規表現を示します。 文字列定数はダブルクォートで始まり終ります。 \"は文字列の一部としてのダブルクォート、 \\は文字列の一部としてのバックスラッシュ、 \tはタブ、\nは改行を表します。

"[.?!][]\"')}]*\\($\\| $\\|\t\\|  \\)[ \t\n]*"

対照的に、変数sentence-endを評価するとつぎのように なっているはずです。

sentence-end
     => "[.?!][]\"')}]*\\($\\| $\\|  \\|  \\)[
]*"

この出力では、タブと改行はそれ自身として現れています。

この正規表現には、連続してつぎのような4つの部分が含まれています。

[.?!]
パターンの最初の部分は、3つの文字、ピリオド、疑問符、感嘆符の いずれかに一致する文字選択である。 一致部分はこれらの3つの文字の1つで始まる必要がある。
[]\"')}]*
パターンの2番目の部分は、ピリオド、疑問符、感嘆符のいずれかに続く、 任意の閉じ括弧やクォーテーションマークの0個以上の繰り返しに一致する。 \"は、文字列内のダブルクォートを表すLisp構文である。 最後の*は、直前の正規表現(この場合は文字選択)を 0回以上繰り返すことを表す。
\\($\\| $\\|\t\\| \\)
パターンの3番目の部分は、文末に続く白文字、 つまり、(空白を伴うかもしれない)行末、1つのタブ、2つの空白の いずれかに一致する。 2つのバックスラッシュは、括弧や縦棒を正規表現の構文にする。 括弧はグループを区切り、縦棒は選択肢を区切る。 ドル記号は行末に一致するために用いている。
[ \t\n]*
パターンの最後の部分は、 文末に最低限必要な白文字より余計な白文字に一致する。


Node:Regexp Search, Next:, Previous:Regular Expressions, Up:Searching and Matching

正規表現の探索

GNU Emacsでは、正規表現に一致するつぎの部分を インクリメンタルにもそうでなくも探せます。 インクリメンタルサーチコマンドについては、 Regexp Searchを 参照してください。 ここでは、プログラムで有用な探索関数のみについて述べます。 基本的なものはre-search-forwardです。

これらの探索関数は、バッファがマルチバイトであれば 正規表現をマルチバイトに変換します。 バッファがユニバイトであれば、正規表現をユニバイトに変換します。 See Text Representations

re-search-forward regexp &optional limit noerror repeat コマンド
この関数は、カレントバッファにおいて前方へ向けて 正規表現regexpに一致するテキストの文字列を探索する。 関数はregexpに一致しないテキストはすべて飛び越え、 みつけた一致箇所の末尾へポイントを置く。 ポイントの新たな値を返す。

limitnil以外(カレントバッファ内の位置であること)であると、 探索の上限を表す。 その位置を越える箇所での一致は受け入れない。

repeatを指定してあると(正の数であること)、 その回数だけ探索を繰り返す(一致箇所の末尾を新たな探索の開始位置とする)。 連続してこれらの探索に成功すると関数は成功し、 ポイントを移動してその新たな値を返す。 さもなければ探索は失敗である。

関数が失敗した場合の動作は、noerrorの値に依存する。 noerrornilであると、 エラーsearch-failedを通知する。 noerrortであると、 re-search-forwardはなにもせずにnilを返す。 noerrornilでもtでもないと、 re-search-forwardはポイントをlimit(あるいはバッファの末尾)へ 移動してnilを返す。

つぎの例では、ポイントは始めはTのまえにある。 探索を呼び出すと、ポイントは当該行の末尾 (hattと改行のあいだ)へ移動する。

---------- Buffer: foo ----------
I read "-!-The cat in the hat
comes back" twice.
---------- Buffer: foo ----------

(re-search-forward "[a-z]+" nil t 5)
     => 27

---------- Buffer: foo ----------
I read "The cat in the hat-!-
comes back" twice.
---------- Buffer: foo ----------

re-search-backward regexp &optional limit noerror repeat コマンド
この関数は、カレントバッファにおいて後方へ向けて 正規表現regexpに一致するテキストの文字列を探索し、 みつけた一致箇所の先頭へポイントを置く。

この関数はre-search-forwardに類似したものであるが、 単純な鏡像ではない。 re-search-forwardは、一致箇所の先頭が 開始位置に可能な限り近い一致箇所を探す。 re-search-backwardが完全な鏡像であれば、 一致箇所の末尾が可能な限り近い一致箇所を探す。 しかし、実際には、一致箇所の先頭が可能な限り近い一致箇所を探す。 これは、正規表現との一致をとる処理は、 指定開始位置において先頭から末尾へ向けてつねに行われるからである。

re-search-forwardの完全な鏡像には、 正規表現の一致を末尾から先頭へ向けて行う特別な機能が必要である。 それを実装する手間をかけるほどの価値はない。

string-match regexp string &optional start Function
この関数は、文字列stringにおいて正規表現regexpに一致した 最初の箇所の添字を返す。 あるいは、一致がなければnilを返す。 startnil以外であると、 stringの指定した添字から探索を始める。

たとえばつぎのとおりである。

(string-match
 "quick" "The quick brown fox jumped quickly.")
     => 4
(string-match
 "quick" "The quick brown fox jumped quickly." 8)
     => 27

文字列の最初の文字の添字は0であり、 2番目の文字の添字は1であるといった具合になる。

この関数から戻ったあとでは、 一致箇所を越えた最初の文字の添字は(match-end 0)で得られる。 see Match Data

(string-match
 "quick" "The quick brown fox jumped quickly." 8)
     => 27

(match-end 0)
     => 32

looking-at regexp Function
この関数は、カレントバッファ内のポイントの直後のテキストが 正規表現regexpに一致するかどうかを調べる。 ここで『直後』とは、開始位置は固定されていて、 ポイントのうしろの最初の文字で始まる場合にのみ探索は成功する。 結果は、一致すればtであり、さもなければnilである。

この関数はポイントを移動しないが、マッチデータを更新する。 match-beginningmatch-endを使ってマッチデータを参照できる。

つぎの例では、ポイントはTの直前にある。 ポイントがこれ以外の場所にあると結果はnilになる。

---------- Buffer: foo ----------
I read "-!-The cat in the hat
comes back" twice.
---------- Buffer: foo ----------

(looking-at "The cat in the hat$")
     => t


Node:POSIX Regexps, Next:, Previous:Regexp Search, Up:Searching and Matching

POSIXの正規表現探索

普通の正規表現関数は、\|や反復構文を扱うために必要なときには バックトラックしますが、これを行い続けるのは なんらかの一致をみつけるまでです。 みつけてしまえば、それらは成功してみつけた最初の一致を報告します。

本節では、正規表現の一致に関するPOSIX規格で規定された 完全なバックトラックを行う代替の探索関数について述べます。 それらはすべての可能性を試し尽くしすべての一致箇所を探し終える までバックトラックを継続してます。 そのため、POSIXで要求されるとおりの最長の一致を報告できるのです。 これは動作がとても遅いですから、最長一致が本当に必要な場合に限って これらの関数を使ってください。

posix-search-forward regexp &optional limit noerror repeat Function
これはre-search-forwardと同様であるが、 正規表現の一致に関するPOSIX規格で規定された完全なバックトラックを行う。

posix-search-backward regexp &optional limit noerror repeat Function
これはre-search-backwardと同様であるが、 正規表現の一致に関するPOSIX規格で規定された完全なバックトラックを行う。

posix-looking-at regexp Function
これはlooking-atと同様であるが、 正規表現の一致に関するPOSIX規格で規定された完全なバックトラックを行う。

posix-string-match regexp string &optional start Function
これはstring-matchと同様であるが、 正規表現の一致に関するPOSIX規格で規定された完全なバックトラックを行う。


Node:Search and Replace, Next:, Previous:POSIX Regexps, Up:Searching and Matching

探索と置換

perform-replace from-string replacements query-flag regexp-flag delimited-flag &optional repeat-count map Function
この関数は、query-replaceと関連するコマンドの中身である。 from-stringの出現を探しだし、それらの一部やすべてを置き換える。 query-flagnilであると、すべての出現を置換する。 さもなければ、1つ1つユーザーにどうするかを問い合わせる。

regexp-flagnil以外であると、 from-stringを正規表現として扱う。 さもなければ、その字面とおりに一致する。 delimited-flagnil以外であると、 単語区切りで囲まれたもののみを対象にする。

引数replacementsは、出現を置き換えるものを指定する。 それが文字列であれば、その文字列を使う。 文字列のリストでもよく、要素を巡回して使う。

repeat-countnil以外であれば、整数であること。 これは、replacementsのリスト内の各文字列を つぎに進めるまえに何回使用するかを指定する。

通常、キーマップquery-replace-mapで、 可能なユーザーの応答を定義する。 引数mapnil以外であれば、 query-replace-mapのかわりに使うキーマップである。

query-replace-map Variable
この変数は、y-or-n-pmap-y-or-n-pに加えて、 query-replaceや関連する関数に対する 正しいユーザー応答を定義する特別なキーマップを保持する。 2つの意味で普通のものではない。
  • 『キーバインディング』はコマンドではなく、 このキーマップを用いる関数にのみ意味がある単なるシンボルである。
  • プレフィックスキーは扱えない。 各キーバインディングは単一イベントのキー列である必要がある。 これは、関数では入力を得るためにread-key-sequenceを使わずに、 『自前』でイベントを読み取り探索するからである。

query-replace-map向けの意味のある『バインディング』をつぎに示します。 query-replaceと関連するものだけに意味のあるものもあります。

act
当該動作を行う、いいかえれば『yes』。
skip
この問いに対する動作は行わない、いいかえれば『no』。
exit
この問いには『no』で答え、 残りの応答も『no』と仮定して一連の問いを止める。
act-and-exit
この問いには『yes』で答え、 残りの応答は『no』と仮定して一連の問いを止める。
act-and-show
この問いには『yes』で答えるが、結果を表示する。 つぎの問いへは進まない。
automatic
この問いと以降の一連の問いに『yes』で答え、 これ以降ユーザーに問い合わせない。
backup
問いに答えたまえの箇所へ戻る。
edit
この問いに対処するために、通常の動作のかわりに再帰編集に入る。
delete-and-edit
対象のテキストを削除してから、 それを置き換えるために再帰編集に入る。
recenter
ウィンドウの中央に位置決めして再表示してから、 同じ問いを問い直す。
quit
ただちに中断する。 y-or-n-pと関連する関数でのみ、この応答を用いる。
help
ヘルプを表示してから、再度問い直す。


Node:Match Data, Next:, Previous:Search and Replace, Up:Searching and Matching

マッチデータ

Emacsは、正規表現の探索中に捜し出したテキスト断片の開始/終了位置を 記録しています。 つまり、たとえば、rmailメッセージ内で日付のような複雑なパターンを 探索してから、パターンの制御をもとに一致した一部分を取り出せるのです。

マッチデータは、通常、もっとも最近に行った探索のみを記述するので、 あとで使用したい探索とそのマッチデータを使うあいだに、 不注意に別の探索を行わないように注意してください。 あいだで探索を行う必要がある場合には、その周りで マッチデータを保存/復元してそれらが上書きされないようにします。


Node:Replacing Match, Next:, Up:Match Data

一致したテキストの置換

この関数は、最後の探索で一致したテキストをreplacementで置換します。

replace-match replacement &optional fixedcase literal string subexp Function
この関数は、最後の探索で一致したバッファ内(あるいは文字列string)の テキストを置換する。 当該テキストをreplacementで置き換える。

バッファで最後に探索を行った場合には、 stringnilを指定すること。 そうすると、replace-matchはバッファを編集することで置換を行い、 置換したテキストの末尾にポイントを置きtを返す。

文字列で探索した場合には、stringに同じ文字列を渡すこと。 そうすると、replace-matchは新たな文字列を構築することで 置換を行い、新たな文字列を返す。

fixedcasenil以外であると、 置換テキストの大文字小文字は変更しない。 さもなければ、置換テキストの大文字小文字は、 対象テキストの大文字小文字に応じて変換される。 元テキストがすべて大文字であると、置換テキストも大文字に変換される。 元テキストの最初の単語が大文字で始まっていると、 置換テキストの最初の単語も大文字で始める。 元テキストが1単語のみであり、しかも、その単語が大文字1文字であると、 replace-matchはすべてが大文字ではなく大文字で始まるとみなす。

case-replacenilであると、 fixed-caseの値に関わらず、大文字小文字変換を行わない。 see Searching and Case

literalnil以外であると、 必要に応じて大文字小文字変換は行うものの replacementをそのまま挿入する。 それがnil(デフォルト)であると、 文字\を特別に扱う。 replacement\が現れるときには、 つぎの列のいずれかであること。

\&
\&は置換対象のテキスト全体を表す。
\n
nを数字文字とすると\nは、 もとの正規表現内のn番目の部分式に一致したテキストを表す。 部分式とは、\(...\)で囲んでグループ化した式である。
\\
\\は置換テキスト内で1つの\を表す。

subexpnil以外であると、 一致箇所全体ではなく正規表現のsubexp番目の部分式に 一致した箇所のみを置換することを指示する。 たとえば、foo \(ba*r\)に一致させたあとで、 subexpに1を指定してreplace-matchを呼び出すと、 \(ba*r\)に一致したテキストのみを置換することを意味する。


Node:Simple Match Data, Next:, Previous:Replacing Match, Up:Match Data

マッチデータの簡単な参照

本節では、最後の探索や一致操作において なにに一致したのかを調べるためのマッチデータの使い方を説明します。

一致したテキスト全体や正規表現の括弧で括った特定の部分式に一致した テキストを調べることができます。 以下の関数の引数countでどれかを指定します。 countがゼロであれば、一致全体を調べることになります。 countが正であれば、望みの部分式を指定します。

正規表現の部分式は、エスケープした括弧\(...\)でグループ化した 式であることに注意してください。 count番目の部分式は、正規表現全体の先頭から \(の出現を数えてみつけます。 最初の部分式は1、つぎは2、といった具合です。 部分式は正規表現だけにあります。 単純な文字列探索のあとでは、利用可能な情報は一致全体に関するものだけです。

探索に失敗すると、マッチデータを変更することもしないこともあります。 過去には探索に失敗しても変更しなかったのですが、 将来そうなります。

match-string count &optional in-string Function
この関数は、最後の探索や一致操作で一致したテキストを文字列として返す。 countがゼロであるとテキスト全体を返す。 countが正であれば、count番目の括弧で囲んだ部分式に対応する 部分のみを返す。 countが範囲を越えていたり、当該部分式に一致するものがない場合には、 値はnilである。

最後の探索や一致操作をstring-matchで文字列に対して行った場合には、 引数in-stringとして同じ文字列を渡すこと。 バッファの探索や一致のあとでは、in-stringを省略するか nilを渡すこと。 ただし、match-stringを呼び出すときのカレントバッファが 探索を行ったときのバッファであること。

match-string-no-properties count Function
この関数はmatch-stringと同様であるが、 結果にはテキスト属性を含まない。

match-beginning count Function
この関数は、最後の正規表現探索やその部分式に一致したテキストの開始位置を返す。

countがゼロであると、値は一致全体の開始位置である。 さもなければ、countは正規表現内の部分式を指定し、 関数の値は当該部分式に一致した部分の開始位置である。

一致に利用されなかった選択肢\|内の部分式に対しては、 値はnilである。

match-end count Function
この関数はmatch-beginningと同様であるが、 一致箇所の開始位置ではなく終了位置を返す点が異なる。

コメントでテキスト内の位置を示しながら マッチデータの利用例を示します。

(string-match "\\(qu\\)\\(ick\\)"
              "The quick fox jumped quickly.")
              ;0123456789
     => 4

(match-string 0 "The quick fox jumped quickly.")
     => "quick"
(match-string 1 "The quick fox jumped quickly.")
     => "qu"
(match-string 2 "The quick fox jumped quickly.")
     => "ick"

(match-beginning 1)       ; 一致箇所quの先頭は
     => 4                 ;   添字4

(match-beginning 2)       ; 一致箇所ickの先頭は
     => 6                 ;   添字6

(match-end 1)             ; 一致箇所quの末尾は
     => 6                 ;   添字6

(match-end 2)             ; 一致箇所ickの末尾は
     => 9                 ;   添字9

別の例も示します。 ポイントは始めは行頭にあります。 探索によって、ポイントは空白と単語inのあいだに移動します。 一致箇所全体の先頭はバッファの9番目の文字(T)であり、 最初の部分式の一致箇所の先頭は13番目の文字(c)です。

(list
  (re-search-forward "The \\(cat \\)")
  (match-beginning 0)
  (match-beginning 1))
    => (9 9 13)

---------- Buffer: foo ----------
I read "The cat -!-in the hat comes back" twice.
        ^   ^
        9  13
---------- Buffer: foo ----------

(この例では、返される添字はバッファ内位置であり、 バッファの最初の文字を1と数える。)


Node:Entire Match Data, Next:, Previous:Simple Match Data, Up:Match Data

マッチデータ全体を参照する

関数match-dataset-match-dataは、 マッチデータ全体を一度に読んだり書いたりします。

match-data Function
この関数は、最後の探索で一致したテキストに関するすべての情報を収めた 新たに構築したリストを返す。 要素0が式全体に一致した部分の先頭位置であり、 要素1が式全体に一致した部分の終了位置である。 つぎの2つの要素は最初の部分式に一致した部分の先頭/終了位置、 といった具合である。 一般に、要素 は(match-beginning n)に対応し、 要素 は(match-end n)に対応する。

バッファで行った一致ではすべての要素はマーカかnilであり、 string-matchにより文字列で行った一致では すべての要素は整数かnilである。

探索関数の呼び出しとその探索結果としてのマッチデータを参照するための match-dataの呼び出しのあいだには、 別の探索があってはならない。

(match-data)
     =>  (#<marker at 9 in foo>
          #<marker at 17 in foo>
          #<marker at 13 in foo>
          #<marker at 17 in foo>)

set-match-data match-list Function
この関数は、match-listの要素からマッチデータを設定する。 match-listは、以前にmatch-dataの呼び出しで得たリストであること。

match-listが存在しないバッファを指していても、エラーにはならない。 無意味な情報をマッチデータに設定するが、害にはならない。

store-match-dataはほぼ廃れているset-match-dataの別名である。


Node:Saving Match Data, Previous:Entire Match Data, Up:Match Data

マッチデータの保存と復元

探索を行う可能性がある関数を呼び出す場合、 あとで使うためにそれ以前の探索によるマッチデータを保存したいときには、 当該関数の呼び出しの周りでマッチデータを保存し復元する必要があります。 つぎの例は、マッチデータを保存し損なった場合に生じる問題点を 示しています。

(re-search-forward "The \\(cat \\)")
     => 48
(foo)                   ; fooはさらに
                        ;   探索する
(match-end 0)
     => 61              ; 予期しない結果。48でない!

マッチデータの保存と復元はsave-match-dataで行えます。

save-match-data body... Macro
このマクロは、周りのマッチデータを保存し復元して、 bodyを実行する。

スペシャルフォームsave-match-dataの効果をまねるために match-dataとともにset-match-dataを使うこともできます。 つぎのようにします。

(let ((data (match-data)))
  (unwind-protect
      ...   ; もとのマッチデータを変更しても大丈夫
    (set-match-data data)))

プロセスフィルタ関数(see Filter Functions)や プロセスの番兵(see Sentinels)を実行するときには、 Emacsは自動的にマッチデータを保存し復元します。


Node:Searching and Case, Next:, Previous:Match Data, Up:Searching and Matching

探索と大文字小文字

デフォルトでは、Emacsの探索は探索対象テキストの大文字小文字を区別しません。 FOOを探す指定を行うと、 Foofooにも一致するとみなします。 これは、正規表現にも適用されます。 したがって、[aB]は、aAbBに一致します。

この機能を望まないときには、 変数case-fold-searchnilを設定します。 すると、すべての文字は大文字小文字を保ってそのとおりに一致します。 これはバッファローカルな変数ですから、 変数を変更してもカレントバッファだけに影響します。 (see Intro to Buffer-Local。) あるいは、default-case-fold-searchの値を変更します。 これは、case-fold-searchを書き変えていないバッファ向けの デフォルト値です。

ユーザーレベルのインクリメンタルサーチ機能では、 大文字小文字の区別は異なった扱い方をします。 小英文字を与えるとその大文字にも一致しますが、 大英文字を与えると大文字のみに一致します。 しかし、これはLispコードで使用している探索関数には まったく関係ありません。

case-replace User Option
この変数は、置換関数が大文字小文字を保存するかどうかを決定する。 変数がnilであると、置換テキストをそのまま使うことを意味する。 nil以外の値であると、置換対象のテキストに応じて 置換テキストの大文字小文字を変換することを意味する。

この変数が実際に効果を発揮するのは関数replace-matchにおいてである。 see Replacing Match

case-fold-search User Option
このバッファローカルな変数は、 大文字小文字を区別して探索するかどうかを決定する。 変数がnilであると大文字小文字を区別する。 さもなければ大文字小文字を区別しない。

default-case-fold-search Variable
この変数の値は、case-fold-searchを書き変えていないバッファ向けの デフォルト値である。 これは(default-value 'case-fold-search)と同じである。


Node:Standard Regexps, Previous:Searching and Case, Up:Searching and Matching

編集に用いられる標準的な正規表現

本節では、編集上の特定目的に用いられる正規表現を保持している 変数について述べます。

page-delimiter Variable
これは、ページを区切る行頭を記述した正規表現である。 デフォルト値は、"^\014"(つまり、"^^L"すなわち"^\C-l") である。 これはページ送り文字で始まる行に一致する。

つぎの2つの正規表現は、つねに行の先頭から一致が 始まると仮定してはいけません。 一致の開始位置を固定する^を使うべきではありません。 ほとんどの場合、段落コマンドは行の先頭でのみ一致を検査しますから、 ^は不必要であることを意味します。 幅0以外の左端余白があると、段落コマンドは左端余白のうしろからの一致を 受け入れます。 そのような場合、^は誤りです。 しかし、左端余白をけっして使わないモードならば、 ^は無害です。

paragraph-separate Variable
これは、段落を区切る行の始まりを認識するための正規表現である。 (これを変更したら、paragraph-startも変更すること。) デフォルト値は"[ \t\f]*$"であり、 (左端余白に続く)空白やタブやページ送りだけから成る行に一致する。

paragraph-start Variable
これは、段落を始める行や区切る行の始まりを認識するための正規表現である。 デフォルト値は"[ \t\n\f]"であり、 (左端余白に続く)空白やタブやページ送りだけから成る行に一致する。

sentence-end Variable
これは、文末を記述する正規表現である。 (これに関わらず、段落の区切りも文末である。) デフォルト値はつぎのとおりである。
"[.?!][]\"')}]*\\($\\| $\\|\t\\| \\)[ \t\n]*"

これは、ピリオド、疑問符、感嘆符のいずれかのあとに 閉じ括弧文字が続き(なくてもよい)、 タブや空白や改行が続くことを意味する。

この正規表現の詳しい説明は、Regexp Exampleを参照。


Node:Syntax Tables, Next:, Previous:Searching and Matching, Up:Top

構文テーブル

構文テーブル(syntax table)は、 各文字の構文的なテキスト上の機能を指定します。 この情報は、構文解析関数や複雑な移動を行うコマンドなどが 単語やシンボルなどの構文要素がどこで始まりどこで終るかを調べるために使います。 現在の構文テーブルが、本章の関数に加えて、 単語単位の移動関数(see Word Motion)、 リスト単位の移動関数(see List Motion)の意味を制御します。


Node:Syntax Basics, Next:, Up:Syntax Tables

構文テーブルの概念

構文テーブルは文字テーブル(see Char-Tables)です。 cで添字付けられる要素は、コードがcである文字について記述します。 要素の値は、当該文字の構文上の機能を符号化したリストです。

構文テーブルは、テキスト内を動き回るためにのみ使われ、 EmacsのLispリーダはこれを使いません。 Emacs LispがLisp式を読むときには、組み込みの構文規則を使います。 (入力構文を再定義する方法を与えるLispシステムもあるが、 単純であるようにEacs Lispではこの機能を省くことにした。)

各バッファには独自のメジャーモードがあり、 各メジャーモードはさまざまな文字の構文クラスを独自に扱います。 たとえば、lispモードでは文字;はコメントを始めますが、 Cモードでは文を終らせます。 このような多様性を扱うために、 Emacsは各バッファごとにローカルな構文テーブルを選びます。 典型的には、各メジャーモードに独自の構文テーブルがあり、 そのモードを使っているバッファに当該構文テーブルをインストールします。 この構文テーブルを変更すると、 同じモードのバッファだけでなく将来そのモードになったバッファでも 構文を変更してしまいます。 類似したモードでは1つの構文テーブルを共有することがあります。 構文テーブルの設定方法の例については、See Example Major Modes

構文テーブルでは、標準の構文テーブルから文字のデータを継承し、 一方でその他の文字に独自の指定を行えます。 構文クラスの『継承』とは、 『標準の構文テーブルから当該文字の構文を引き継ぐ』ことです。 ある文字に対して標準の構文を変更すると、 それを継承するすべての構文テーブルに影響します。

syntax-table-p object Function
この関数は、objectが構文テーブルならばtを返す。


Node:Syntax Descriptors, Next:, Previous:Syntax Basics, Up:Syntax Tables

構文記述子

本節では、文字の構文を指定する構文クラスと構文フラグ、 それらを構文記述子(syntax descriptor)としてどのように 表現するかについて述べます。 構文記述子はLisp文字列であり、 望みの構文を指定するためにmodify-syntax-entryに渡します。

構文テーブルは、各文字の構文クラスを指定します。 ある構文テーブルでの文字のクラスと 他の構文テーブルでの当該文字のクラスとのあいだにはなんの関係も必要ありません。

各クラスはニーモニック文字(指定子)で区別します。 ニーモニック文字は、 クラスを指定する必要があるときにクラス名として働きます。 通常、指定子の文字は当該クラスによく現れるものです。 しかしながら、指定子としての意味は不変で、その文字の現在の構文とは独立です。

構文記述子は、構文クラス、(括弧のクラスの場合にのみ使われる) 釣り合う文字、フラグを指定するLisp文字列です。 最初の文字は、構文クラスを指定する文字(指定子)です。 2番目の文字はその文字に釣り合う文字ですが、使用しない場合には空白です。 そのあとに望みのフラグが続きます。 釣り合う文字やフラグが必要なければ、文字1つだけで十分です。

たとえば、Cモードにおける文字*の構文記述子は . 23(句読点、釣り合う文字なし、 コメント開始の2番目の文字、コメント終了の最初の文字)であり、 /. 14(句読点、釣り合う文字なし、 コメント開始の最初の文字、コメント終了の2番目の文字)です。


Node:Syntax Class Table, Next:, Up:Syntax Descriptors

構文クラス一覧

以下の一覧は、構文クラス、そのクラスを表す文字(指定子)、 そのクラスの意味、その使用例です。

@w{白文字(whitespace character)} 構文クラス
白文字 -で指定)は、 シンボルや単語を互いに区切る。 典型的には、白文字には他の構文上の意味はなく、 複数個の白文字は1つの白文字と構文的には等価である。 ほとんどすべてのメジャーモードでは、 空白、タブ、改行、ページ送りは白文字である。

@w{単語構成文字(word constituent)} 構文クラス
単語構成文字wで指定)は普通の英単語の一部分であり、 典型的には、プログラムの変数やコマンド名に使われる。 すべての大英文字、小英文字、数字文字は、典型的には単語構成文字である。

@w{シンボル構成文字(symbol constituent)} 構文クラス
シンボル構成文字_で指定)は、 単語構成文字に加えて、変数やコマンド名に使われる追加の文字である。 たとえば、英単語の一部分ではないがシンボル名に使える特定の文字を指定 するために、Lispモードではシンボル構成文字クラスを使う。 このような文字は$&*+-_<>である。 標準のCでは、単語構成文字でなくてシンボルに使える唯一の文字は 下線(_)である。

@w{句読点文字(punctuation character)} 構文クラス
句読点文字.で指定)は、 英文の句読点として使われたり、 プログラム言語でシンボルを区切るために使われる文字である。 emacs-lispモードを含むほとんどのプログラム言語向けモードでは、 シンボル構成文字でも単語構成文字でもない少数の文字には別の用途があるため、 このクラスの文字はない。

@w{開き括弧文字(open parenthesis character)} 構文クラス
@w{閉じ括弧文字(close parenthesis character)} 構文クラス
開き/閉じ括弧文字は、文や式を囲む相異なる対として使われる文字である。 そのようなグループ化は、開き括弧文字で始まり閉じ括弧文字で終る。 各開き括弧文字は特定の閉じ括弧文字に対応し、その逆もいえる。 Emacsは、通常、閉じ括弧文字を挿入すると 対応する開き括弧文字を短時間指し示す。 see Blinking

開き括弧文字クラスは(で指定し、 閉じ括弧文字クラスは)で指定する。

英文向けのテキスト(text)モードとCモードでは、 括弧の対は、()[]{}である。 Emacs Lispでは、リストとベクトルの区切り(()[])は、 括弧文字としてクラス分けされる。

@w{文字列クォート(string quote)} 構文クラス
文字列クォート文字"で指定)は、 LispやCを含む多くの言語で文字列定数を区切るために使われる。 同じ文字列クォート文字が文字列の最初と最後に現れる。

Emacsの構文解析機能では、文字列を1つの字句とみなす。 文字列内の文字の普通の構文的な意味は抑制される。

lisp向けのモードには文字列クォート文字が2つ、 ダブルクォート(")と縦棒(|)がある。 |はEmacs Lispでは使わないがCommon Lispで使う。 Cにも2つの文字列クォート文字、 文字列用のダブルクォートと文字定数用のシングルクォート(')がある。

英文はプログラム言語ではないので、英文には文字列クォート文字はない。 英文でも引用符は用いるが、その内側の文字の普通の構文的な属性を 抑制したくないのである。

@w{エスケープ(escape)} 構文クラス
エスケープ文字\で指定)は、 Cの文字列や文字定数で使われるようなエスケープシーケンスを開始する。 CとLispでは、文字\はこのクラスに属する。 (Cではこの文字は文字列の内側だけで使われるが、 Cモードでつねにこのように扱っても問題ないことがわかった。)

words-include-escapesnil以外であると、 このクラスの文字は単語の一部分と解釈される。 see Word Motion

@w{文字クォート(character quote)} 構文クラス
文字クォート文字/で指定)は、 後続の1文字をクォートし、通常の構文上の意味を抑制する。 直後の1文字のみに影響するという点で、エスケープ文字と異なる。

words-include-escapesnil以外であると、 このクラスの文字は単語の一部分と解釈される。 see Word Motion

このクラスは、TeXモードのバックスラッシュに使われる。

@w{対になった区切り(paired delimiter)} 構文クラス
対になった区切り文字$)は文字列クォート文字と同様であるが、 区切り文字のあいだにある文字の構文上の属性を抑制しない点が異なる。 現在、対になった区切りはTeXモードのみで使い、 数学モードに出入りする$である。

@w{式前置子(expression prefix)} 構文クラス
式前置演算子')は、式のまえに現れると 式の一部であるとみなされる構文上の演算子に使われる。 lisp向けのモードでは、(クォートする)アポストロフ'、 (マクロで使う)コンマ,、 (ある種のデータの入力構文に使われる)#の文字がそうである。

@w{コメント開始(comment starter)} 構文クラス
@w{コメント終了(comment ender)} 構文クラス
コメント開始文字とコメント終了文字は、 さまざまな言語でコメントを区切るために用いられる。 これらのクラスは、それぞれ、<>で指定する。

英文にはコメント文字はない。 Lispでは、セミコロン(;)でコメントが始まり、 改行かページ送りで終る。

@w{継承(inherit)} 構文クラス
この構文クラスは特定の構文を指定しない。 標準の構文テーブルで当該文字の構文を探す指定である。 この構文クラスは@で指定する。

@w{汎用コメント区切り(generic comment delimiter)} 構文クラス
汎用コメント区切り文字は、特別な種類のコメントを 始めて終える文字である。 任意の汎用コメント区切り文字は 任意の汎用コメント区切り文字に対応するが、 普通のコメント開始文字/コメント終了文字には対応しない。 汎用コメント区切り文字同士のみで対応する。

この構文クラスは、主にテキスト属性syntax-table (see Syntax Properties)で使うことを意図したものである。 任意の範囲の文字がコメントを形成すると印を付けるには、 その範囲の先頭と末尾の文字にそれらが汎用コメント区切りであることを 識別する属性syntax-tableを与える。

@w{汎用文字列区切り(generic string delimiter)} 構文クラス
汎用文字列区切り文字は、文字列を始めて終える。 このクラスは文字列クォートクラスと異なり、 汎用文字列区切りは他の汎用文字列区切りに対応し、 普通の文字列クォート文字には対応しない。

この構文クラスは、主にテキスト属性syntax-table (see Syntax Properties)で使うことを意図したものである。 任意の範囲の文字が文字列定数を形成すると印を付けるには、 その範囲の先頭と末尾の文字にそれらが汎用文字列区切りであることを 識別する属性syntax-tableを与える。


Node:Syntax Flags, Previous:Syntax Class Table, Up:Syntax Descriptors

構文フラグ

構文テーブルの各文字には、構文クラスに加えて、フラグも指定できます。 文字1234bpで 表現される6つの可能なフラグがあります。

pを除くすべてのフラグは、複数の文字から成るコメント区切りの記述に 使います。 数字フラグは、当該文字のクラスで表される構文上の属性に加えて、 コメント列の一部分でもあることを示します。 フラグはクラスや他のフラグとは独立であり、 Cモードの*のような文字のためにあります。 Cモードの*は、句読点文字であるとともに、 コメント開始列の2番目の文字/*でもあり、 コメント終了列の最初の文字*/でもあります。

文字cに対して可能なフラグとそれらの意味を以下に示します。


Node:Syntax Table Functions, Next:, Previous:Syntax Descriptors, Up:Syntax Tables

構文テーブル向け関数

本節では、構文テーブルを作成/参照/変更するための関数について述べます。

make-syntax-table Function
この関数は、新たな構文テーブルを作成する。 英文字やコントロール文字の構文は標準の構文テーブルから継承する。 他の文字の構文は標準の構文テーブルからコピーする。

ほとんどのメジャーモードの構文テーブルはこのように作成する。

copy-syntax-table &optional table Function
この関数は、構文テーブルtableのコピーを作成しそれを返す。 tableを指定しないと(あるいはnil)、 現在の構文テーブルのコピーを返す。 tableが構文テーブルでないとエラーを通知する。

modify-syntax-entry char syntax-descriptor &optional table コマンド
この関数は、文字charの構文指定を 構文記述子syntax-descriptorとする。 構文テーブルtableにおいてのみ構文を変更し、 他の構文テーブルは変更しない。 tableのデフォルトはカレントバッファの構文テーブルである。 syntax-descriptorで望みの構文を指定する。 これは、クラス指定子で始まり、 必要に応じて釣り合う文字とフラグを含む文字列である。 see Syntax Descriptors

この関数はつねにnilを返す。 当該構文テーブルにおけるこの文字に対する古い構文情報は破棄される。

構文記述子の最初の文字が12個の構文クラス指定子の1つでないとエラーを通知する。 charが文字でなくてもエラーを通知する。


【例】
;; 空白文字をクラス白文字にする (modify-syntax-entry ?\ " ") => nil ;; $を開き括弧文字にする ;; 対応する閉じる文字は^である (modify-syntax-entry ?$ "(^") => nil ;; ^を閉じ括弧文字にする ;; 対応する開く文字は$である (modify-syntax-entry ?^ ")$") => nil ;; /を句読点文字にする ;; コメント開始列の最初の文字、および、 ;; コメント終了列の2番目の文字にもする ;; これはCモードで用いられる (modify-syntax-entry ?/ ". 14") => nil

char-syntax character Function
この関数は、文字characterの構文クラスを指定子で表したもので返す。 これは構文クラスのみを返し、釣り合う文字や構文フラグは返さない。

charが文字でないとエラーを通知する。

つぎの例はCモードにあてはまる。 最初の例は、空白の構文クラスが(空白で表現される)白文字であることを示す。 2番目の例は、/の構文が句読点であることを示す。 これは、この文字がコメント開始/終了の一部分でもあることは示さない。 3番目の例は、開き括弧は開き括弧クラスであることを示す。 これは、この文字に釣り合う文字が)であることは示さない。

(string (char-syntax ?\ ))
     => " "

(string (char-syntax ?/))
     => "."

(string (char-syntax ?\())
     => "("

ここでは、char-syntaxが返す文字を 見やすくするためにstringを用いた。

set-syntax-table table Function
この関数は、tableをカレントバッファの構文テーブルにする。 tableを返す。

syntax-table Function
この関数は、現在の構文テーブル、つまり、 カレントバッファの構文テーブルを返す。


Node:Syntax Properties, Next:, Previous:Syntax Table Functions, Up:Syntax Tables

構文属性

言語の構文を指定するに十分なほど構文テーブルに柔軟性がないときには、 バッファ内の特定の文字の出現に対して構文テーブルに優先する テキスト属性syntax-tableを指定できます。 See Text Properties

テキスト属性syntax-tableの正しい値はつぎのとおりです。

syntax-table
属性値が構文テーブルであると、 文字のこの出現に対する構文を判定するために カレントバッファの構文テーブルのかわりにこのテーブルを用いる。
(syntax-code . matching-char)
この形のコンスセルは、文字のこの出現の構文を指定する。
nil
属性がnilであると、通常どおり、 現在の構文テーブルから文字の構文を判定する。

parse-sexp-lookup-properties Variable
これがnil以外であると、 構文を解析する関数は、テキスト属性による構文指定に注意を払う。 さもなければ、現在の構文テーブルのみを用いる。


Node:Motion and Syntax, Next:, Previous:Syntax Properties, Up:Syntax Tables

移動と構文

本節では、特定の構文クラスを持つ文字を越えて移動するための 関数について述べます。

skip-syntax-forward syntaxes &optional limit Function
この関数は、syntaxesで指定される構文クラスを持つ文字を越えて ポイントを前方へ向けて移動する。 バッファの末尾、(指定されていれば)limitの位置、 飛び越さない文字のいずれかに出会うと停止する。 戻り値は移動距離であり非負整数である。

skip-syntax-backward syntaxes &optional limit Function
この関数は、syntaxesで指定される構文クラスである文字を越えて ポイントを後方へ向けて移動する。 バッファの先頭、(指定されていれば)limitの位置、 飛び越さない文字のいずれかに出会うと停止する。

戻り値は移動距離である。 それはゼロか負の整数である。

backward-prefix-chars Function
この関数は、式前置子構文の文字を飛び越えてポイントを後方へ向けて移動する。 式前置子クラスやフラグpを持つ文字を飛び越す。


Node:Parsing Expressions, Next:, Previous:Motion and Syntax, Up:Syntax Tables

釣り合った式の解析

ここでは、括弧が対になっているS式(sexp)とも呼ばれる 釣り合った式を解析したり走査する関数について述べます。 構文テーブルで文字の解釈を制御することで、 LispモードではLispの式に対して、CモードではCの式に対して これらの関数を用いることができます。 釣り合った式を飛び越えて移動するための便利な上位レベルの関数については、 See List Motion

parse-partial-sexp start limit &optional target-depth stop-before state stop-comment Function
この関数は、カレントバッファのstartから始まるS式を解析するが、 limitを越えては走査しない。 位置limitで止まるか、 以下に述べる条件が満たされると解析を停止し、当該箇所にポイントを置く。 ポイントを置いた箇所での解析状況を表す値を返す。

statenilであると、 位置startは、関数定義の先頭のような 括弧の構造のトップレベルであると仮定する。 あるいは、構造の途中から解析を再開したい場合もある。 それには、解析の初期状態を引数stateに指定する必要がある。

3番目の引数target-depthnil以外であると、 括弧の深さがtarget-depthに等しくなると解析を停止する。 深さは0、あるいは、stateで指定された値から始まる。

4番目の引数stop-beforenil以外であると、 S式を始める文字に出会うと解析を停止する。 stop-commentnil以外であると、 コメントの始まりに出会うと解析を停止する。 stop-commentがシンボルsyntax-tableであると、 コメントや文字列の始まり、コメントや文字列の終りのいずれかに 出会ったあとで解析を停止する。

5番目の引数stateは9要素のリストであり、 以下に述べるようにこの関数の値と同じ形である。 (9番目の最後の要素は省いてもよい。) parse-partial-sexpの呼び出しの戻り値を、 別のparse-partial-sexpの呼び出しの解析状態の初期値に使ってよい。

結果は、解析の最終状態を記述した9要素のリストである。

  1. 0から数えた括弧の深さ。
  2. ポイントを停止した箇所を含むもっとも内側の括弧式の開始位置。 なければnil
  3. 閉じている最後の完全な部分式の開始位置。 なければnil
  4. 文字列の内側であるとnil以外である。 より正確には、これは文字列を終える文字である。 あるいは、汎用文字列区切り文字で終えるときにはtである。
  5. (どちらかの形式の)コメントの内側であるとtである。
  6. ポイントがクォート文字の直後であるとtである。
  7. この解析中に出会った最小の括弧の深さ。
  8. どの形式のコメントが活性であるかを表す。 『a』形式であるとnil、 『b』形式であるとt、 汎用コメント区切り文字で終るコメントの場合にはsyntax-tableである。
  9. 文字列やコメントの開始位置。 コメントの内側であるときにはこれはコメントの開始位置であり、 文字列の内側であるときにはこれは文字列の開始位置である。 文字列やコメントの外側では、この要素はnilである。

引数stateでは、要素0、3、4、5、7は重要である。

この関数は、入れ子にあった括弧を持つ言語向けに 字下げを計算するためにしばしば用いられる。

scan-lists from count depth Function
この関数は、位置fromから前方へ向けてcount個の 釣り合った括弧のグループを走査する。 走査を停止した位置を返す。 countが負であると、後方へ向けて走査する。

depthが0以外であると、括弧の深さをその値から数え始める。 停止箇所の候補位置は、括弧の深さが0になる箇所である。 scan-listsは、そのような箇所をcount回数えてから停止する。 したがって、depthに正の値を指定すると、 括弧のレベルをdepthレベルだけ抜けることを意味する。

parse-sexp-ignore-commentsnil以外であると、 コメントを無視して走査する。

走査がバッファ(あるいはその参照可能部分)の先頭や末尾に達し、 深さが0でないと、エラーを通知する。 深さは0であるが指定個数だけ数えてない場合には、nilを返す。

scan-sexps from count Function
この関数は、位置fromから前方へ向けてcount個のS式を走査する。 走査を終えた位置を返す。 countが負であると、後方へ向けて移動する。

parse-sexp-ignore-commentsnil以外であると、 コメントを無視して走査する。

走査が括弧によるグループの途中で バッファ(あるいはその参照可能部分)の先頭や末尾に達すると、 エラーを通知する。 指定個数だけ数えるまえに括弧によるグループのあいだで 先頭や末尾に達した場合はnilを返す。

parse-sexp-ignore-comments Variable
値がnil以外であると、 本節の関数やforward-sexpは、コメントを白文字として扱う。

Emacsの古い版では、コメントの終了が*/のような形であり、かつ、 コメントの終了と思える場合にのみ、この機能は動作した。 改行でコメントを終える言語では、改行すべてがコメントの終りではないために、 この変数をnilにする必要があった。 このような制限事項はすでにない。

forward-commentを使うと、 1つのコメントや複数のコメントを飛び越えて前後に移動できます。

forward-comment count Function
この関数は、ポイントを前方へ向けて(countが負ならば後方へ向けて) count個のコメントを飛び越えて移動する。 コメントか白文字以外のものに出会うと停止し、当該箇所にポイントを置く。 count個だけ数えたあとにももちろん停止する。

ポイントに続くすべてのコメントと白文字を飛び越えるには、 (forward-comment (buffer-size))を使います。 バッファ内のコメントの個数は(buffer-size)を越えるはずがないので、 引数に使うには(buffer-size)はよいものです。


Node:Standard Syntax Tables, Next:, Previous:Parsing Expressions, Up:Syntax Tables

標準的な構文テーブル

Emacsのほとんどのメジャーモードにはそれ独自の構文テーブルがあります。 それらのいくつかをつぎに示します。

standard-syntax-table Function
この関数は、基本(fundamental)モードで使用する構文テーブルである 標準の構文テーブルを返す。

text-mode-syntax-table Variable
この変数の値は、テキスト(text)モードで使用する構文テーブルである。

c-mode-syntax-table Variable
この変数の値は、Cモードのバッファ向けの構文テーブルである。

emacs-lisp-mode-syntax-table Variable
この変数の値は、編集コマンドがemacs-lispモードで使用する構文テーブルである。 (これはLispの関数readにはなんの効果もない。)


Node:Syntax Table Internals, Next:, Previous:Standard Syntax Tables, Up:Syntax Tables

構文テーブルの内部

Lispプログラムでは普通は構文テーブルの要素を直接には操作しません。 Lispレベルの構文テーブル関数は、 普通は構文記述子(see Syntax Descriptors)を操作します。 ですが、内部形式を明文化しておきます。

構文テーブルの各要素は、(syntax-code . matching-char)の 形のコンスセルです。 CARsyntax-codeは、構文クラスと構文フラグを符号化する整数です。 釣り合う文字を指定してあると、 CDRmatching-charnil以外です。

つぎの表は、各構文クラスに対応するsyntax-codeの値です。

整数 クラス 整数 クラス 整数 クラス
0 whitespace 5 close parenthesis 10 character quote
  白文字   閉じ括弧   文字クォート
1 punctuation 6 expression prefix 11 comment-start
  句読点   式前置子   コメント開始
2 word 7 string quote 12 comment-end
  単語   文字列クォート   コメント終了
3 symbol 8 paired delimiter 13 inherit
  シンボル   対になった区切り   継承
4 open parenthesis 9 escape 14 comment-fence
  開き括弧   エスケープ   コメント区切り
15 string-fence
  文字列区切り

たとえば、(の普通の構文値は、(4 . 41)です。 (41は)の文字コード。)

フラグは、最下位ビットから16番目のビットから始まる上位ビットに符号化します。 つぎの表は、各構文フラグとそれに対応する2の巾です。

フラグ 2の巾 フラグ 2の巾 フラグ 2の巾
1 (lsh 1 16) 3 (lsh 1 18) p (lsh 1 20)
2 (lsh 1 17) 4 (lsh 1 19) b (lsh 1 21)


Node:Categories, Previous:Syntax Table Internals, Up:Syntax Tables

カテゴリ

カテゴリ(category)は、文字を構文的に分類する別の方法です。 必要に応じて複数のカテゴリを定義できて、 そうすると各文字に1つか複数のカテゴリを独立に設定できます。 構文クラスと異なり、カテゴリは互いに排他的ではありません。 1つの文字が複数のカテゴリに属することは普通にあります。

各バッファにはカテゴリテーブル(category table)があり、 どのカテゴリが定義済みでどの文字がどのカテゴリに属するかを記録しています。 各カテゴリテーブルはそれ独自のカテゴリ群を定義しますが、 それらは標準のカテゴリテーブルをコピーして普通は初期化されます。 そのため、すべてのモードで標準のカテゴリを使えます。

各カテゴリには名前があり、それは から~までの 範囲のASCII印字文字です。 define-categoryでカテゴリを定義するときにその名前を指定します。

カテゴリテーブルは実際には文字テーブル(see Char-Tables)です。 カテゴリテーブルの添字cの要素は、 カテゴリ集合(category set)です。 これはブールベクトルであり、文字cが属するカテゴリ群を表します。 このカテゴリ集合において、添字catの要素がtであると、 catは集合の要素であることを意味し、 当該文字cはカテゴリcatに属することを意味します。

define-category char docstring &optional table Function
この関数は、名前をchar、説明文字列をdocstringとして 新たなカテゴリを定義する。

新たなカテゴリは、カテゴリテーブルtableに対して定義される。 tableのデフォルトは、カレントバッファのカテゴリテーブルである。

category-docstring category &optional table Function
この関数は、カテゴリテーブルtableのカテゴリcategoryの 説明文字列を返す。
(category-docstring ?a)
     => "ASCII"
(category-docstring ?l)
     => "Latin"

get-unused-category table Function
この関数は、カテゴリテーブルtableで現在定義されていない 新たなカテゴリ名(文字)を返す。 tableにおいて可能なすべてのカテゴリが使用済みであるとnilを返す。

category-table Function
この関数は、カレントバッファのカテゴリテーブルを返す。

category-table-p object Function
この関数は、objectがカテゴリテーブルであるとtを返し、 さもなければnilを返す。

standard-category-table Function
この関数は、標準のカテゴリテーブルを返す。

copy-category-table &optional table Function
この関数は、カテゴリテーブルtableのコピーを作成しそれを返す。 tableを指定しない(あるいはnil)と、 現在のカテゴリテーブルのコピーを返す。 tableがカテゴリテーブルでないとエラーを通知する。

set-category-table table Function
この関数は、カレントバッファのカテゴリテーブルをtableとする。 tableを返す。

make-category-set categories Function
この関数は、新たなカテゴリ集合、つまり、 文字列categoriesに指定したカテゴリで 内容を初期化したブールベクトルを返す。 categoriesの要素はカテゴリ名であること。 新たなカテゴリ集合では、categoriesの各カテゴリに対してはtを それ以外のカテゴリに対してはnilを設定する。
(make-category-set "al")
     => #&128"\0\0\0\0\0\0\0\0\0\0\0\0\2\20\0\0"

char-category-set char Function
この関数は、文字charに対するカテゴリ集合を返す。 これは、文字charが属するカテゴリ群を記録したブールベクトルである。 関数char-category-setは、カテゴリテーブルに 存在する同じブールベクトルを返すため、新たな領域を割り付けない。
(char-category-set ?a)
     => #&128"\0\0\0\0\0\0\0\0\0\0\0\0\2\20\0\0"

category-set-mnemonics category-set Function
この関数は、カテゴリ集合category-setを この集合に属するすべてのカテゴリの名前からなる文字列に変換する。
(category-set-mnemonics (char-category-set ?a))
     => "al"

modify-category-entry character category &optional table reset Function
この関数は、カテゴリテーブルtable(デフォルトはカレントバッファの カテゴリテーブル)内の文字characterのカテゴリ集合を変更する。

普通、カテゴリ集合にcategoryを追加して変更する。 しかし、resetnil以外であるとcategoryを削除する。


Node:Abbrevs, Next:, Previous:Syntax Tables, Up:Top

略語と略語の展開

略語(abbrev)とは、より長い文字列へ展開される文字の列のことです。 ユーザーが略語の文字列を挿入すると、その展開形に自動的に置換されます。 これにより打鍵量を省けます。

現在有効な略語の集まりは、略語表(abbrev table)に記録されています。 各バッファにはローカルな略語表がありますが、 通常、同じメジャーモードのすべてのバッファは1つの略語表を共有します。 グローバルな略語表もあります。 通常、両方を使います。

略語表は、各略語に対するシンボルを収めたオブジェクト配列として表現されます。 シンボルの名前が略語です。 その値は展開形であり、その関数定義は展開を行うフック関数です。 その属性リストのセルには略語を展開した回数である利用回数が入ります。 それらのシンボルは、通常のオブジェクト配列にはインターンされませんから、 Lisp式を読み取った結果には、それらはけっして現れません。 実際、略語を扱うコード以外では、それらはけっして使われません。 したがって、それらをかなり非標準的に使っても安全です。 See Creating Symbols

ユーザーレベルの略語コマンドについては、 Abbrevsを参照してください。


Node:Abbrev Mode, Next:, Previous:Abbrevs, Up:Abbrevs

略語(abbrev)モードの設定

略語(abbrev)モードは、変数abbrev-modeの値で制御される マイナモードです。

abbrev-mode Variable
この変数の値がnil以外であると、 バッファに略語が挿入されると自動的に展開するようになる。 値がnilであると、略語を定義することはできるが、 自動的には展開されない。

この変数は設定されると自動的にバッファローカルになる。

default-abbrev-mode Variable
これは、abbrev-modeを上書きしていないバッファ向けの abbrev-modeの値である。 これは(default-value 'abbrev-mode)と同じである。


Node:Abbrev Tables, Next:, Previous:Abbrev Mode, Up:Abbrevs

略語表

本節では、略語表の作成方法と扱い方について述べます。

make-abbrev-table Function
この関数は、新たな空の略語表、つまり、 シンボルを含まないオブジェクト配列を作成して返す。 ベクトルはゼロで埋められる。

clear-abbrev-table table Function
この関数は、略語表table内のすべての略語を未定義にして略語表を空にする。 関数はnilを返す。

define-abbrev-table tabname definitions Function
この関数は、tabname(シンボル)を略語表の名前として定義する。 つまり、この変数としての値は略語表になる。 definitionsに従って略語表に略語を定義する。 ここで、definitions(abbrevname expansion hook usecount)の形の 要素から成るリストである。 戻り値はつねにnilである。

abbrev-table-name-list Variable
その値が略語表であるシンボルのリストである。 define-abbrev-tableは、新たな略語表の名前をこのリストに追加する。

insert-abbrev-table-description name &optional human Function
この関数は、nameで指名される略語表の記述をポイントのまえに挿入する。 引数nameは、その値が略語表であるシンボルである。 戻り値はつねにnilである。

humannil以外であると、この記述は人間向けである。 さもなければ、この記述はLisp式、つまり、 nameの現在の定義どおりにnameを定義するような define-abbrev-tableの呼び出しである。


Node:Defining Abbrevs, Next:, Previous:Abbrev Tables, Up:Abbrevs

略語を定義する

これらの関数は、指定した略語表に略語を定義します。 define-abbrevは下位レベルの基本的な関数ですが、 add-abbrevはユーザーに情報を問い合わせるコマンドが使います。

add-abbrev table type arg Function
この関数は、ユーザーからの情報に基づいて 略語表tableに略語を追加する。 引数typeは、この略語の種類を英語で表した文字列である (典型的には、"global""mode-specific"。) この文字列はユーザーへのプロンプトに使われる。 引数argは、展開形の単語数である。

戻り値は、新たな略語を内部的に表現するシンボルであるか、 既存の略語を再定義することをユーザーが拒否したときにはnilである。

define-abbrev table name expansion hook Function
この関数は、略語表tableにおいて、 略語nameexpansionに展開するように定義し、 hookを呼び出すように定義する。 戻り値は、Emacs内部で略語を表現するシンボルを返すが、 その名前はnameである。

引数nameは文字列であること。 引数expansionは、普通は、目的の展開形(文字列)であるが、 略語を未定義にするにはnilである。 これが文字列でもnilでもなければ、 略語を『展開する』ときにはhookだけを実行する。

引数hookは、関数かnilである。 hooknil以外であると、 略語をexpansionに置換し終えてから引数なしで呼ばれる。 hookが呼ばれるときには、 ポイントはexpansionの直後に置かれる。

略語の利用回数は0に初期化される。

only-global-abbrevs User Option
この変数がnil以外であると、 ユーザーはグローバルな略語だけを使う意図があることを表す。 モード固有の略語を定義するコマンドに対して、 グローバルな略語を定義するように指示する。 この変数は本節の関数のふるまいを変えることはないが、 それらを呼び出す側でこの変数を検査している。


Node:Abbrev Files, Next:, Previous:Defining Abbrevs, Up:Abbrevs

略語をファイルに保存する

略語定義を保存したファイルは、実際には、Lispコードのファイルです。 略語は、同じ内容の同じ略語表を定義するLispプログラムの形で保存されます。 したがって、ファイルはload(see How Programs Do Loading)で ロードできます。 しかし、関数quietly-read-abbrev-fileがより便利なインターフェイスを 提供します。

save-some-buffersなどのユーザーレベルの機能では、 ここに述べた変数の制御のもとで、略語をファイルに自動的に保存できます。

abbrev-file-name User Option
これは、略語を読み込んだり保存するデフォルトのファイル名である。

quietly-read-abbrev-file filename Function
この関数は、write-abbrev-fileで書いておいた ファイルfilenameから、略語定義を読み取る。 filenamenilであると、 abbrev-file-nameで指定されるファイルを使う。 save-abbrevstを設定して、変更は保存されるようにする。

この関数はいっさいメッセージを表示しない。 nilを返す。

save-abbrevs User Option
save-abbrevnil以外の値であると、 Emacsはファイルを保存するときに略語も保存する。 abbrev-file-nameが略語を保存するファイルを指定する。

abbrevs-changed Variable
略語を定義したり変更すると、この変数はnil以外に設定される。 これは、読者の略語を保存する機会を与えるために、 Emacsのさまざまなコマンドに対するフラグとして働く。

write-abbrev-file filename コマンド
ロードすると同じ略語を定義するようなLispプログラムの形で、 ファイルfilenameにすべての略語表のすべての略語定義を保存する。 この関数はnilを返す。


Node:Abbrev Expansion, Next:, Previous:Abbrev Files, Up:Abbrevs

略語の探索と展開

通常、略語は、self-insert-commandを含む特定の対話的なコマンドに よって展開されます。 本節では、データのやりとりに使う変数に加えて、そのようなコマンドを書くために 使用するサブルーティンについて述べます。

abbrev-symbol abbrev &optional table Function
この関数は、名前abbrevの略語を表すシンボルを返す。 そのような略語が定義されていなければ、戻り値はnilである。 省略可能な第2引数tableは、探索対象の略語表である。 tablenilであると、 この関数は、まずカレントバッファのローカルな略語表を試し、 つぎにグローバルな略語表を試す。

abbrev-expansion abbrev &optional table Function
この関数は、abbrevが (カレントバッファで使用される略語表での定義どおりに) 展開されるであろう文字列を返す。 省略可能な引数tableは、abbrev-symbolと同様に、 使用する略語表を指定する。

expand-abbrev コマンド
このコマンドは、ポイントのまえの略語をあれば展開する。 略語の直後にポイントがない場合、このコマンドはなにもしない。 このコマンドは、展開を行えばtを返し、 さもなければnilを返す。

abbrev-prefix-mark &optional arg コマンド
現在のポイント位置を略語の開始位置としてマークする。 つぎにexpand-abbrevを呼び出すと、 通常どおりにポイントのまえの単語を使うかわりに、 ここから(その時点での)ポイントまでのテキストを略語として展開する。

abbrev-all-caps User Option
これがnil以外であると、 大文字だけで入力された略語を大文字だけで展開する。 さもなければ、大文字だけで入力された略語は、 展開形の各単語を大文字で始めるように展開される。

abbrev-start-location Variable
これは、expand-abbrevがつぎに展開する略語の開始位置として使う バッファ内位置である。 (nilであると、そのかわりにポイントのまえの単語を使う意味である。) expand-abbrevが呼び出されるたびに、 abbrev-start-locationnilに設定される。 この変数は、abbrev-prefix-markでも設定される。

abbrev-start-location-buffer Variable
この変数の値は、abbrev-start-locationが設定されたバッファである。 別のバッファで略語を展開しようとするとabbrev-start-locationは クリアされる。 この変数はabbrev-prefix-markが設定する。

last-abbrev Variable
これは、もっとも最近に略語展開されたabbrev-symbol (略語を表すシンボル)である。 この情報は、コマンドunexpand-abbrev向けに expand-abbrevが残す (see Expanding Abbrevs) 。

last-abbrev-location Variable
これは、もっとも最近に略語展開した箇所である。 これは、コマンドunexpand-abbrev向けに expand-abbrevが残した情報を保持する。

last-abbrev-text Variable
これは、もっとも最近に略語展開したときの(あれば)大文字小文字変換後の 展開形のテキストである。 略語展開を取り消すと、この値はnilである。 これは、コマンドunexpand-abbrev向けに expand-abbrevが残した情報を保持する。

pre-abbrev-expand-hook Variable
これは、任意の略語を展開する直前に順に実行される関数を 収めたノーマルフックである。 see Hooks。 ノーマルフックなので、フック関数は引数を受け取らない。 しかし、バッファでポイントのまえを調べることで 展開すべき略語をみつけることができる。

以下のコード例は、pre-abbrev-expand-hookの使い方を示します。 ユーザーが略語を句読点文字で終えると、フック関数が確認を求めます。 したがって、このフックにより、ユーザーは展開の可否を決定でき、 了承しなかったときには展開を止められます。

(add-hook 'pre-abbrev-expand-hook 'query-if-not-space)

;; この関数は、pre-abbrev-expand-hookが起動する

;; ユーザーが略語を空白で終えると、この関数はなにもしない
;; (つまり、略語を展開できるように戻る)
;; ユーザーがその他の文字を入力したら、
;; この関数は展開するかどうかを問い合わせる

;; ユーザーがプロンプトにyで答えたら、
;; (関数notを使っているので)この関数はnilを返すが
;; 問題ない。戻り値は展開には影響しない

(defun query-if-not-space ()
  (if (/= ?\  (preceding-char))
      (if (not (y-or-n-p "Do you want to expand this abbrev? "))
          (error "Not expanding this abbrev"))))


Node:Standard Abbrev Tables, Previous:Abbrev Expansion, Up:Abbrevs

標準の略語表

Emacsにあらかじめロードされるメジャーモード向けの 略語表を保持する変数一覧を示します。

global-abbrev-table Variable
これは、モードに依存しない略語向けの略語表である。 これに定義された略語は、すべてのバッファに適用される。 各バッファにはローカルな略語表もあり、 それらの略語定義はグローバルな略語表の略語定義に優先する。

local-abbrev-table Variable
このバッファローカルな変数の値は カレントバッファの(モード固有の)略語表である。

fundamental-mode-abbrev-table Variable
これは、基本(fundamental)モードで使われるローカルな略語表である。 いいかえれば、基本(fundamental)モードであるすべてのバッファの ローカルな略語表である。

text-mode-abbrev-table Variable
これは、テキスト(text)モードで使われるローカルな略語表である。

lisp-mode-abbrev-table Variable
これは、lispモードとemacs-lispモードで使われるローカルな略語表である。


Node:Processes, Next:, Previous:Abbrevs, Up:Top

プロセス

オペレーティングシステムの用語では、 プロセス(process)とは、プログラムを実行する空間のことです。 Emacsはプロセスとして動いています。 Emacs Lispのプログラムでは、 独自のプロセスとして他のプログラムを起動できます。 それらは、Emacsプロセスのサブプロセス(subprocess)とか 子プロセス(child process)と呼ばれ、 Emacsプロセスはそれらの親プロセス(parent process)です。

Emacsのサブプロセスは、それを作成する方法に依存して、 同期(synchronous)であるか非同期(asynchronous)です。 同期サブプロセスを作成すると、 Lispプログラムは実行を継続するまえにそのサブプロセスの終了を待ちます。 非同期サブプロセスを作成すると、それはLispプログラムと並行して動作します。 この種のサブプロセスは、Emacs内部ではやはり『プロセス』と呼ばれる Lispオブジェクトで表現されます。 Lispプログラムはこのオブジェクトを用いて サブプロセスと通信したりそれを制御できます。 たとえば、シグナルを送ったり、状態情報を取得したり、 プロセスからの出力を受け取ったり、プロセスへ入力を送れます。

processp object Function
この関数は、objectがプロセスであればtを返し、 さもなければnilを返す。


Node:Subprocess Creation, Next:, Up:Processes

サブプロセス作成関数

プログラムを実行するために新たなサブプロセスを作る関数が3つあります。 その1つstart-processは、非同期プロセスを作成して プロセスオブジェクトを返します(see Asynchronous Processes)。 残りの2つ、call-processcall-process-regionは 同期プロセスを作成しますが、プロセスオブジェクトは返しません (see Synchronous Processes)。

同期/非同期プロセスについては以下の節に述べます。 3つの関数の呼び出し方は類似しているので、 ここではそれらに共通な引数について述べます。

いずれの場合でも、関数の引数programは、 実行すべきプログラムを指定します。 そのファイルがみつからなかったり実行できないと、 エラーを通知します。 ファイル名が相対名であると、 変数exec-pathは探索すべきディレクトリのリストを保持しています。 Emacsは起動時に環境変数PATHの値に基づいてexec-pathを 初期化します。 ~...のファイル名の標準的な書き方は、 exec-pathでも普通どおりに解釈されますが、 ($HOMEなどの)環境変数の置換は認識しません。 それにはsubstitute-in-file-nameを使います (see File Name Expansion)。

サブプロセスを作成する各関数には、 プログラムの標準出力の受け取り場所を指定する 引数buffer-or-nameがあります。 これはバッファかバッファ名である必要があります。 バッファ名であると、そのバッファが既存でなければ新たに作成します。 nilでもかまいませんが、その場合、 フィルタ関数で処理しない限り出力を破棄します。 (Filter Functionsとsee Read and Print)。 通常、複数のプロセスの出力を同じバッファへは送らないようにします。 それらの出力がでたらめに混ざってしまうからです。

サブプロセスを作成する3つの関数すべてに、 &rest引数であるargsがあります。 argsはすべてが文字列である必要があり、 それぞれを区切ってコマンド行引数としてprogramに与えられます。 引数全体を指定されたプログラムへ直接渡すため、 これらの引数ではワイルドカード文字や他のシェル構文の特別な意味はありません。

注意 引数programにはプログラムの名前だけを指定し、 コマンド行引数はいっさい指定しない。 コマンド行引数はargsで与えること。

サブプロセスのカレントディレクトリは default-directoryの値で決まります(see File Name Expansion)。

サブプロセスはEmacsから環境変数を継承しますが、 優先するものをprocess-environmentで指定できます。 See System Environment

exec-directory Variable
この変数の値は、Emaccsが起動することを意図した GNU Emacsとともに配布されたプログラム群を収めたディレクトリ名 (文字列)である。 プログラムmovemailはそのようなプログラムの例であり、 inboxから新たなメイルを取り出すためにrmailが利用する。

exec-path User Option
この変数の値は、サブプロセスで実行するプログラムを探索する ディレクトリのリストである。 各要素はディレクトリ名(文字列)であるか、 デフォルトディレクトリ(つまりdefault-directoryの値) を意味するnilである。

引数programが絶対ファイル名でないと、 call-processstart-processexec-pathの値を使う。


Node:Shell Arguments, Next:, Previous:Subprocess Creation, Up:Processes

シェル引数

Lispプログラムから、 ユーザーが指定したファイル名を含んだコマンドを指定して シェルを実行する必要がときどきあります。 これらのプログラムでは、任意の正しいファイル名を扱える必要があります。 しかし、シェルは、特定の文字がファイル名として現れると特別に扱うので、 そのような文字がシェルに混乱をもたらします。 そのような文字を扱うには、関数shell-quote-argumentを使います。

shell-quote-argument argument Function
この関数は、argumentを実際の内容とする シェル構文で表した引数を文字列で返す。 この戻り値をシェルコマンドに連結し、 実行のためにシェルに渡しても問題を生じないはずである。

この関数が行うことの詳細は読者のオペレーティングシステムに依存する。 この関数は通常のシェル構文に合うように設計してある。 非標準のシェルを使う場合には、この関数を再定義する必要があろう。 MS-DOSでは、この関数はargumentを無変更で返す。 MS-DOSのシェルにはクォートの機能がないため、 これは本当は正しいことではないが最良のことである。

;; つぎの例はGNUとUNIXシステムのふるまいである
(shell-quote-argument "foo > bar")
     => "foo\\ \\>\\ bar"

シェルコマンドを作るshell-quote-argumentの使用例をつぎに示す。

(concat "diff -c "
        (shell-quote-argument oldfile)
        " "
        (shell-quote-argument newfile))


Node:Synchronous Processes, Next:, Previous:Shell Arguments, Up:Processes

同期プロセスの作成

同期プロセス(synchronous process)を作成すると、 Emacsは実行を続行するまえにそのプロセスが終了するのを待ちます。 diredはその例です。 lsを同期プロセスで実行し、その出力を少々修正します。 プロセスは同期なので、Emacsがなにかを行おうとするまえに ディレクトリ一覧全部がバッファに届きます。

Emacsは同期サブプロセスの終了を待ちますが、 ユーザーはC-gと打って中断できます。 C-gはまずシグナルSIGINTでサブプロセスをキルしようとしますが、 中断を完了するまえにサブプロセスが終了するのを待ちます。 その期間にユーザーがさらにC-gを打つと、 SIGKILLでサブプロセスを即座にキルし、ただちに中断を完了します。 See Quitting

同期サブプロセス作成関数は、 そのプロセスがどのように終了したかを表すものを返します。

同期サブプロセスからの出力は、ファイルから読むテキストと同様に、 コーディングシステムを用いて一般には復号化します。 call-process-regionがサブプロセスへ送る入力は、 ファイルへ書くテキストと同様に、 コーディングシステムを用いて符号化します。 See Coding Systems

call-process program &optional infile destination display &rest args Function
この関数は、別のプロセスでprogramを呼び出し、 それが終了するのを待つ。

infilenilでなければ プロセスへの標準入力はinfileであるが、 さもなければ/dev/nullである。 引数destinationでプロセスの出力先をつぎのように指定する。

バッファ
このバッファのポイントのまえに出力を挿入する。 これにはプロセスの標準出力と標準エラーの両者を含む。
文字列
文字列で指定した名前のバッファのポイントのまえに出力を挿入する。
t
カレントバッファのポイントのまえに出力を挿入する。
nil
出力を破棄する。
0
出力を破棄し、サブプロセスの終了を待たずにただちに戻る。

この場合、このプロセスはEmacsと並行して動作するので真のサブプロセスではない。 しかし、この関数から戻るとEmacsはサブプロセスの処理を本質的には終えたと いう意味で同期プロセスと考えることができる。

(real-destination error-destination)
標準出力と標準エラーを分離し、 real-destinationの指定に従って通常の出力を扱い、 error-destinationに従ってエラー出力を処理する。 error-destinationnilであるとエラー出力を破棄し、 tであると通常の出力に混ぜ、 文字列であるとその名前のファイルにエラー出力を振り向ける。

エラー出力を入れるバッファを直接に指定することはできない。 それを実装するのは難しすぎる。 しかし、エラー出力を一時ファイルへ送ってから そのファイルをバッファに挿入すれば、同じ効果を得られる。

displaynil以外であると、call-processは、 出力が挿入されるとバッファを再表示する。 (しかし、コーディングシステムとして実際のデータから コーディングシステムを推定するundecidedを指定していると、 非ASCII文字に出会うと再表示を継続できない場合もある。 これを修正するのが困難である根本的な理由がある。) さもなければ、関数call-processは再表示しないので、 Emacsが通常の過程でそのバッファを再表示するまでは、 スクリーン上で結果は見えない。

残りの引数argsは、プログラムに対する コマンド行引数を指定する文字列である。

(待たないように指示しない限り)call-processが返す値は、 プロセスの終了理由を表す。 数でサブプロセスの終了状態を表し、 0は成功、それ以外の値は失敗を意味する。 プロセスがシグナルで終了すると、 call-processはシグナルを記述する文字列を返す。

つぎの例では、バッファfooがカレントである。

(call-process "pwd" nil t)
     => nil

---------- Buffer: foo ----------
/usr/user/lewis/manual
---------- Buffer: foo ----------

(call-process "grep" nil "bar" nil "lewis" "/etc/passwd")
     => nil

---------- Buffer: bar ----------
lewis:5LTsHm66CSWKg:398:21:Bil Lewis:/user/lewis:/bin/csh

---------- Buffer: bar ----------

insert-directoryの定義にあるcall-processの よい使用例をつぎに示す。

(call-process insert-directory-program nil t nil switches
              (if full-directory-p
                  (concat (file-name-as-directory file) ".")
                file))

call-process-region start end program &optional delete destination display &rest args Function
この関数は、programを動かすプロセスの標準入力として startendのあいだのテキストを送る。 deletenil以外であると、送ったテキストを削除する。 これは、カレントバッファに送った入力のかわりに出力を挿入することを 意味するdestinationtであるときに有用である。

引数destinationdisplayは、 サブプロセスからの出力をどのように扱い、 出力か到着するたびに表示を更新するかどうかを制御する。 詳しくは、上記のcall-processの記述を参照。 destinationが整数0であると、 call-process-regionは、サブプロセスの終了を待たずに 出力を破棄してただちにnilを返す。

残りの引数argsは、プログラムに対する コマンド行引数を指定する文字列である。

call-process-regionの戻り値はcall-processと同様であり、 待たずに戻るように指示するとnilであり、 さもなければサブプロセスの終了状態を表す数か文字列である。

つぎの例では、 バッファfooの始めの5文字(単語input)を標準入力として ユーティリティcatを実行するためにcall-process-regionを使う。 catは、標準入力を標準出力へコピーする。 引数destinationtであるので、 出力はカレントバッファに挿入される。

---------- Buffer: foo ----------
input-!-
---------- Buffer: foo ----------

(call-process-region 1 6 "cat" nil t)
     => nil

---------- Buffer: foo ----------
inputinput-!-
---------- Buffer: foo ----------

コマンドshell-command-on-regionは、 つぎのようにcall-process-regionを使う。

(call-process-region
 start end
 shell-file-name      ; プログラムの名前
 nil                  ; リージョンを削除しない
 buffer               ; 出力はbufferへ入れる
 nil                  ; 出力中は再表示しない
 "-c" command)        ; シェルに対する引数

shell-command-to-string command Function
この関数は、シェルコマンドとしてcommand(文字列)を実行し、 コマンドの出力を文字列として返す。


Node:Asynchronous Processes, Next:, Previous:Synchronous Processes, Up:Processes

非同期プロセスの作成

非同期プロセスを作成すると、Emacsとサブプロセスの両者は ただちに動作を継続します。 そしてプロセスはEmacsと並行に動作し、 両者は以下の節に述べる関数を用いて互いに通信できます。 しかし、通信は部分的に非同期です。 特定の関数を呼び出したときにだけEmacsはプロセスへデータを送り、 Emacsが入力待ちか時間待ちをしているときにだけ プロセスからの出力を受け取れます。

ここでは、非同期プロセスの作成方法について述べます。

start-process name buffer-or-name program &rest args Function
この関数は、新たな非同期サブプロセスを作成し、 そのプロセスでプログラムprogramを走らせる。 Lispにおいて新たなサブプロセスを表すプロセスオブジェクトを返す。 引数nameはプロセスオブジェクトの名前を指定する。 その名前のプロセスがすでに存在すると、 名前を一意にするために(<1>などを付加して)nameを修正する。 バッファbuffer-or-nameは、そのプロセスに対応付けるバッファである。

残りの引数argsは、プログラムに対する コマンド行引数を指定する文字列である。

つぎの例では、最初のプロセスは動き始めると 100秒間(休止ではなく)動作する。 そのあいだに2番目のプロセスを動かし始めると、 一意であるためにそれには名前my-process<1>が与えられる。 2番目のプロセスは、最初のプロセスが終了するまえに バッファfooにディレクトリ一覧を挿入する。 2番目のプロセスが終了するとそれを表すメッセージがバッファに挿入される。 しばらくして最初のプロセスが終了すると、 別のメッセージがバッファに挿入される。

(start-process "my-process" "foo" "sleep" "100")
     => #<process my-process>

(start-process "my-process" "foo" "ls" "-l" "/user/lewis/bin")
     => #<process my-process<1>>

---------- Buffer: foo ----------
total 2
lrwxrwxrwx  1 lewis     14 Jul 22 10:12 gnuemacs --> /emacs
-rwxrwxrwx  1 lewis     19 Jul 30 21:02 lemon

Process my-process<1> finished

Process my-process finished
---------- Buffer: foo ----------

start-process-shell-command name buffer-or-name command &rest command-args Function
この関数はstart-processと同様であるが、 指定したコマンドを実行するためにシェルを用いる点が異なる。 引数commandはシェルコマンドの名前であり、 command-argsはそのシェルコマンドに対する引数である。 変数shell-file-nameは、使用するシェルを指定する。

start-processで直接にではなく シェルを介してプログラムを実行すると、 引数のワイルドカードなどのシェルの機能を利用できる。 つまり、ユーザー指定の任意のファイル名をコマンドに入れる場合には、 まえもってshell-quote-argumentでクォートし、 ファイル名内のシェルの特別な文字が そのような特別な意味を持たないようにする。 see Shell Arguments

process-connection-type Variable
この変数は、非同期サブプロセスとの通信に用いる装置の型を制御する。 これがnil以外であると疑似端末PTYを利用できる場合にはそれを用る。 さもなければパイプを用いる。

シェル(shell)モードなどのユーザーに見えるプロセス向けには、 パイプでは不可能なプロセスとその子プロセスとのあいだで ジョブ制御(C-cC-zなど)を許すので 疑似端末PTYが望ましい。 プログラムの内部目的向けに使われるサブプロセスでは、 効率的なパイプを用いるほうがよい。 また、多くのシステムでは疑似端末PTYの総数には制約があり、 それらを浪費しないほうがよい。

process-connection-typeの値は start-processを呼び出したときに使われる。 したがって、start-processの呼び出しの周りでこの変数を束縛することで、 1つのサブプロセスに対する通信方法を指定できる。

(let ((process-connection-type nil))  ; パイプを使う
  (start-process ...))

サブプロセスが実際にはパイプか疑似端末PTYのどちらを 使っているかを調べるには、関数process-tty-nameを使う (see Process Information)。


Node:Deleting Processes, Next:, Previous:Asynchronous Processes, Up:Processes

プロセスの削除

プロセスを削除するとは、サブプロセスからEmacsをただちに切り離し、 サブプロセスを活性なプロセスリストから取り除くことです。 サブプロセスへシグナルを送ってサブプロセスを終了させますが、 ただちに終了するとは保証されません。 プロセスオブジェクトを指すLispオブジェクトがある限り、 プロセスオブジェクトは存在し続けます。 プロセスマークは以前と同様に同じ場所 (プロセスからの出力をバッファに挿入した箇所)を指し続けます。

プロセスはいつでも明示的に削除できます。 プロセスは終了後に自動的に削除されますが、 終了後ただちにではありません。 終了したプロセスが自動的に削除されるまえに明示的に削除しても無害です。

delete-exited-processes User Option
この変数は、(exitを呼び出すかシグナルのために)終了した プロセスの自動削除を制御する。 nilであると、ユーザーがlist-processesを 実行するまで存在し続ける。 さもなければ、終了後にただちに削除する。

delete-process name Function
この関数は、nameに対応付けられたプロセスを シグナルSIGHUPでキルし削除する。 引数は、プロセス、プロセス名、バッファ、バッファ名のいずれかである。
(delete-process "*shell*")
     => nil

process-kill-without-query process &optional do-query Function
この関数は、Emacsを終了するときにプロセスprocessが動作中であると、 ユーザーに問い合わせるかどうかを指定する。 do-querynilであると、プロセスを黙って削除する。 さもなければ、Emacsはプロセスのキルに関して問い合わせる。

問い合わせるようにしてあったプロセスであると戻り値はtであり、 さもなければ戻り値はnilである。 新たに作成されたプロセスは、つねに問い合わせ用になっている。

(process-kill-without-query (get-process "shell"))
     => t


Node:Process Information, Next:, Previous:Deleting Processes, Up:Processes

プロセス情報

プロセスに関する情報を返す関数がいくつかあります。 list-processesは対話的利用のためにあります。

list-processes コマンド
このコマンドは、活性なすべてのプロセスの一覧を表示する。 さらに、ExitedSignaledである状態の プロセスをすべて削除する。 nilを返す。

process-list Function
この関数は、削除されていないすべてのプロセスのリストを返す。
(process-list)
     => (#<process display-time> #<process shell>)

get-process name Function
この関数はnameという名前のプロセスを返す。 あるいは、そのようなプロセスがなければnilを返す。 nameが文字列でないとエラーを通知する。
(get-process "shell")
     => #<process shell>

process-command process Function
この関数は、プロセスprocessを始動するために実行したコマンドを返す。 これは文字列のリストであり、 最初の文字列は実行されたプログラム、 残りの文字列はそのプログラムに与えた引数である。
(process-command (get-process "shell"))
     => ("/bin/csh" "-i")

process-id process Function
この関数は、プロセスprocessのプロセス番号PIDを返す。 これは同じ計算機上で動いている他のすべてのプロセスと プロセスprocessを区別するための整数である。 プロセスのPIDは、プロセスを始動したときに オペレーティングシステムのカーネルが選び、 プロセスが終了するまで変わらない。

process-name process Function
この関数はプロセスprocessの名前を返す。

process-contact process Function
この関数は、通常の子プロセスに対してはtを返し、 ネットワーク接続に対しては(hostname service)を返す (see Network)。

process-status process-name Function
この関数は、process-nameの状態をシンボルとして返す。 引数process-nameは、プロセス、バッファ、プロセス名(文字列)、 バッファ名(文字列)のいずれかであること。

実際のサブプロセスに対して可能な値はつぎのとおり。

run
実行中のプロセスである。
stop
一時停止しているが継続可能である。
exit
終了したプロセス。
signal
致命的なシグナルを受け取ったプロセスである。
open
ネットワーク接続を開いている。
closed
ネットワーク接続は閉じている。 接続をいったん閉じるとそれを再度開くことはできないが、 同じ接続先へ新たな接続を開くことはできる。
nil
process-nameは既存プロセスの名前ではない。
(process-status "shell")
     => run
(process-status (get-buffer "*shell*"))
     => run
x
     => #<process xx<1>>
(process-status x)
     => exit

ネットワーク接続では、process-statusは シンボルopenclosedのいずれかを返す。 後者は、相手側が接続を閉じたか Emacsがdelete-processを行ったことを表す。

process-exit-status process Function
この関数は、プロセスprocessの終了状態か、 プロセスをキルしたシグナル番号を返す。 (どちらであるかを判定するには、process-statusの結果を用いる。) processが終了していないと値は0である。

process-tty-name process Function
この関数は、プロセスprocessがEmacsとの通信に用いている端末名を返す。 あるいは、端末のかわりにパイプを用いていればnilを返す (Asynchronous Processesprocess-connection-typeを参照)。

process-coding-system process Function
この関数は、プロセスprocessからの出力を 復号化するために用いているコーディングシステムと、 processへの入力を符号化するために用いている コーディングシステムを記述するコンスセルを返す。
(coding-system-for-decoding . coding-system-for-encoding)

set-process-coding-system process decoding-system encoding-system Function
この関数は、プロセスprocessからの以降の出力および入力に用いる コーディングシステムを指定する。 サブプロセスから出力の復号化にはdecoding-systemを使い、 サブプロセスの入力の符号化にはencoding-systemを使う。


Node:Input to Processes, Next:, Previous:Process Information, Up:Processes

プロセスへ入力を送る

本節の関数を用いてEmacsが入力を送ると、 非同期プロセスは入力を受け取ります。 入力の送先であるプロセスと、送るべき入力データを指定する必要があります。 そのデータは、サブプロセスの『標準入力』に現れます。

疑似端末PTYのバッファ付き入力の容量に上限がある オペレーティングシステムもあります。 そのようなシステムでは、Emacsは他の文字に混ぜて定期的にEOFを送り、 文字が流れるように強制します。 ほとんどのプログラムでは、このようなEOFは無害なはずです。

ファイルに書き込むテキストと同様に、 サブプロセスの入力は、サブプロセスがそれを受け取るまえに コーディングシステムを用いて普通は符号化されます。 set-process-coding-systemで 使用するコーディングシステムを指定できます (see Process Information)。 さもなければ、coding-system-for-writenil以外であればこれを使います。 それ以外ではデフォルトの機構で決まるものを使います (see Default Coding Systems)。

process-send-string process-name string Function
この関数は、文字列stringの内容を 標準入力としてプロセスprocess-nameに送る。 引数process-nameは、プロセスかプロセス名であること。 これがnilであると、カレントバッファのプロセスを用いる。

関数はnilを返す。

(process-send-string "shell<1>" "ls\n")
     => nil


---------- Buffer: *shell* ----------
...
introduction.texi               syntax-tables.texi~
introduction.texi~              text.texi
introduction.txt                text.texi~
...
---------- Buffer: *shell* ----------

process-send-region process-name start end コマンド
この関数は、startendで定義される領域内のテキストを 標準入力としてプロセスprocess-nameへ送る。 process-nameはプロセスかプロセス名であること。 (nilであると、カレントバッファのプロセスを使う。)

startendのどちらかが カレントバッファ内の位置を表す整数でもマーカでもないと、 エラーを通知する。 (どちらが大きな数であるかは重要ではない。)

process-send-eof &optional process-name Function
この関数は、プロセスprocess-nameが入力で 「ファイルの終りEOF」を見るようにする。 EOFはそれまでに送ったテキストのあとにある。

process-nameを指定しなかったりnilであると、 この関数はカレントバッファのプロセスにEOFを送る。 カレントバッファにプロセスがないとエラーを通知する。

関数はprocess-nameを返す。

(process-send-eof "shell")
     => "shell"


Node:Signals to Processes, Next:, Previous:Input to Processes, Up:Processes

プロセスにシグナルを送る

サブプロセスにシグナルを送ることは、 サブプロセスの動作に割り込む一方法です。 それぞれ独自の意味を持つ異なるシグナルがいくつかあります。 一連のシグナルとそれらの名前は、オペレーティングシステムが定義します。 たとえば、シグナルSIGINTは、ユーザーがC-cを打った、 あるいは、それと同様なことが起こったことを意味します。

各シグナルには、サブプロセスに対する標準的な効果があります。 ほとんどのシグナルはサブプロセスをキルしますが、 その実行を一時停止したり再開するものもあります。 プログラムがシグナルを処理している場合には、 シグナルの効果を一般的に述べることはできません。

本節の関数を呼び出してシグナルを明示的に送ることができます。 また、Emacsは特定の場面で自動的にシグナルを送ります。 バッファを削除すると、そのバッファに対応付けられているすべての プロセスにシグナルSIGHUPを送ります。 Emacsを終了するときには、動作しているすべてのサブプロセスに シグナルSIGHUPを送ります。 (SIGHUPは、ユーザーが電話を切ったことを普通は表すシグナル。)

シグナルを送る各関数は、省略可能な2つの引数、 process-namecurrent-groupを受け付けます。

引数process-nameは、プロセス、プロセス名、nilのいずれかです。 これがnilであると、カレントバッファに対応付けられているプロセスが デフォルトになります。 process-nameがプロセスを指定しないとエラーを通知します。

引数current-groupは、Emacsのサブプロセスとして ジョブ制御可能なシェルを実行しているときに違いが現れるフラグです。 これがnil以外であると、 Emacsがサブプロセスとの通信に用いている端末の現在のプロセスグループに シグナルを送ります。 プロセスがジョブ制御可能なシェルであると、 これはシェルの現在のサブジョブ 10 であることを意味します。 nilであると、Emacsのサブプロセスの直接のプロセスグループに シグナルを送ります。 プロセスがジョブ制御可能なシェルであると、これはシェルそのものです。

オペレーティングシステムはパイプではプロセスグループを扱わないため、 サブプロセスとの通信にパイプを用いている場合には、 フラグcurrent-groupには効果はありません。 同じ理由で、パイプを用いている場合には ジョブ制御可能なシェル(のジョブ制御機能)は働きません。 Asynchronous Processesprocess-connection-typeを参照してください。

interrupt-process &optional process-name current-group Function
この関数は、プロセスprocess-nameに シグナルSIGINTを送って割り込む。 Emacsの外側では、『割り込み文字』(普通、C-cであるシステムもあり、 その他のシステムではDEL)を打つとこのシグナルを送る。 引数current-groupnil以外であると、 この関数は、Emacsがサブプロセスと通信している端末上で 『C-cを打つ』と考えることができる。

kill-process &optional process-name current-group Function
この関数は、プロセスprocess-nameに シグナルSIGKILLを送ってキルする。 このシグナルはサブプロセスを即座にキルし、 サブプロセスはこれを処理できない。

quit-process &optional process-name current-group Function
この関数は、プロセスprocess-nameにシグナルSIGQUITを送る。 このシグナルは、『中断文字』 (Emacsの外側では普通はC-bC-\)が 送るシグナルと同じものである。

stop-process &optional process-name current-group Function
この関数は、プロセスprocess-nameに シグナルSIGTSTPを送って一時停止させる。 その実行を再開させるにはcontinue-processを使う。

Emacsの外側でジョブ制御可能なシステムでは、 『一時停止文字』(普通はC-z)が普通はこのシグナルを送る。 current-groupnil以外であると、 この関数は、Emacsがサブプロセスと通信している端末上で 『C-zを打つ』と考えることができる。

continue-process &optional process-name current-group Function
この関数は、プロセスprocessに シグナルSIGTCONTを送って実行を再開させる。 以前に一時停止させられたprocessを再開する。

signal-process pid signal Function
この関数は、必ずしもEmacsの子プロセスではない プロセスpidにシグナルを送る。 引数signalは、送るべきシグナルを整数で指定する。


Node:Output from Processes, Next:, Previous:Signals to Processes, Up:Processes

プロセスからの出力を受け取る

サブプロセスが標準出力に書く出力を受け取る方法は2つあります。 プロセスに対応付けられたバッファに出力を挿入するか、 あるいは、フィルタ関数(filter function)と呼ばれる関数を 出力に対して作用させます。 プロセスにバッファもフィルタ関数もなければ、その出力は破棄します。

サブプロセスからの出力は、Emacsが待っている、つまり、 端末入力を読んでいるとき、 sit-forsleep-forを実行中のとき(see Waiting)、 accept-process-output(see Accepting Output)を実行中のときに だけ到着します。 これにより、並行プログラムを普通は悩ますような タイミングエラーの問題を最小に抑えます。 たとえば、安全にプロセスを作成してから、 バッファかフィルタ関数を指定できます。 この処理の途中で待つような基本関数を呼び出さなければ、 出力は到着しません。

ファイルから読むテキストと同様に、 サブプロセスの出力は、バッファやフィルタ関数が受け取るまえに コーディングシステムを用いて普通は復号化します。 set-process-coding-systemで 使用するコーディングシステムを指定できます (see Process Information)。 さもなければ、coding-system-for-readnil以外であればこれを使います。 それ以外ではデフォルトの機構で決まるものを使います (see Default Coding Systems)。

警告: データからコーディングシステムを決定するundecidedのような コーディングシステムは、非同期サブプロセスの出力に対しては 完全に信頼性のある動作はできない。 これは、Emacsが非同期サブプロセスの出力が 到着するたびに一塊で処理するからである。 Emacsは1つの塊から正しい変換を検出しようと試みるが、 これがつねに動作するとは限らない。 したがって、可能な限り 文字コード変換と行末変換の両方を指定したコーディングシステムを使う。 つまり、undecidedlatin-1などではなく、 latin-1-unixのようなものを使う。


Node:Process Buffers, Next:, Up:Output from Processes

プロセスバッファ

プロセスには対応付けられたバッファが(普通は)あります。 そのバッファはEmacsの普通のバッファであり、2つの目的に使われます。 プロセスからの出力を保存することと、 プロセスがキルされたことを判定するためです。 バッファを用いてそれを操作しているプロセスを識別することもできます。 普通は1つのバッファに1つのプロセスを対応付けるからです。 プロセスの多くの応用では、プロセスへ送る入力を編集するために バッファを使いますが、これはEmacs Lispに組み込まれたことではありません。

プロセスにフィルタ関数(see Filter Functions)がなければ、 その出力は対応付けられたバッファに挿入されます。 出力の挿入位置はprocess-markで決定され、 process-markは挿入したばかりのテキストの末尾を 指すように更新されます。 process-markは普通はバッファの末尾にありますが、 つねにそうであるとは限りません。

process-buffer process Function
この関数は、プロセスprocessに対応付けられているバッファを返す。
(process-buffer (get-process "shell"))
     => #<buffer *shell*>

process-mark process Function
この関数は、プロセスprocessからの出力を挿入する箇所を指定する processのプロセスマーカを返す。

processにバッファがなければ、 process-markはどこも指していないマーカである。

バッファにプロセス出力を挿入する際には、 挿入箇所を決定するためにこのマーカを使用し、 挿入したテキストの末尾を指すようにこのマーカを更新する。 これにより、出力の連続した塊を順に挿入できるのである。

バッファに出力を直接挿入する場合と同様に、 フィルタ関数はこのマーカを扱うべきである。 process-markを用いたフィルタ関数の好例は、以下の節にある。

プロセスへ送るためにユーザーがプロセスバッファに 入力することが予想されるときは、 プロセスマーカは新たな入力とそれ以前の出力を区切る。

set-process-buffer process buffer Function
この関数は、プロセスprocessにバッファbufferを対応付ける。 buffernilであると、 プロセスに対応付けられたバッファはない。

get-buffer-process buffer-or-name Function
この関数はbuffer-or-nameに対応付けられたプロセスを返す。 バッファに複数のプロセスが対応付けられている場合には、 それらの1つを選ぶ。 (現状では、もっとも最近に作られたプロセスを選ぶ。) 同じバッファに複数のプロセスを対応付けることは一般にはよくない。
(get-buffer-process "*shell*")
     => #<process shell>

プロセスのバッファを削除すると、 サブプロセスにシグナルSIGHUPを送ってプロセスを削除する (see Signals to Processes)。


Node:Filter Functions, Next:, Previous:Process Buffers, Up:Output from Processes

プロセスフィルタ関数

プロセスのフィルタ関数(filter function)は、 対応付けられたプロセスからの標準出力を受け取る関数です。 プロセスにフィルタがあると、そのプロセスからのすべての出力は フィルタに渡されます。 プロセスにフィルタがない場合に限って、 プロセスからの出力向けにプロセスバッファを直接使います。

フィルタ関数は、Emacsがなにかを待っているときにのみ呼ばれます。 そのような期間にのみプロセスの出力が到着するからです。 Emacsが待つのは、端末入力を読んでいるとき、 sit-forsleep-forを実行中のとき(see Waiting)、 accept-process-output(see Accepting Output)を実行中のときです。

フィルタ関数は2つの引数、 対応付けられたプロセスとそのプロセスから受け取ったばかりの出力である文字列を 受け取ります。 関数は出力に対してなにを行ってもかまいません。

フィルタ関数の内側では中断は普通は禁止されています。 さもないと、コマンドレベルで打ったC-gの効果や、 ユーザーコマンドを中断するために打ったC-gの効果は予測できません。 フィルタ関数の内側で中断を行いたい場合には、 inhibit-quitnilを束縛します。 See Quitting

フィルタ関数の実行中にエラーが発生するとそのエラーは自動的に捕捉され、 フィルタ関数を始動したときに動いていた プログラムの実行を停止しないようにします。 しかし、debug-on-errornil以外であると、 エラーを捕捉しません。 これにより、Lispデバッガでフィルタ関数をデバッグできます。 See Debugger

多くのフィルタ関数は、ときどきあるいはつねに、 プロセスのバッファにテキストを挿入します。 これはフィルタ関数がないときのEmacsの動作を模倣するものです。 そのようなフィルタ関数では、対象のバッファに挿入するために set-bufferを使う必要があります。 カレントバッファをなかば恒久的に切り替えないように、 これらのフィルタ関数はカレントバッファを記録/復元する必要があります。 プロセスマーカを更新し、必要に応じてポイントの値も更新します。 これらはつぎのように行います。

(defun ordinary-insertion-filter (proc string)
  (with-current-buffer (process-buffer proc)
    (let ((moving (= (point) (process-mark proc))))
      (save-excursion
        ;; テキストを挿入し、プロセスマーカを進める
        (goto-char (process-mark proc))
        (insert string)
        (set-marker (process-mark proc) (point)))
      (if moving (goto-char (process-mark proc))))))

カレントバッファを記録/復元するためにsave-excursionではなく with-current-bufferを使うのは、 2番目のgoto-charの呼び出しで行うポイントの移動効果を 有効にするためです。

新たにテキストが到着するたびにプロセスバッファが見えるように フィルタ関数で強制するには、 つぎのような行をwith-current-bufferの直前に入れます。

(display-buffer (process-buffer proc))

ポイント位置に関わらずに新たな出力の末尾にポイントを移動するには、 変数movingを削除して、 無条件にgoto-charを呼び出します。

Emacsの初期の版では、正規表現を探索したり一致処理するフィルタ関数では、 マッチデータを明示的に保存/復元する必要がありました。 今のEmacsは、フィルタ関数に対してはこれを自動的に行いますから、 フィルタ関数で明示的に行う必要はありません。 See Match Data

プロセスのバッファに出力を書き込むフィルタ関数は、 そのバッファが有効であるかどうかを検査するべきです。 無効なバッファに挿入しようとするとエラーになります。 バッファが無効であれば、 式(buffer-name (process-buffer process)) を実行するとnilを返します。

関数に渡される出力は任意のサイズの塊できます。 同じ出力を2回生成するプログラムは、 あるときには一度に200文字の塊を1つ送る場合もあれば、 40文字の塊を5つ送る場合もあります。 サブプロセスの出力から特定のテキスト文字列を探すフィルタでは、 そのような文字列が2つかそれ以上の出力の塊に分割される場合も 扱えるようにします。

set-process-filter process filter Function
この関数は、プロセスprocessにフィルタ関数filterを指定する。 filternilであると、プロセスにフィルタはない。

process-filter process Function
この関数は、プロセスprocessのフィルタ関数を返す。 あるいは、フィルタ関数がなければnilを返す。

フィルタ関数の使用例をつぎに示します。

(defun keep-output (process output)
   (setq kept (cons output kept)))
     => keep-output
(setq kept nil)
     => nil
(set-process-filter (get-process "shell") 'keep-output)
     => keep-output
(process-send-string "shell" "ls ~/other\n")
     => nil
kept
     => ("lewis@slug[8] % "
"FINAL-W87-SHORT.MSS    backup.otl              kolstad.mss~
address.txt             backup.psf              kolstad.psf
backup.bib~             david.mss               resume-Dec-86.mss~
backup.err              david.psf               resume-Dec.psf
backup.mss              dland                   syllabus.mss
"
"#backups.mss#          backup.mss~             kolstad.mss
")


Node:Accepting Output, Previous:Filter Functions, Up:Output from Processes

プロセスからの出力を受け取る

非同期サブプロセスからの出力は、 Emacsが時間待ちや端末入力などの なんらかの外部事象を待っているときにのみ到着します。 Lispプログラムから特定の場面で出力の到着を明示的に許したり、 プロセスの出力が到着するのを待つことができると有用なことがあります。

accept-process-output &optional process seconds millisec Function
この関数は、Emacsにプロセスからの未処理の出力を読み取ることを許す。 その出力は、対応付けられたバッファに挿入されるか、 フィルタ関数に与えられる。 processnil以外であると、 この関数は、processからなんらかの出力を得るまで戻らない。

引数secondsmillisecは、時間切れを指定する。 前者は秒単位の時間、後者はミリ秒単位の時間を指定する。 指定された2つの時間は合計され、 任意のサブプロセスの出力を受け取ったどうかに関わらず、 その時間だけ経過するとaccept-process-outputは戻ってくる。

引数secondsは整数である必要はない。 浮動小数点数であると、この関数は秒未満の時間も待つ。 秒未満を扱えないシステムもある。 そのようなシステムでは、secondsを切り下げる。

すべてのオペレーティングシステムで秒未満を扱えるわけではない。 扱えないシステムでmillisecにゼロ以外を指定すると エラーになる。

関数accept-process-outputは、 出力を得るとnil以外を返す。 あるいは、出力が到着するまえに時間切れするとnilを返す。


Node:Sentinels, Next:, Previous:Output from Processes, Up:Processes

番兵:プロセスの状態変化の検出

プロセスの番兵(process sentinel)は、 プロセスを終了/一時停止/継続させる (Emacsが送ったかプロセス自身の動作によって生起した)シグナルを含めて 対応付けられたプロセスの状態が任意の理由で変化したときに 呼び出される関数です。 プロセスの番兵は、プロセスが終了しても呼び出されます。 番兵は2つの引数、事象が発生したプロセスと 事象の種類を記述する文字列を受け取ります。

事象を記述する文字列はつぎのとおりです。

番兵はEmacsが(たとえば、端末入力や時間経過、プロセスの出力を) 待っているときにのみ実行されます。 他のLispプログラムの実行途中で無秩序に番兵を実行した場合に起こる タイミングエラーを回避するためです。 sit-forsleep-for(see Waiting)、あるいは、 accept-process-output(see Accepting Output)を 呼び出すとプログラムは待ちに入り、番兵が動けることになります。 Emacsは、コマンドループで入力を読むときにも番兵の実行を許します。

番兵の内側では中断は普通は禁止されています。 さもないと、コマンドレベルで打ったC-gの効果や、 ユーザーコマンドを中断するために打ったC-gの効果は予測できません。 番兵の内側で中断を行いたい場合には、 inhibit-quitnilを束縛します。 See Quitting

プロセスのバッファに出力を書き込む番兵は、 そのバッファが有効であるかどうかを検査するべきです。 無効なバッファに挿入しようとするとエラーになります。 バッファが無効であれば、 式(buffer-name (process-buffer process)) を実行するとnilを返します。

番兵の実行中にエラーが発生するとそのエラーは自動的に捕捉され、 番兵を始動したときに動いていた プログラムの実行を停止しないようにします。 しかし、debug-on-errornil以外であると、 エラーを捕捉しません。 これにより、Lispデバッガで番兵をデバッグできます。 See Debugger

Emacsの初期の版では、正規表現を探索したり一致処理する番兵では、 マッチデータを明示的に保存/復元する必要がありました。 今のEmacsは、番兵に対してはこれを自動的に行いますから、 番兵で明示的に行う必要はありません。 See Match Data

set-process-sentinel process sentinel Function
この関数は、プロセスprocessに番兵sentinelを対応付ける。 sentinelnilであると、プロセスに番兵はない。 番兵がない場合のデフォルトのふるまいは、 プロセス状態が変化するとプロセスのバッファにメッセージを挿入する。
(defun msg-me (process event)
   (princ
     (format "Process: %s had the event `%s'" process event)))
(set-process-sentinel (get-process "shell") 'msg-me)
     => msg-me
(kill-process (get-process "shell"))
     -| Process: #<process shell> had the event `killed'
     => #<process shell>

process-sentinel process Function
この関数は、プロセスprocessの番兵を返すか、 番兵がなければnilを返す。

waiting-for-user-input-p Function
番兵やフィルタ関数が動作中にこの関数を呼び出すと、 番兵やフィルタ関数を呼び出したときにEmacsがユーザーからの キーボード入力を待ってるとnil以外を返し、 それ以外ではnilを返す。


Node:Transaction Queues, Next:, Previous:Sentinels, Up:Processes

トランザクションキュー

トランザクションを用いたサブプロセスとの通信に トランザクションキュー(transaction queue)を使えます。 まずtq-createを用いて、 指定したプロセスとの通信用トランザクションキューを作成します。 そして、トランザクションを送るためにtq-enqueueを呼び出します。

tq-create process Function
この関数は、プロセスprocessとの通信用トランザクションキューを 作成して返す。 引数processは、バイトストリームを送受信できる機能を 有するサブプロセスであること。 つまり、子プロセスであるか、別のマシン上の可能性もある サーバーへのTCP接続である。

tq-enqueue queue question regexp closure fn Function
この関数はキューqueueにトランザクションを送る。 キューを指定することは、 通信相手のサブプロセスを指定する効果がある。

引数questionは、トランザクションを始める送出メッセージである。 引数fnは、対応する応答が戻ってきたときに呼び出す関数である。 その関数は2つの引数、closureと受け取った応答で呼び出される。

引数regexpは、1つの応答だけに一致する正規表現である。 tq-enqueueが応答の末尾を判定するために使う。

tq-enqueueの戻り値そのものに意味はない。

tq-close queue Function
未処理のトランザクションすべてが完了するのを待ち、 接続や子プロセスを終了して、 トランザクションキューqueueを終える。

トランザクションキューはフィルタ関数を用いて実装してあります。 See Filter Functions


Node:Network, Previous:Transaction Queues, Up:Processes

ネットワーク接続

Emacs Lispプログラムは、同一マシンや別のマシン上の他のプロセスに対して TCPネットワーク接続を開くことができます。 ネットワーク接続は、サブプロセスと同様にLispが扱い、 プロセスオブジェクトとして表現されます。 しかし、通信相手のプロセスはEmacsプロセスの子プロセスではありませんから、 キルしたりシグナルを送ることはできません。 データの送受信のみが可能です。 delete-processは接続を閉じますが、 もう一方の端のプロセスをキルしません。 そのプロセスは、接続が閉じた場合の動作を判断する必要があります。

ネットワーク接続を表すプロセスオブジェクトと サブプロセスを表すプロセスオブジェクトとは、 関数process-statusを使って区別できます。 この関数は、ネットワーク接続に対しては openclosedをつねに返し、 本当のサブプロセスに対してはこれらのいずれの値もけっして返しません。 See Process Information

open-network-stream name buffer-or-name host service Function
この関数は、ホストのサーバーに対するTCP接続を開く。 接続を表すプロセスオブジェクトを返す。

引数nameは、プロセスオブジェクトに付ける名前を指定する。 必要に応じて一意にするために修正される。

引数buffer-or-nameは、接続に対応付けるバッファである。 出力を扱うフィルタ関数を指定しない限り、 接続からの出力はそのバッファに挿入される。 buffer-or-namenilであると、 接続にはバッファを対応付けないことを意味する。

引数hostserviceは、接続先を指定する。 hostはホスト名(文字列)であり、 serviceは定義済みのネットワークサービス(文字列)か ポート番号(整数)である。


Node:System Interface, Next:, Previous:Calendar, Up:Top

オペレーティングシステムとのインターフェイス

本章は、Emacsの起動と終了、 オペレーティングシステムの環境に収められた値の参照方法、 端末入出力とフロー制御についてです。

関連情報についてはSee Building Emacs。 また、端末やスクリーンに関係する オペレーティングシステムの状態情報については、 Displayも参照してください。


Node:Starting Up, Next:, Up:System Interface

Emacsの始動

本節では、Emacsが起動時になにを行うか、および、 それらをカスタマイズする方法について述べます。


Node:Start-up Summary, Next:, Up:Starting Up

概要:始動時の動作手順

Emacsが始動したときに行う(startup.elでの) 処理の順序はつぎのとおりです。

  1. load-pathにある各ディレクトリファイルにおいて subdirs.elという名前のファイルを実行することで load-pathにサブディレクトリを追加する。
  2. LANGなどの環境変数で要求されていれば、 言語環境と端末のコーディングシステムを設定する。
  3. ウィンドウシステムを使用している場合には、 そのウィンドウシステム向けの初期化ライブラリをロードする。 そのライブラリ名はterm/windowsystem-win.elである。
  4. 初期化オプションを処理する。 (初期化オプションの一部は、これより初期の段階で扱われる。)
  5. 必要ならば、ウィンドウフレームとフェイスを初期化する。
  6. ノーマルフックbefore-init-hookを実行する。
  7. オプション-no-site-fileが指定されていなければ、 ライブラリsite-startをロードする。 このライブラリの名前は普通はsite-start.elである。
  8. コマンド行で-q-batchが指定されていなければ、 ファイル~/.emacsをロードする。 オプション-uで、~のかわりに用いるホームディレクトリを持つ 他のユーザー名を指定できる。
  9. inhibit-default-initnil以外でなければ、 ライブラリdefaultをロードする。 (コマンド行で-qを指定したり、 -batchモードでは、これを行わない。) ライブラリのファイル名は普通はdefault.elである。
  10. ノーマルフックafter-init-hookを実行する。
  11. バッファ*scratch*がカレントバッファであり 基本(fundamental)モードであるならば、 initial-major-modeに従ってメジャーモードを設定する。
  12. バッチモードやウィンドウシステムを用いていなければ、 あれば端末固有のLispファイルが存在するならロードする。
  13. inhibit-startup-echo-area-messageで抑制していなければ、 初期メッセージをエコー領域に表示する。
  14. コマンド行の引数を処理する。
  15. term-setup-hookを実行する。
  16. 初期化ファイルの指定に従って 選択されているフレームのパラメータを修正する frame-notice-user-settingsを呼び出す。
  17. window-setup-hookを実行する。 see Window Systems
  18. 未処理のコマンド行引数(上の数手順)がなく、 inhibit-startup-messageの値がnilであり、 バッファが空であれば、 コピーレフト/無保証/基本的な利用情報を表示する。

inhibit-startup-message User Option
この変数は、(無保証などの)初期の始動メッセージを禁止する。 これがnil以外であるとメッセージを表示しない。

始動メッセージの内容に十分慣れたら、 読者個人の初期化ファイルで設定できるようにこの変数がある。 新規ユーザーが受け取るはずである情報を隠してしまうため、 新規ユーザーの初期化ファイルや複数のユーザーに影響するような方法で この変数に設定しないこと。

inhibit-startup-echo-area-message User Option
この変数は、エコー領域に表示する始動メッセージを制御する。 個人のファイル.emacsにつぎのフォームを追加することで エコー領域の始動メッセージを抑制できる。
(setq inhibit-startup-echo-area-message
      "your-login-name")

Emacsは、読者のファイル.emacsで上に示した式を明示的に検査する。 読者のログイン名はLisp文字列定数として式に現れる必要がある。 inhibit-startup-echo-area-messageに同じ値を 設定する別の方法では、始動メッセージを禁止できない。

このように、望むならば自身のためにメッセージを簡単に禁止できるが、 読者の.emacsをむやみにコピーしても、 他人に対してはメッセージを禁止できない。


Node:Init File, Next:, Previous:Start-up Summary, Up:Starting Up

初期化ファイル:.emacs

読者がEmacsを始動すると、Emacsは読者のホームディレクトリから ファイル.emacsを普通はロードしようとします。 このファイルが存在すれば、これにはLispコードを入れておく必要があります。 コマンド行オプション-q-uは、 初期化ファイルの使い方に影響します。 -qは初期化ファイルをロードしないように指示し、 -uは読者の初期化ファイルのかわりに指定したユーザーの初期化ファイルを ロードするように指示します。 See Entering Emacs

デフォルトの初期化ファイルをサイトごとに持てます。 これはdefault.elという名前のライブラリです。 Emacsは、ライブラリを探索する標準パスから ファイルdefault.elを探します (see How Programs Do Loading)。 Emacsの配布には、このファイルは付属していません。 ローカルなカスタマイズのためにサイトで用意します。 バッチモードや-qを指定してある場合を除いて、 デフォルトの初期化ファイルが存在すると、 読者がEmacsを始動するたびにそれをロードします。 しかし、存在するなら、個人の初期化ファイルをさきにロードします。 そこでinhibit-default-initnil以外の値を設定してあると、 Emacsはそのあとファイルdefault.elをロードしません。

サイトごとのカスタマイズ向けの別のファイルはsite-start.elです。 Emacsはユーザーの初期化ファイルをロードするまえに このファイルをロードします。 このファイルのロードを禁止するには オプション-no-site-fileを使います。

site-run-file Variable
この変数は、ユーザーの初期化ファイルよりさきに ロードするべきサイトごとのカスタマイズファイルを指定する。 普通の値は"site-start"である。 実際に効果があるようにこれを変更する唯一の方法は、 Emacsをダンプするまえに行うことである。

読者のファイル.emacsに大量のコードがある場合には、 something.elという名前の別のファイルへコピーして、 それをバイトコンパイルし(see Byte Compilation)、 読者のファイル.emacsでは、load(see Loading)で そのファイルをロードするようにします。

読者のファイル.emacsでよく使われるであろう さまざまなカスタマイズを行う方法の例については、 See Init Examples

inhibit-default-init User Option
この変数は、読者のEmacsセッションにおいては、 デフォルトの初期化ライブラリファイルをロードしないようにする。 その値がnil以外であるとデフォルトライブラリをロードしない。 デフォルト値はnilである。

before-init-hook Variable
すべての初期化ファイル (ユーザーの初期化ファイル、 default.elと/あるいはsite-start.el)を ロードする直前に一度だけ実行するノーマルフック。 (実際の効果があるようにこれを変更する唯一の方法は、 Emacsをダンプするまえに行うことである。)

after-init-hook Variable
すべての初期化ファイル (ユーザーの初期化ファイル、 default.elと/あるいはsite-start.el)をロード直後、 端末固有の初期化のまえに一度だけ実行するノーマルフック。


Node:Terminal-Specific, Next:, Previous:Init File, Up:Starting Up

端末固有の初期化

端末の各種類ごとに、Emacsがその種類の端末で動作するときに Emacsがロードする専用Lispライブラリを持てます。 ライブラリ名は、変数term-file-prefixの値と 端末種類を連結して作ります。 通常、term-file-prefixの値は"term/"であり、 これを変更することは勧めません。 Emacsは通常どおり、load-pathのディレクトリ群において .elc.elの接尾辞でファイルを探します。

端末固有ライブラリの普通の機能は、 Emacsが識別可能なキー列を送るように特別なキーを設定することです。 端末のすべてのファンクションキーがtermcapに入っていない場合には、 function-key-mapを設定したり追加する必要もあります。

端末種類の名前にハイフンが含まれる場合、 ライブラリ名を選ぶうえでは、最初のハイフンよりまえの名前の部分が有効です。 したがって、aaa-48aaa-30-rvのどちらも ライブラリterm/aaaを使います。 必要ならば、ライブラリでは(getenv "TERM")を評価することで 端末種類の完全な名前を得ることができます。

読者のファイル.emacsで 変数term-file-prefixnilを設定すると、 端末固有ライブラリをロードしないようにできます。 この機能は、読者独自のカスタマイズを試すときに有用です。

変数term-setup-hookに設定すれば、 端末固有ライブラリの特定の動作に優先できます。 これは、読者のファイル.emacsと端末固有ライブラリの両者を ロードしたあとの初期化後にEmacsが実行するノーマルフックです。 端末専用ライブラリがない端末向けの初期化を定義するために この変数を使えます。 See Hooks

term-file-prefix Variable
変数term-file-prefixnil以外であると、 Emacsは、つぎのように端末固有の初期化ファイルをロードする。
(load (concat term-file-prefix (getenv "TERM")))

端末固有の初期化ファイルをロードしたくない場合には、 読者のファイル.emacsで 変数term-file-prefixnilを設定する。 それには、読者のファイル.emacs(setq term-file-prefix nil)を入れる。

term-setup-hook Variable
この変数は、読者のファイル.emacs、 (あれば)デフォルトの初期化ファイル、 端末固有のLispファイルをロードしたあとにEmacsが実行する ノーマルフックである。

端末固有ファイルの定義に優先するためにterm-setup-hookを使える。

関連する機能については、 Window Systemswindow-setup-hookを参照してください。


Node:Command Line Arguments, Previous:Terminal-Specific, Up:Starting Up

コマンド行引数

Emacsを始動するときにコマンド行引数を使ってさまざまな動作を要求できます。 一日に一度より多くEmacsを始動する必要はないでしょうし、 しばしばEmacsセッションをそれより長く動かし続けるでしょうから、 コマンド行引数はほとんど使いません。 実際、コマンド行引数を使う癖は避けたほうがよいです。 そのような癖をつけると、Emacsを必要以上に終了したり再始動するからです。 これらのオプションは2つの理由で存在します。 (別のプログラムから起動される)他のエディタと互換性があるようにするのと、 シェルスクリプトから特定のLispプログラムを実行できるようにするためです。

本節では、Emacsがコマンド行引数を処理する方法と、 それらをカスタマイズする方法について述べます。

command-line Function
この関数は、Emacsを呼び出すときに指定されたコマンド行引数を解析して処理し、 ユーザーのファイル.emacsをロードし始動メッセージを表示する。

command-line-processed Variable
この変数の値は、コマンド行引数を一度処理し終えるとtである。

dump-emacsを呼んでEmacsを再ダンプするときには、 この変数にnilを設定すれば、 新たにダンプしたEmacsでコマンド行引数を処理するようにできる。

command-switch-alist Variable
この変数の値は、ユーザー定義のコマンド行オプションの連想リストである。 この変数は、読者が要素を追加できるように存在する。

コマンド行オプション(command line option)は、 つぎの形のコマンド行の引数である。

-option

command-switch-alistの要素はつぎの形である。

(option . handler-function)

handler-functionは、オプションoptionを処理するために呼ばれ、 オプション名を唯一の引数として受け取る。

コマンド行のオプションには引数が続く場合もある。 そのような場合、handler-functionは 変数command-line-args-leftからすべての残りのコマンド行引数を 調べることができる。 (コマンド行引数全体のリストはcommand-line-argsにある。)

コマンド行引数は、ファイルstartup.elの 関数command-line-1が解析する。 Command Argumentsも参照。

command-line-args Variable
この変数の値は、Emacsに渡されたコマンド行引数のリストである。

command-line-functions Variable
この変数の値は、認識できないコマンド行引数を処理する関数のリストである。 つぎに処理する引数に特別な意味がないと、 このリストの関数をnil以外の値を返すまで現れる順に呼び出す。

これらの関数は引数なしで呼び出される。 これらの関数では、呼び出し時に束縛される変数argiを介して 対象となるコマンド行引数を参照できる。 (いま対象となっている引数を除く)残りの引数は 変数command-line-args-leftにある。

関数がargiを認識して処理したときには、 その引数を処理したことを表すためにnil以外の値を返すこと。 後続の引数の一部も処理した場合には、 command-line-args-leftから それらを削除することで処理したことを示せる。

これらの関数すべてがnilを返すと、 訪問するファイル名として引数を用いる。


Node:Getting Out, Next:, Previous:Starting Up, Up:System Interface

Emacsから抜ける

Emacsから抜けるには2つの方法があります。 Emacsを終了するためにEmacsジョブをキルするか、 あとでEmacsを継続できるように休止します。 実用上は、ログアウトするとき以外にはEmacsをほとんど終了しないでしょう。 Emacsを休止するほうが一般的です。


Node:Killing Emacs, Next:, Up:Getting Out

Emacsの終了

Emacsを終了するとは、Emacsプロセスの実行を終らせることを意味します。 親プロセスが普通は制御を取り戻します。 Emacsを終了するための下位の基本関数はkill-emacsです。

kill-emacs &optional exit-data Function
この関数は、Emacsプロセスを終了しEmacsを終える。

exit-dataが整数であると、Emacsプロセスの終了状態として使われる。 (これは主にバッチ処理で有用である。 Batch Modeを参照。)

exit-dataが文字列であると、 その内容を端末入力バッファへ詰め込み、 シェル(やつぎに入力を読むプログラム)がそれらを読み取れるようにする。

保存済みのファイルを除くEmacsプロセス内のすべての情報は、 Emacsを終了すると失われます。 Emacsを不注意に終了すると多くの作業を失うことになるので、 保存する必要があるバッファがあったり動作中のサブプロセスがあると、 Emacsは確認を求めます。 これは関数save-buffers-kill-emacsが行います。

kill-emacs-query-functions Variable
標準的な問い合わせをしたあとで、 save-buffers-kill-emacsは、 リストkill-emacs-query-functions内の関数を 現れる順に引数なしで呼び出す。 これらの関数では、ユーザーにさらなる確認を求めることができる。 これらのどれかがnilを返すと、Emacsは終了しない。

kill-emacs-hook Variable
この変数はノーマルフックである。 save-buffers-kill-emacsがファイルをすべて保存し確認し終えると、 このフックの関数群を実行する。


Node:Suspending Emacs, Previous:Killing Emacs, Up:Getting Out

Emacsの休止

Emacsを休止するとは、Emacsを一時的に停止し、 普通はシェルである親プロセスに制御を戻すことです。 これにより、あとで同じEmacsプロセスで、つまり、同じバッファ群、 同じキルリング、同じアンドゥ履歴などで編集を再開できます。 Emacsを再開するには、親シェルにおいて ほとんどの場合fgなどの適切なコマンドを使います。

ジョブの休止を扱えないオペレーティングシステムもあります。 そのようなシステムでは、『休止』はEmacsのサブプロセスとして 一時的に新たなシェルを実際には作成します。 そのシェルを終了するとEmacsに戻ります。

ウィンドウシステムを使っている場合には、 Emacsジョブを再開する親プロセスがいないかもしれませんし、 別のウィンドウへ移動すれば別のジョブへ入力できますから、 Emacsの休止は有用ではありません。 したがって、Emacsがウィンドウシステムを使っている場合には、 休止できません。

suspend-emacs string Function
この関数は、Emacsを休止し、親プロセスへ制御を戻す。 親プロセスがEmacsを再開した場合にのみ、 suspend-emacsはLisp内の呼び出し側へnilを返す。

stringnil以外であると、 Emacsの親シェルが端末入力として読めるようにその文字群を送る。 親シェルはstringの文字群を表示せず、 その結果のみが現れる。

休止するまえに、suspend-emacsは ノーマルフックsuspend-hookを実行する。

ユーザーがEmacsを再開すると、suspend-emacsは ノーマルフックsuspend-resume-hookを実行する。 see Hooks

再開後のつぎの再表示では、 変数no-redraw-on-reenternilならば スクリーン全体を再描画する。 (see Refresh Screen)。

つぎの例では、Emacsを休止してもpwdは表示されないことに注意。 しかし、シェルはそれを読み取って実行する。

(suspend-emacs)
     => nil

(add-hook 'suspend-hook
          (function (lambda ()
                      (or (y-or-n-p
                            "Really suspend? ")
                          (error "Suspend cancelled")))))
     => (lambda nil
          (or (y-or-n-p "Really suspend? ")
              (error "Suspend cancelled")))
(add-hook 'suspend-resume-hook
          (function (lambda () (message "Resumed!"))))
     => (lambda nil (message "Resumed!"))
(suspend-emacs "pwd")
     => nil
---------- Buffer: Minibuffer ----------
Really suspend? y
---------- Buffer: Minibuffer ----------

---------- Parent Shell ----------
lewis@slug[23] % /user/lewis/manual
lewis@slug[24] % fg

---------- Echo Area ----------
Resumed!

suspend-hook Variable
この変数は、休止するまえに実行されるノーマルフックである。

suspend-resume-hook Variable
この変数は、再開後に実行されるノーマルフックである。


Node:System Environment, Next:, Previous:Getting Out, Up:System Interface

オペレーティングシステム環境

Emacsでは、さまざまな関数を介して オペレーティングシステム環境の変数を参照できます。 これらの変数には、システムの名前、ユーザーの識別番号UIDなどが 含まれます。

system-configuration Variable
この変数は、読者のシステムのハードウェア/ソフトウェア構成に対する GNUの構成名を文字列で保持している。 この文字列の一部分を検査する簡便な方法は string-matchを使うことである。

system-type Variable
この変数の値は、Emacsが動作している オペレーティングシステムの種類を表すシンボルである。 つぎに可能な値の一覧を示す。
alpha-vms
Alphaマシン上のVMS。
aix-v3
AIX。
berkeley-unix
バークレーBSD。
dgux
データジェネラルDGUXオペレーティングシステム。
gnu
(HURDかMachから成るGNUカーネルを使っている)GNUシステム。
gnu/linux
GNU/Linuxシステム。 つまり、Linuxカーネルを用いたGNUシステムの変種。 (これらのシステムは人々が『Linux』と呼ぶものの1つであるが、 Linxuは実際にはカーネルのみであり、システム全体ではない。)
hpux
ヒューレットパッカードHPUXオペレーティングシステム。
irix
シリコングラフィックスIrixシステム。
ms-dos
マイクロソフトMS-DOS『オペレーティングシステム』。
next-mach
NeXTのMachベースのシステム。
rtu
マスコンプRTU、UCBユニバース。
unisoft-unix
ユニソフトUniPlus。
usg-unix-v
AT&T System V。
vax-vms
VAX VMS。
windows-nt
マイクロソフトWindows NT。
xenix
SCO Xenix 386。

絶対に必要でない限り、細分類のために新たなシンボルを追加したくない! 実際、将来にはこれらのいくつかを削除することを願っている。 オペレーティングシステムの違いを区別するには、 system-configurationを使うことを勧める。

system-name Function
この関数は読者が使っているマシンの名前を返す。
(system-name)
     => "www.gnu.org"

シンボルsystem-nameは、関数としても変数としても使えます。 実際、関数としては、変数system-nameが現在保持している値を返します。 したがって、Emacsが読者のシステム名に関して混乱している場合には、 変数system-nameに設定できます。 変数はフレームタイトルの作成にも有用です(see Frame Titles)。

mail-host-address Variable
この変数がnil以外であると、system-nameのかわりに 電子メイルアドレスの生成に使われる。 たとえば、user-mail-addressのデフォルト値の作成に使われる。 see User Identification。 (これはEmacsの始動時に行われるため、 Emacsをダンプしたときの値が実際に使われる値である。 see Building Emacs)。

getenv var Function
この関数は、環境変数varの値を文字列で返す。 Emacs内部では、環境変数の値はLisp変数process-environmentに 保持されている。
(getenv "USER")
     => "lewis"

lewis@slug[10] % printenv
PATH=.:/user/lewis/bin:/usr/bin:/usr/local/bin
USER=lewis
TERM=ibmapa16
SHELL=/bin/csh
HOME=/user/lewis

setenv variable value コマンド
このコマンドは、環境変数variableに値valueを設定する。 どちらの引数も文字列である。 この関数はprocess-environmentを修正することで動作する。 この変数をletで束縛しても十分に実用的である。

process-environment Variable
この変数は、各要素が1つの環境変数を記述する文字列のリストである。 関数getenvsetenvは、この変数を用いて動作する。
process-environment
=> ("l=/usr/stanford/lib/gnuemacs/lisp"
    "PATH=.:/user/lewis/bin:/usr/class:/nfsusr/local/bin"
    "USER=lewis"
    "TERM=ibmapa16"
    "SHELL=/bin/csh"
    "HOME=/user/lewis")

path-separator Variable
この変数は、(環境変数などで)探索パスを 区切る文字を指定する文字列を保持する。 UNIXとGNUシステムではその値は":"であり、 MS-DOSとWidows NTでは";"である。

invocation-name Variable
この変数は、起動したEmacsのプログラム名を保持する。 値は文字列であり、ディレクトリ名は含まない。

invocation-directory Variable
この変数は、起動したEmacsの実行形式のディレクトリを保持する。 ディレクトリを判別できない場合にはnilである。

installation-directory Variable
nil以外であると、サブディレクトリlib-srcetcを 探すためのディレクトリである。 Emacsがこれらのディレクトリを標準のインストールディレクトリで みつけられなくてもEmacsの実行形式になんらかの意味で 関連するディレクトリでみつけられれば、nil以外である。

load-average &optional use-float Function
この関数は、1分間/5分間/15分間のロードアベレッジ (負荷平均)をリストで返す。

デフォルトでは、これらの値は、動作しようとしてるプロセスの平均個数を表す システムのロードアベレッジを100倍した整数である。 use-floatnil以外であると、 100倍しない浮動小数点数で返す。

(load-average)
     => (169 48 36)
(load-average t)
     => (1.69 0.48 0.36)

lewis@rocky[5] % uptime
 11:55am  up 1 day, 19:37,  3 users,
 load average: 1.69, 0.48, 0.36

emacs-pid Function
この関数は、Emacsプロセスのプロセス番号IDを返す。

tty-erase-char Variable
この変数は、Emacsが始動するまえに システムの端末ドライバが選んでいた消去文字を保持する。

setprv privilege-name &optional setp getprv Function
この関数は、(UNIX上には存在しない)VMS基本操作を設定/再設定する。 最初の引数は文字列で表した基本操作の名前である。 第2引数setptnilであり、 基本操作をオンにするかオフにするかを表す。 デフォルトはnilである。 関数は、成功すればtを返し、さもなければnilを返す。

第3引数getprvnil以外であると、 setprvは基本操作を変更しないが、 その基本操作が現在オンであるかオフであるかを表す tnilを返す。


Node:User Identification, Next:, Previous:System Environment, Up:System Interface

ユーザーの識別

init-file-user Variable
この変数は、Emacsが使用すべきユーザー初期化ファイルを指定する。 あるいは、そのようなものがなければnilである。 この値は、-q-u userの コマンド行オプションを反映する。

カスタマイズファイルや他の種類のユーザープロフィールを ロードするLispパッケージは、それらを探す場所を判断するために この変数に従うこと。 この変数のユーザー名のカスタマイズをロードするべきである。 init-file-usernilであると オプション-qが使われたことを意味し、 Lispパッケージはいかなるカスタマイズファイルや ユーザープロフィールもロードしないこと。

user-mail-address Variable
これは、Emacsを使用しているユーザーの通常の電子メイルアドレスを保持する。 Emacsは通常、読者の初期化ファイルを読み取ったあと、 この変数が未設定であるとデフォルト値を設定する。 したがって、デフォルト値を使いたくない場合には、 読者のファイル~/.emacsで別の値に設定できる。

user-login-name &optional uid Function
uidを指定しないと、 この関数はログインしたユーザー名を返す。 環境変数LOGNAMEが設定されていればその値を使う。 さもなければ、環境変数USERが設定されていればその値を使う。 さもなければ、実UIDではなく実効UIDに基づいた値である。

UIDを指定すると、値は(整数である)UIDに 対応するユーザー名である。

(user-login-name)
     => "lewis"

user-real-login-name Function
この関数は、Emacsの実UIDに対応するユーザー名を返す。 これは、実効UIDや環境変数LOGNAMEUSERを無視する。

user-full-name &optional uid Function
この関数は、ログインしたユーザーの氏名を返す。 あるいは、環境変数NAMEが設定してあればその値を返す。
(user-full-name)
     => "Bil Lewis"

uidnil以外であると、 それは整数のユーザー番号か文字列のログイン名であること。 すると、user-full-nameは、 そのユーザー番号かログイン名に対応するユーザーの氏名を返す。

シンボルuser-login-nameuser-real-login-nameuser-full-nameは、関数でもある変数です。 関数としては、その変数が保持する値と同じ値を返します。 これらの変数により、関数として返す値を指定しておくことで Emacsを『ごまかせ』ます。 これらの変数は、フレームタイトルの作成にも有用です (see Frame Titles)。

user-real-uid Function
この関数は、ユーザーの実UIDを返す。
(user-real-uid)
     => 19

user-uid Function
この関数は、ユーザーの実効UIDを返す。


Node:Time of Day, Next:, Previous:User Identification, Up:System Interface

時刻

本節では、現在時刻と時刻帯(タイムゾーン)を調べる方法を説明します。

current-time-string &optional time-value Function
この関数は、人間向けの文字列で現在時刻と日付を返す。 文字列の書式は不変であり、各部分の文字数はつねに同じなので、 各部分を取り出すのにsubstringを使っても問題ない。 将来、文字列の末尾に追加情報を付加することもあるので、 文字列の末尾からではなく先頭から文字を数えるほうがよい。

引数time-valueを指定すると、 それは現在時刻のかわりに書式付けする時刻を指定する。 引数は、最初の2つの要素が整数であるリストであること。 したがって、current-time(下記参照)や file-attributes(see File Attributes)で得た時刻を使える。

(current-time-string)
     => "Wed Oct 14 22:21:05 1987"

current-time Function
この関数は、システムの時刻の値を 3つの整数のリスト(high low microsec)で返す。 整数highlowを組み合わせると 1970年1月1日0:00からの経過秒数を与える。 つまり、経過秒数は

第3要素microsecは、現在の秒内のミリ秒を表す (返す時間精度が秒のシステムでは0)。

最初の2つの要素は、関数file-attributesで得られる ファイルに関する時刻の値と比較できる。 see File Attributes

current-time-zone &optional time-value Function
この関数は、ユーザーの地域の時刻帯を記述するリストを返す。

値は、(offset name)の形である。 ここで、offsetはUTC 11 に対して進んでいる(グリニッジの東)秒数を 与える整数である。 第2要素nameは、その時刻帯の名称を与える文字列である。 夏時間制が始まったり終ると、どちらの要素も変わる。 時刻帯には季節の時刻調整はないとユーザーが指定すると、 どちらの値も定数である。

値を計算するために必要な情報をオペレーティングシステムから得られないと リストのどちらの要素もnilである。

引数time-valueを指定すると、 現在時刻のかわりに分析すべき時刻を指定する。 引数は、2つの整数を収めたコンスセルであるか、 最初の2つの要素が整数であるリストであること。 したがって、current-time(上記参照)や file-attributes(see File Attributes)で得た時刻を使える。


Node:Time Conversion, Next:, Previous:Time of Day, Up:System Interface

時刻の変換

これらの関数は、時刻の値(2つか3つの整数から成るリスト)を 文字列や日時情報に変換します。 日時情報を時刻の値に変換する関数もあります。 時刻の値は、関数current-time(see Time of Day)や file-attributes(see File Attributes)で得られます。

多くのオペレーティングシステムでは、時刻の値を32ビットに制限しています。 これらのシステムでは、典型的には協定世界時1901年12月13日20:45:52から 2038年1月19日03:14:07までしか表現できません。 しかし、より大きな時刻の値を扱い、 より広い範囲の過去から未来を表現できるシステムもあります。

時刻変換関数は、グレゴリオ暦を導入するまえであっても つねにグレゴリオ暦を使います。 紀元前1年からの経過年数を数え、通常のグレゴリオ暦のように0年を飛ばしません。 たとえば、-37年は、グレゴリオ暦紀元前38年を表します。

format-time-string format-string time Function
この関数は、timeformat-stringに従って文字列に変換する。 引数format-stringには、時刻のさまざまな部分で置き換えられる %列を含んでよい。 %列の意味を以下に示す。
%a
曜日の省略名を表す。
%A
曜日の(省略しない)名称を表す。
%b
月の省略名を表す。
%B
月の(省略しない)名称を表す。
%c
%x %Xの同義語。
%C
これにはローケル固有の意味がある。 デフォルトのローケル(C)では、%A, %B %e, %Yと等価。
%d
ゼロでパディングした月内の日。
%D
%m/%d/%yの同義語。
%e
空白でパディングした月内の日。
%h
%bの同義語。
%H
時(00-23)を表す。
%I
時(00-12)を表す。
%j
年内の日(001-366)を表す。
%k
空白でパディングした時(0-23)を表す。
%l
空白でパディングした時(0-12)を表す。
%m
月(01-12)を表す。
%M
分(00-59)を表す。
%n
改行を表す。
%p
AMPMの適切なほうを表す。
%r
%I:%M:%S %pの同義語。
%R
%H:%Mの同義語。
%S
秒(00-60)を表す。
%t
タブ文字を表す。
%T
%H:%M:%Sの同義語。
%U
日曜日を週の始まりと仮定した年内の週(01-52)を表す。
%w
数字で表した曜日(0-6)。 日曜日を0とする。
%W
月曜日を週の始まりと仮定した年内の週(01-52)を表す。
%x
これにはローケル固有の意味がある。 デフォルトのローケル(C)では、%Dと等価。
%X
これにはローケル固有の意味がある。 デフォルトのローケル(C)では、%Tと等価。
%y
年の下2桁(00-99)を表す。
%Y
100年単位の年を表す。
%Z
時刻帯の省略名を表す。

これらの%列には、桁数やパディングの種類も指定できる。 printfと同様に動作し、 %列のあいだに桁数を数字で指定する。 桁数を0で始めるとゼロでパディングすることを意味する。 桁数を_で始めると空白でパディングすることを意味する。

たとえば、%Sは分内の秒数を指定し、 %03Sはゼロでパディングして3桁にすることを意味し、 %_3Sは空白でパディングして3桁にすることを意味する。 %Sは普通はパディングして2桁にするため、 %3Sだけであるとゼロでパディングする。

decode-time time Function
この関数は、時刻の値を日時情報に変換する。 戻り値は、つぎの9要素のリストである。
(seconds minutes hour day month year dow dst zone)

各要素の意味はつぎのとおりである。

sec
0から59の整数で表した分内の秒数。
minute
0から59の整数で表した時内の分数。
hour
0から23の整数で表した日内の時。
day
1から31の整数で表した月内の日。
month
1から12の整数で表した年内の月。
year
年。 典型的には1900より大きい。
dow
日曜日を0とした0から6の整数で表した曜日。
dst
夏時間制が有効であるとt、さもなければnil
zone
グリニッジから東周りではかった時刻帯を表す秒数。

Common Lispに関した注意: Common Lispでは、dowzoneの意味が異なる。

encode-time seconds minutes hour day month year &optional ...zone Function
この関数はdecode-timeの逆である。 7項目から成る日時情報を時刻の値に変換する。 引数の意味については、上記decode-timeの一覧を参照。

100未満の年は普通の年として扱う。 それらを1900年代として扱いたい場合には、 encode-timeを呼び出すまえに修正しておくこと。

省略可能な引数zoneのデフォルトは、 現在の時刻帯とその夏時間制の規則である。 指定する場合には、(current-time-zoneで得られるような)リストであるか、 環境変数TZと同じ形式の文字列であるか、 (decode-timeで得られるような)整数であること。 指定した時刻帯は、夏時間の補正をせずに使われる。

encode-timeに7引数より多く渡すと、 始めの6つをsecondsからyearまでに、 最後の引数をzoneに使い、そのあいだの引数は無視する。 この機能は、decode-timeが返したリストの要素を つぎのようにしてencode-timeの引数に使うことを可能にする。

(apply 'encode-time (decode-time ...))

引数secminutehourdaymonthの 値が範囲外になるようにすると単純な日時演算を行える。 たとえば、0日はその月のまえの日を意味する。

オペレーティングは可能な時刻の値の範囲を制限する。 その範囲を越える時刻を符号化しようとするとエラーになる。


Node:Timers, Next:, Previous:Time Conversion, Up:System Interface

遅延実行のためのタイマ

未来のある時刻に関数を呼び出したり、 ある一定期間なにもしないでいたら関数を呼び出すために タイマを設定できます。

Emacsは、Lispプログラムの任意の箇所ではタイマを実行できません。 サブプロセスからの出力を受け取るときにだけタイマを実行できます。 つまり、待つことが可能sit-forread-eventなどの 基本関数の内側や(入力を)待っているあいだに実行できます。 したがって、Emacsが忙しいとタイマの実行が遅れることがあります。 しかし、Emacsが暇ならば、タイマの実行はとても正確です。

run-at-time time repeat function &rest args Function
この関数は、時刻timeに引数argsで 関数functionを呼び出すように予約する。 引数functionはのちに呼び出される関数であり、 引数argsはそれを呼び出すときに与える引数である。 時刻timeは文字列で指定する。

絶対時刻をさまざまな書式で指定できる。 この関数は、よく使われる日時の書式を受け付けるように努める。 正しい書式にはつぎの2つを含む。

year-month-day hour:min:sec timezone

hour:min:sec timezone month/day/year

ここで、どちらの例のフィールドもすべて数である。 current-time-stringが返す書式、および、 他の書式も許される。

相対時刻を指定するには、単位を伴った数字を使う。 たとえばつぎのとおり。

1 min
今から1分後。
1 min 5 sec
今から65秒後。
1 min 2 sec 3 hour 4 day 5 week 6 fortnight 7 month 8 year
今からちょうど103ヵ月、123日、10862秒後。 12

timeが数(整数か浮動小数点数)であれば、 秒単位の相対時刻を指定する。

引数repeatは、呼び出しをどの程度頻繁に繰り返すかを指定する。 repeatnilであると、繰り返さずに 時刻timeに関数functionを一度だけ呼び出す。 repeatが数であると、繰り返し間隔を秒単位で指定する。

ほとんどの場合、最初の呼び出しではrepeatの効果はなく、 timeだけが時刻を指定する。 1つ例外があり、timetであると、 時刻がrepeatの整数倍であるとタイマを実行する。 これはdisplay-timeのような関数に有用である。

関数run-at-timeは、予約した未来の特定の動作を 識別するタイマを返す。 この値は、cancel-timer(下記参照)の呼び出しに使える。

with-timeout (seconds timeout-forms...) body... Macro
bodyを実行するが、seconds秒でその実行を諦める。 時間が切れるまえにbodyが終了すると with-timeoutbodyの最後のフォームの値を返す。 しかし、時間が切れるとbodyの実行を取り止め、 with-timeouttimeout-formsをすべて実行し、 それらの最後の値を返す。

このマクロは、seconds秒後に動作するタイマを設定することで動作する。 その時間内にbodyが終了すれば、タイマを取り消す。 タイマが実際に動作するとbodyの実行を終了させてから、 timeout-formsを実行する。

プログラムから待つことが可能な基本関数を呼び出したときにのみ、 タイマはLispプログラム内で実行可能なため、 with-timeoutbodyの計算途中では bodyの実行を停止できない。 それらが待つことが可能な基本関数の1つを呼び出したときにのみ停止できる。 したがって、長い計算を行わない入力を待つようなbodywith-timeoutを使う。

関数y-or-n-p-with-timeoutは、 応答を長く待ちすぎないようにタイマを使った単純な例です。 See Yes-or-No Queries

run-with-idle-timer secs repeat function &rest args Function
Emacsがsecs秒間なにもしないときに実行するタイマを設定する。 secsの値は整数でも浮動小数点数でもよい。

repeatnilであると、 これ以降にはじめてEmacsが十分長い期間なにもしないでいると、 タイマを一度だけ実行する。 しばしばrepeatnil以外であり、 Emacsがsecs秒なにもしないでいるたびに タイマを実行することを意味する。

関数run-with-idle-timerは、 cancel-timer(下記参照)の呼び出しに使えるタイマの値を返す。

Emacsがユーザー入力を待ち始めると『アイドル状態』になり、 なにか入力がくるまでアイドル状態のままです。 5秒間のアイドル状態で動作するタイマがあったとすると、 Emacsがアイドルになってから約5秒後にそのタイマが実行されます。 しかしrepeatが真(nil以外)であったとしても、 そのタイマはEmacsがアイドル状態であり続ける限りは再実行されません。 アイドル状態の期間は単調に増加するので、再度5秒後には戻りません。

Emacsがアイドル状態のときにはさまざまなことを行います。 ガベッジコレクション、自動保存、サブプロセスからのデータの処理です。 しかし、アイドル状態中のこれらの動作はアイドルタイマに干渉しません。 アイドル状態の時間を0にしないからです。 600秒に設定されたアイドルタイマは、 最後のユーザーコマンドを終了してから10分後に実行されます。 たとえその10分間に、サブプロセスの出力を何千回も受け取ろうが、 ガベッジコレクションや自動保存を行ったとしてもです。

ユーザーが入力を与えると、その入力を実行中はEmacsは非アイドル状態です。 そして再度アイドル状態になり、 繰り返すように設定されたアイドルタイマを1つずつそれ以降に実行します。

cancel-timer timer Function
タイマtimerの予約を取り消す。 timerは、以前にrun-at-timerun-with-idle-timerが返した値であること。 これは、run-at-timeの呼び出しの効果を取り消し、 その時刻になってもなにも特別なことは起こらない。


Node:Terminal Input, Next:, Previous:Timers, Up:System Interface

端末入力

本節では、端末入力を記録したり処理する関数や変数について述べます。 関連する関数についてはDisplayを参照してください。


Node:Input Modes, Next:, Up:Terminal Input

入力方式

set-input-mode interrupt flow meta quit-char Function
この関数は、キーボード入力を読み取るモードを設定する。 interruptnil以外であると、 Emacsは入力割り込みを用いる。 nilであると、CBREAKモードを用いる。 デフォルトの設定はシステムに依存する。 この指定に関わらずつねにCBREAKモードを用いるシステムもある。

EmacsがXと直接通信しているときは、 通信方法が割り込みであると承知していると この引数を無視して割り込みを使う。

flownil以外であると、 Emacsは端末出力にフロー制御XON/XOFFC-qC-s)を用いる。 CBREAKモード以外ではこれの効果はない。 see Flow Control

引数metaは、文字コードが127を越える入力文字の扱い方を制御する。 metatであると、8ビット目が立っている文字を メタ文字に変換する。 metanilであると、8ビット目を無視する。 パリティビットを用いる端末では、これが必要である。 metatでもnilでもないと、 Emacsは入力した8ビットすべてを無変更で使う。 8ビット文字集合を使う端末には、これがよい。

quit-charnil以外であると、 中断に使用する文字を指定する。 通常、この文字はC-gである。 see Quitting

関数current-input-modeは、Emacsが現在使用している 入力モードの設定を返します。

current-input-mode Function
この関数は、キーボード入力を読み取るための現在のモードを返す。 set-input-modeの引数に対応する (interrupt flow meta quit)の形の リストを返す。 各要素の意味はつぎのとおりである。
interrupt
nil以外であると、Emacsは割り込み駆動の入力を用いている。 nilであると、EmacsはCBREAKモードを用いている。
flow
nil以外であると、 Emacsは端末出力にフロー制御XON/XOFFC-qC-s) を用いている。 この値は、interruptnilの場合にのみ意味を持つ。
meta
Emacsが入力文字の8ビット目をメタビットとして扱うときにはtである。 Emacsが各入力文字の8ビット目をつねに0にするときにはtである。 さもなければ、Emacsは文字コードとして8ビットすべてを使っている。
quit
現在Emacsが中断に使っている文字であり、普通はC-gである。


Node:Translating Input, Next:, Previous:Input Modes, Up:Terminal Input

入力イベントの変換

本節では、入力イベントをキー列の一部になるまえに別の 入力イベントに変換する機能について述べます。 これらの機能は、ここに述べる順に各イベントに適用されます。 つまり、各イベントはまずextra-keyboard-modifiersに従って修正され、 つぎに(適切ならば)keyboard-translate-tableを介して変換され、 最後に指定されているキーボードコーディングシステムで復号化されます。 キー列の一部として読み取られるイベントであると、 読み取られるキー列に追加され、それを含む部分キー列を まずfunction-key-mapで検査してから、 つぎにkey-translation-mapで検査します。

extra-keyboard-modifiers Variable
この変数は、Lispプログラムがキーボード上の 修飾キーを『押す』ことができるようにする。
1
<SHIFT>キー。
2
<LOCK>キー。
4
<CTL>キー。
8
<META>キー。

ユーザーがキーボードのキーを打つたびに、 ビットマスクで指定した修飾キーが押し下げられているかのように キーを修正する。

ウィンドウシステムを使っているときには、 プログラムは任意の修飾キーを『押す』ことができる。 さもなければ、<CTL>と<META>のキーのみを 仮想的に押すことができる。

keyboard-translate-table Variable
この変数は、キーボード文字の変換表である。 これにより、コマンドのバインディングを変更せずに、 キーボードのキー配置を変更できる。 その値は普通は文字テーブルであるか、あるいは、nilである。

keyboard-translate-tableが文字テーブルであると、 キーボードから読み取った各文字をこの文字テーブルで探す。 みつけた値がnil以外であると、 実際の入力文字のかわりにその値を使う。

つぎの例では、keyboard-translate-tableに文字テーブルを設定する。 そして、文字C-sC-\C-qC-^を入れ換える。 これ以降、C-\を打つとC-sを打った効果があり、 その逆もそうである。 (この話題に関しては詳しくは、see Flow Control。)

(defun evade-flow-control ()
  "Replace C-s with C-\ and C-q with C-^."
  (interactive)
  (setq keyboard-translate-table
        (make-char-table 'keyboard-translate-table nil))
  ;; C-sC-\を入れ換える
  (aset keyboard-translate-table ?\034 ?\^s)
  (aset keyboard-translate-table ?\^s ?\034)
  ;; C-qC-^を入れ換える
  (aset keyboard-translate-table ?\036 ?\^q)
  (aset keyboard-translate-table ?\^q ?\036))

この変換は、端末から読み取った文字に最初に行われる変換である。 recent-keysのような記録機能やドリブルファイルは、 変換後の文字を記録する。

keyboard-translate from to Function
この関数は、文字コードfromを文字コードtoに変換するように keyboard-translate-tableを変更する。 必要ならばキーボード変換表を作成する。

残りの変換機能は、読み取ったキー列の部分列を変換します。 それらはread-key-sequenceに実装されていて、 read-eventで読む入力には効果はありません。

function-key-map Variable
この変数は、普通の文字端末上のファンクションキーが 送出する文字の列を記述したキーマップを保持する。 このキーマップは他のキーマップと同じ構造であるが、使い方が異なる。 キー列のバインディングではなく、 読み取りつつあるキー列を変換する方法を指定する。

function-key-mapがキー列kを ベクトルvに『バインド』すると、 キー列のどこにkが現れても、 vのイベントで置き換える。

たとえば、端末VT100は、キーパッドのキー<PF1>を押すと <ESC> O Pを送出する。 したがって、Emacsではこの列を1つのイベントpf1に変換したい。 VT100を使っているときにfunction-key-mapにおいて <ESC> O P[pf1]に『バインド』すれば、 これを行える。

つまり、C-c <PF1>を打つと 文字の列C-c <ESC> O Pが送出される。 のちに関数read-key-sequenceがこれをC-c <PF1>に戻し、 ベクトル[?\C-c pf1]を返す。

マイナモード/ローカル/グローバルのキーマップに矛盾するような function-key-map内の項目は無視される。 この意図は、ファンクションキーが送出する文字の列には それ独自のキーバインディングがあるべきではなく、 もしあったとしても、もとの定義を優先することである。

function-key-mapの値は、 端末のterminfoやtermcapの情報に従って自動的に普通は設定されるが、 端末固有のLispファイルの助けが必要な場合もある。 Emacsには、一般的な多くの端末向けの端末固有ファイルがある。 それらの主目的は、terminfoやtermcapから推定できないものを function-key-mapに定義することである。 see Terminal-Specific

key-translation-map Variable
この変数は、function-key-mapと同様に 入力イベントを別の入力イベントへ変換するために用いる別のキーマップである。 function-key-mapとは2つの意味で異なる。
  • key-translation-mapは、 function-key-mapの変換後に使われる。 function-key-mapによる変換結果を使う。
  • key-translation-mapは、実際のキーバインディングに優先する。 たとえば、key-translation-mapC-x fにバインディングがあると、 グローバルマップにC-x fのバインディングがあったとしても 変換結果が効果を持つ。

key-translation-mapの意図は、 self-insert-commandに普通はバインドされる通常の文字を含めて ユーザー向けに文字集合を別の文字集合に 対応付けられるようにすることである。

キーの『変換として』キー列のかわりに関数を用いると、 function-key-mapkey-translation-mapは 単なる配置替え以上のことに使えます。 その関数で当該キーの変換を計算するのです。

キー変換関数は1つの引数を受け取ります。 その引数は、read-key-sequenceで指定されたプロンプトか、 エディタコマンドループがキー列を読み取っている場合にはnilです。 多くの場合、プロンプトの値は無視できます。

関数自身が入力を読むときには、 後続のイベントを変更することもできます。 たとえば、後続の文字をハイパー文字にするC-c hの定義は つぎのようになります。

(defun hyperify (prompt)
  (let ((e (read-event)))
    (vector (if (numberp e)
                (logior (lsh 1 24) e)
              (if (memq 'hyper (event-modifiers e))
                  e
                (add-event-modifier "H-" e))))))

(defun add-event-modifier (string e)
  (let ((symbol (if (symbolp e) e (car e))))
    (setq symbol (intern (concat string
                                 (symbol-name symbol))))
    (if (symbolp e)
        symbol
      (cons symbol (cdr e)))))

(define-key function-key-map "\C-ch" 'hyperify)

set-keyboard-coding-systemを用いた キーボード文字集合の復号化を有効にしているときには、 上に述べた変換を終えてから復号化を行います。 See Specifying Coding Systems。 Emacsの将来の版では、他の変換のまえに復号化を行うでしょう。


Node:Recording Input, Previous:Translating Input, Up:Terminal Input

入力を記録する

recent-keys Function
この関数は、キーボードやマウスからの最近の100個の入力イベントを収めた ベクトルを返す。 キー列として使われたかどうかに関わらず、すべてのイベントを含む。 したがって、キーボードマクロで生成したイベントを数えずに 最後の100個のイベントをつねに得ることになる。 (キーボードマクロで生成したイベントを省くのは、 それらはデバッグにはあまり役立たないからである。 キーボードマクロを起動したイベントが見えれば十分なはずである。)

open-dribble-file filename コマンド
この関数は、filenameという名前のドリブルファイル (dribble file)をオープンする。 ドリブルファイルをオープンしていると、 (キーボードマクロを除く)キーボードやマウスからの各入力イベントを そのファイルに書き出す。 文字でないイベントは、その表示表現を<...>で囲って表す。

ドリブルファイルをクローズするには、 引数にnilを指定してこの関数を呼び出す。

この関数は、バグ報告のために Emacsのバグを引き起こす入力を記録するために普通は使う。

(open-dribble-file "~/dribble")
     => nil

関数open-termscript(see Terminal Output)も 参照してください。


Node:Terminal Output, Next:, Previous:Terminal Input, Up:System Interface

端末出力

端末出力関数は、端末に出力を送ったり、 端末へ送った出力を記録します。 変数baud-rateは、Emacsが考えている端末の出力速度を表します。

baud-rate Variable
この変数の値は、Emacsが関知する端末の出力速度である。 この変数に設定しても実際のデータ転送速度を変更しないが、 その値はパディングなどの計算に用いられる。 また、ウィンドウシステムを使っている場合であっても、 スクリーンのどの部分をスクロールするか、 あるいは、再描画するかの決定に影響する。 (このような決定を調整する方法を与えるために、 ウィンドウシステムには真の『出力速度』はないがこのように設計した。)

値の単位はボー(baud)である。

ネットワーク経由で使い、 ネットワークの異なる部分が異なる速度で動いているときには、 Emacsが返す値はローカル端末で使っている場合の値と異なるかもしれません。 リモートマシンへの通信速度でローカル端末と通信する ネットワークプロトコルもあり、 そのような場合、Emacsや他のプログラムは正しい値を得られます。 その他の場合では正しい値を得られません。 Emacsの値がまちがっているときには、 あまり最適でない決定をくだすでしょう。 この問題を修正するには、baud-rateに設定します。

baud-rate Function
この廃れた関数は、変数baud-rateの値を返す。

send-string-to-terminal string Function
この関数は、なにも変更せずに文字列stringを端末へ送る。 string内のコントロール文字は、端末に依存する効果を持つ。

この関数の1つの用途は、ファンクションキーの定義を ダウンロード可能な端末のファンクションキーを定義することである。 たとえば、ファンクションキー4を(文字の列C-u C-fを 計算機に送って)4文字進めると定義にするには、 特定の端末ではつぎのようにする。

(send-string-to-terminal "\eF4\^U\^F")
     => nil

open-termscript filename コマンド
この関数は、Emacsが端末へ送出するすべての文字を記録する タームスクリプトファイル(termscript file)を オープンするために使う。 関数はnilを返す。 タームスクリプトファイルは、 Emacsがスクリーンを乱してしまう問題、 誤ったtermcap定義やEmacsの実際のバグではない端末の望ましくない設定の 問題を調べるのに有用である。 どのような文字の列が実際に出力されるか確信できれば、 それらが使用中のtermcapのどの定義に対応するか調べられる。 Terminal Inputopen-dribble-fileも参照。
(open-termscript "../junk/termscript")
     => nil


Node:Special Keysyms, Next:, Previous:Terminal Output, Up:System Interface

システム固有のX11のキーシンボル

システム固有のX11のキーシンボル(keysym)を定義するには、 変数system-key-alistに設定します。

system-key-alist Variable
この変数の値は、各要素がシステム固有の 各キーシンボルに対応する連想リストであること。 要素は(code . symbol)の形である。 ここで、codeは(『提供業者固有の』ビット 含まない)数値のキーシンボルコードであり、 symbolはファンクションキーの名前である。

たとえば、(168 . mute-acute)は、 数値コードが + 168 であるHP Xサーバーが使うシステム固有キーを定義する。

実際に使用しているXサーバーのキーシンボルと衝突しなければ、 他のXサーバー向けのキーシンボルを連想リストから省かなくても問題ない。

変数は現在の端末につねにローカルであり、 バッファローカルにはなりえない。 see Multiple Displays


Node:Flow Control, Next:, Previous:Special Keysyms, Up:System Interface

フロー制御

本節では、 『Emacsがなぜコマンド文字集合の中からフロー制御文字を使うのか?』という 質問に答えたいと思います。 この話題に関する別の視点については、 配布に含まれるファイルemacs/INSTALLの中の フロー制御に関する記述を読んでください。 termcapの定義とDECの端末集線器については、 emacs/etc/TERMSを参照してください。

ある時期には、ほとんどの端末ではフロー制御を行っておらず、 C-sC-qをフロー制御に用いるものもありませんでした。 したがって、コマンド文字としてC-sC-qを選ぶことは 自然であり議論の余地はありませんでした。 キーに割り付けるべきコマンドがたくさんあったので、 ほとんどすべてのASCIIコントロール文字に意味を与えました。

のちに、フロー制御にこれらの文字を必要とする端末が導入されたのです。 それらはフルスクリーンエディタ向きの端末ではなかったので、 Emacsの保守陣はそれらを無視しました。 後年、C-sC-qによるフロー制御が 端末で広く使われるようになりましたが、当時はそれはオプションでした。 Emacsユーザーの多くはフロー制御をオフにして、 フロー制御のために無意味なキーバインディングに 替えようとはしなかったのです。

Emacsと端末や集線器の製造業者のどちらの使い方が『正しい』でしょう? この問に簡単な答えはありません。

C-sC-qで引き起こされる問題を解消するのに 気が進まないのは、C-sC-qであることに理由がないからです。 文字ストリームに透過な別の(実用上一般的ではないが) フロー制御技術があります。 さらに、それらをフロー制御に使うのは正式な規格ではありません。 興味深いことですが、(1970年ころの)紙テープパンチャ付きの テレタイプモデル33では、計算機からパンチャをオン/オフするために C-sC-qを送っていました!

ウィンドウシステムやPC端末エミュレータが文字端末を置き換えるようになり フロー制御の問題は徐々に解消しつつあります。 しばらくは、読者が望むならEmacsはフロー制御を オンにする手軽な方法を提供します。 関数enable-flow-controlを呼び出すのです。

enable-flow-control コマンド
この関数は、出力のフロー制御にC-sC-qを 使うようにするとともに、keyboard-translate-table (see Translating Input)を用いて C-\C-^をそれらのかわりに使えるようにする。

読者のファイル.emacsで関数enable-flow-control-onを使えば、 特定の種類の端末で自動的にフロー制御をオンにできます。

enable-flow-control-on &rest termtypes Function
この関数は、端末の種類がtermtypesの1つであると、 フロー制御をオンにしC-\C-^をかわりに使う。 たとえば、つぎのように使う。
(enable-flow-control-on "vt200" "vt300" "vt101" "vt131")

enable-flow-controlが行う処理はつぎのとおりです。

  1. (set-input-mode nil t)で 端末入力をCBREAKモードに設定し、 オペレーティングシステムにフロー制御を行うように指示する。
  2. C-\C-^C-sC-qに変換するように keyboard-translate-tableを設定する。 非常に下位レベルであることを除けば、 EmacsはC-sC-qを打ったと考えるので、 たとえ他のコマンドに対してもC-\C-^を打ったとしても 実質的にはC-sC-qを打ったことになる。 see Translating Input

端末側がフロー制御文字を発行するのであれば、 カーネルのフロー制御処理をオンにすれば、 その端末に対する普通のパディングより少なくしても動作するはずです。 termcapの定義をカスタマイズしてパディング量を減らします。 あるいは、baud-rateに小さめの値を設定すると、 パディングの必要量の計算にEmacsは低い速度を使います。 See Terminal Output


Node:Batch Mode, Previous:Flow Control, Up:System Interface

バッチモード

コマンド行オプション-batchは、 Emacsを非対話的に実行します。 このモードでは、Emacsは端末からコマンドを読まず、 端末のモードを変更せず、スクリーンに出力もしません。 これは、実行するLispプログラムを指定できるようにするためです。 それが終るとEmacsも終了します。 実行すべきプログラムは、 fileという名前のライブラリをロードする-l file、 および、 引数なしで関数functionを呼び出す-f functionで 指定します。

バッチモードでは、ストリームとしてtを指定した messageprin1などでエコー領域に 表示されるLispプログラムの出力は、 Emacsの標準エラー記述子へ出力されます。 したがって、Emacsは非対話的な アプリケーションプログラムのようにふるまいます。 (コマンドの表示などのEmacs自身がエコー領域に出力するものは 完全に抑制される。)

noninteractive Variable
この変数は、Emacsがバッチモードで動作しているとnil以外である。


Node:Display, Next:, Previous:Processes, Up:Top

Emacsの画面表示

本章では、Emacsがユーザーに提示する画面表示に関連する さまざまな機能について述べます。


Node:Refresh Screen, Next:, Up:Display

スクリーン全体の再表示

関数redraw-frameは、指定したフレーム(see Frames)の 内容全体を再表示します。

redraw-frame frame Function
この関数は、フレームframeをクリアしてから再表示する。

より強力なのはredraw-displayです。

redraw-display コマンド
この関数は、すべての可視フレームをクリアしてから再表示する。

ユーザー入力の処理のほうが再表示より絶対的に優先します。 入力があるときにこれらの関数を呼び出してもただちにはなにもしませんが、 入力をすべて処理し終えてから再表示します。

通常、Emacsを停止したり再開しても スクリーン全体を再表示します。 Emacsのようなディスプレイ向けプログラムと通常の逐次表示向けに、 表示内容を個別に記録できる端末エミュレータもあります。 そのような端末を使っているときには、 再開時の再表示を禁止した場合もあります。

no-redraw-on-reenter Variable
この変数は、停止後に再開したあとで、 スクリーン全体を再表示するかどうかを制御する。 nil以外であると再描画の必要はないことを意味し、 nilであると再描画が必要であることを意味する。 デフォルトはnilである。


Node:Truncation, Next:, Previous:Refresh Screen, Up:Display

表示の切り詰め

テキスト行がウィンドウの右端を越えていると、 その行をつぎのスクリーン行へ継続するか、 スクリーン行1行に切り詰めます。 長いテキスト行を表示するために使われる追加のスクリーン行を 継続行と呼びます。 通常、ウィンドウの最右端のコラムに現れる$で切り詰めたことを示し、 \でつぎの行に『折り返した』こと、 つまり、継続している行であることを示します。 (表示テーブルで別の文字を指定できる。 Display Tablesを参照。)

継続することと詰め込みは別のことです。 継続はスクリーン上だけのことであり、バッファ内容は変わりません。 また、継続では単語の境界ではなく、正確にスクリーンの右端で 行を分けます。 See Filling

truncate-lines User Option
このバッファローカルな変数は、 ウィンドウの右端を越える行をどのように表示するかを制御する。 デフォルトはnilであり継続を意味する。 値がnil以外であると、そのような行を切り詰める。

変数truncate-partial-width-windowsnil以外であると、 (フレーム内で)左右に並んだウィンドウでは、 truncate-linesの値に関わらずつねに切り詰る。

default-truncate-lines User Option
この変数は、truncate-linesのバッファローカルな値を持たない バッファ向けのtruncate-linesのデフォルト値である。

truncate-partial-width-windows User Option
この変数は、左右に並んだウィンドウ(see Splitting Windows)において、 ウィンドウの右端を越える行の表示を制御する。 nil以外であると、そのような行を切り詰める。 さもなければ、truncate-linesに従って表示する。

ウィンドウで水平方向にスクロールしている(see Horizontal Scrolling)と、 強制的に切り詰めます。

継続や切り詰めを表す文字は、表示テーブルを使って変更できます。 See Display Tables

バッファにとても長い行があるときにそれらの表示に継続行を使うと、 それによりEmacsの再表示が遅くなります。 コラム計算や字下げ関数も遅くなります。 そのような場合には、cache-long-line-scanstを 設定するのがよいです。

cache-long-line-scans Variable
この変数がnil以外であると、 字下げ/移動関数とEmacsの再表示において、 バッファを走査した結果をキャッシュし、 バッファが変更されていないときには キャッシュを調べてバッファの対象領域の再走査を回避する。

キャッシュするようにすると、短い行の処理が多少遅くなる。

この変数は、すべてのバッファで自動的にバッファローカルである。


Node:The Echo Area, Next:, Previous:Truncation, Up:Display

エコー領域

エコー領域(echo area)は、 基本関数messageでメッセージを表示したり、 打鍵を表示するために使われます。 (活性な)ミニバッファはエコー領域と 同じスクリーン上の位置に現れますが、 エコー領域とミニバッファは同じものではありません。 GNU Emacs マニュアルには、 エコー領域とミニバッファがスクリーンの同じ箇所を使う際の 衝突を回避する規則が述べてあります (see Minibuffer)。 エラーメッセージもエコー領域に現れます。 See Errors

エコー領域に表示するには、 ストリーム(see Output Functions)として tを指定したLisp表示関数を使うか、あるいはつぎのようにします。

message string &rest arguments Function
この関数は、エコー領域に1行のメッセージを表示する。 引数stringは、言語Cのprintfの制御文字列と同様である。 書式指定について詳しくは、String Conversionformatを参照。 messageは構築した文字列を返す。

バッチモードでは、messageはメッセージテキストと改行を 標準エラーストリームへ出力する。

stringnilであると、 messageはエコー領域をクリアする。 ミニバッファが活性であると、 これによりミニバッファの内容がスクリーンにただちに表示される。

(message "Minibuffer depth is %d."
         (minibuffer-depth))
 -| Minibuffer depth is 0.
=> "Minibuffer depth is 0."

---------- Echo Area ----------
Minibuffer depth is 0.
---------- Echo Area ----------

message-or-box string &rest arguments Function
この関数はmessageと同様にメッセージを表示するが、 エコー領域のかわりに対話ボックスを使うこともある。 この関数がマウスを用いて起動されたコマンドから呼ばれたとき、 より正確には、last-nonmenu-event(see Command Loop Info)が nilかリストのいずれかであると、 メッセージを表示するために対話ボックスかポップアップメニューを用いる。 さもなければエコー領域を用いる。 (これは、同様な決定をくだすy-or-n-pの判定条件と同じである。 see Yes-or-No Queries。)

呼び出しの周りでlast-nonmenu-eventに適切な値を束縛することで、 マウスを使うかエコー領域を使うか強制できる。

message-box string &rest arguments Function
この関数はmessageと同様にメッセージを表示するが、 可能な限り対話ボックス(やポップアップメニュー)を使う。 対話ボックスやポップアップメニューを扱えない端末などで これらを使用できない場合には、 message-boxmessageと同様にエコー領域を使う。

current-message Function
この関数は、エコー領域に現在表示されているメッセージを返す。 なければnilを返す。

cursor-in-echo-area Variable
この変数は、エコー領域にメッセージを表示しているときに カーソルをどこに表示するかを制御する。 nil以外であると、メッセージの末尾にカーソルを表示する。 さもなければ、エコー領域にではなく、ポイント位置にカーソルを表示する。

この値は普通はnilである。 Lispプログラムはこれにtを短い期間だけ束縛する。

echo-area-clear-hook Variable
このノーマルフックは、(message nil)や他の理由で エコー領域をクリアするたびに実行される。

エコー領域に表示したほとんどすべてのメッセージは バッファ*Messages*にも記録されます。

message-log-max User Option
この変数は、バッファ*Messages*に保持する行数を指定する。 値tは、保持する行数を制限しないことを意味する。 値nilは、メッセージをまったく記録しないことを意味する。 メッセージを表示しつつそれを記録しないようにするには つぎのようにする。
(let (message-log-max)
  (message ...))

echo-keystrokes Variable
この変数は、コマンド文字を表示するまでの経過時間を決定する。 この値は整数であり、表示し始めるまでに待つ秒数を指定する。 ユーザーが(C-xなどの)プレフィックスキーを打ってから つぎを打つまでにこの秒数だけ遅れがあると、 プレフィックスキーをエコー領域に表示する。 (いったんキー列の表示を始めると、 同じキー列の以降の文字すべてを表示する。)

値がゼロであると、コマンド入力を表示しない。


Node:Invisible Text, Next:, Previous:The Echo Area, Up:Display

不可視なテキスト

属性invisibleで文字群を不可視にできます。 つまり、それらをスクリーンに表示されないようにするのです。 テキスト属性(see Text Properties)か オーバレイの属性(see Overlays)を使います。

もっとも単純な場合、 属性invisiblenil以外であると文字は見えなくなります。 これはデフォルトの場合、つまり、 buffer-invisibility-specのデフォルト値を変更していない場合であり、 このようにして属性invisibleは動作します。

より一般的には、変数buffer-invisibility-specを使って、 属性invisibleのどの値のものを不可視なテキストにするかを制御できます。 つまり、invisibleの異なる値を与えて テキストをあらかじめいくつかのグループに分類しておき、 そのあとでbuffer-invisibility-specの値を変更して さまざまなグループを可視/不可視にします。

buffer-invisibility-specで可視性を制御することは、 データベースの項目の一覧を表示するようなプログラムで特に有用です。 データベースの特定の項目だけを見るための 便利なフィルタコマンドを実装できます。 この変数に設定するのはとても速くでき、 変更すべき属性を探すためにバッファ内の全テキストを走査するよりも速いのです。

buffer-invisibility-spec Variable
この変数は、属性invisibleのどの種類を実際に 不可視な文字にするかを指定する。
t
属性invisiblenil以外の文字を不可視にする。 これがデフォルト。
リスト
リストの各要素で不可視にする条件を指定する。 文字の属性invisibleがこれらの条件の1つを満たすと、 その文字を不可視にする。 リストには2種類の要素がありうる。
atom
文字の属性invisibleの値がatomであるか、 そのリストのメンバにatomがあると、 文字を不可視にする。
(atom . t)
文字の属性invisibleの値がatomであるか、 そのリストのメンバにatomがあると、 文字を不可視にする。 さらに、その文字が行末にあり、直後に目に見える改行がある場合には、 ...を表示する。

buffer-invisibility-specに要素を追加したり削除するために 2つの関数が特別にあります。

add-to-invisibility-spec element Function
(リストにelementが既存でなければ) buffer-invisibility-specに要素elementを追加する。

remove-from-invisibility-spec element Function
buffer-invisibility-specから要素elementを削除する。

buffer-invisibility-specの使い方の慣習の1つに、 メジャーモードでは buffer-invisibility-specの1要素と属性invisibleの値に モード自体の名前を使うべきであるというのがあります。

;; ...を表示したければ
(add-to-invisibility-spec '(my-symbol . t))
;; ...を表示しくなければ
(add-to-invisibility-spec 'my-symbol)

(overlay-put (make-overlay beginning end)
             'invisible 'my-symbol)

;; オーバレイを終了したら
(remove-from-invisibility-spec '(my-symbol . t))
;; 同じように
(remove-from-invisibility-spec 'my-symbol)

普通、テキストを操作したりポイントを移動するコマンドは、 テキストの可視性に注意しません。 ユーザーレベルの移動コマンドは、 line-move-ignore-invisiblenil以外であれば 不可視な改行を明示的に無視しますが、 それはそのように明示的にプログラムしてあるからにすぎません。

インクリメンタルサーチでは、 不可視なテキストを含む一致箇所では、 不可視なオーバレイを一時的にあるいは恒久的に可視にできます。 これを可能にするには、オーバレイの属性isearch-open-invisiblenil以外である必要があります。 その属性の値は、オーバレイを引数として呼ばれる関数である必要があります。 その関数がオーバレイを恒久的に可視にします。 その関数は、探索から抜けるときに一致箇所が オーバレイにまたがっているときに使われます。

探索中には、そのようなオーバレイは、 それらの属性invisibleintangibleを一時的に変更することで 一時的に可視にされます。 特定のオーバレイに対して異なる扱いをしたければ、 属性isearch-open-invisible-temporaryに関数を与えておきます。 その関数は2つの引数で呼ばれます。 第1引数はオーバレイ、 第2引数は、オーバレイを可視にするt、あるいは、 オーバレイを再度不可視にするnilです。


Node:Selective Display, Next:, Previous:Invisible Text, Up:Display

選択表示

選択表示とは、 スクリーン上の特定の行を隠すための関連する機能対を指します。

最初の変種は、明示的な選択表示で、 Lispプログラムで使用するために設計されています。 テキストを変更することでどの行を隠すかを制御します。 テキストを不可視にする機能(see Invisible Text)は、 この機能で部分的に置き換えてあります。

2番目の変種は、字下げに基づいて自動的に隠す行を選択します。 この変種は、ユーザーレベルの機能であるように設計されています。

明示的な選択表示を制御するには、 改行(コントロールJ)を復帰(コントロールM)に置き換えます。 置換前の改行に続いていたそれまでの行は見えなくなります。 厳密にいえば、改行だけが行を区切るため、 一時的にはもう行ではなくなっているのです。 つまり、先行する行の一部になっているのです。

選択表示は、編集コマンドに直接には影響しません。 たとえば、C-fforward-char)は 躊躇なく不可視なテキストの中へポイントを移動します。 しかし、改行文字を復帰文字に置換すると 影響を受ける編集コマンドもあります。 たとえば、next-lineは、 改行だけを探すため不可視な行を飛び越してしまいます。 選択表示を使用するモードでは、 改行を考慮するようにコマンドを定義したり、 テキストの一部を可視/不可視にするコマンドを定義できます。

選択表示しているバッファをファイルに書き出すときには、 すべてのコントロールM(復帰)は改行として出力されます。 つまり、つぎにファイルを読み込むと不可視なものはなく、 普通に見えるのです。 選択表示の効果は、Emacsの内側だけで見えるのです。

selective-display Variable
このバッファローカルな変数は、選択表示をオンにする。 つまり、行や行の一部を不可視にできる。
  • selective-displayの値がtであると、 行内のコントロールM(復帰)以降の部分を表示しない。 これは明示的な選択表示である。
  • selective-displayの値が正整数であると、 字下げのコラム幅がその数より大きな行を表示しない。

バッファのある部分が不可視であると、 垂直方向に移動するコマンドは、 その部分が存在しないがごとく動作し、 1つのコマンドnext-lineで任意個数の不可視行を飛び越えられる。 しかし、(forward-charなどの) 文字単位の移動コマンドは不可視な部分を無視せず、 不可視な部分へのテキストの挿入/削除は可能である。

つぎの例では、selective-displayの値を変えて バッファfoo見た目を示す。 バッファの内容に変更はない。

(setq selective-display nil)
     => nil

---------- Buffer: foo ----------
1 on this column
 2on this column
  3n this column
  3n this column
 2on this column
1 on this column
---------- Buffer: foo ----------

(setq selective-display 2)
     => 2

---------- Buffer: foo ----------
1 on this column
 2on this column
 2on this column
1 on this column
---------- Buffer: foo ----------

selective-display-ellipses Variable
このバッファローカルな変数がnil以外であると、 不可視なテキストが続く行末に...を表示する。 つぎの例は、上の例の続きである。
(setq selective-display-ellipses t)
     => t

---------- Buffer: foo ----------
1 on this column
 2on this column ...
 2on this column
1 on this column
---------- Buffer: foo ----------

表示テーブルを使って...にかわる別のテキストを指定できる。 see Display Tables


Node:Overlay Arrow, Next:, Previous:Selective Display, Up:Display

オーバレイ矢印

オーバレイ矢印(overlay arrow)は、 バッファの特定の行にユーザーの注意を向けるために有用です。 たとえば、デバッガとのインターフェイスを取るためのモードでは、 オーバレイ矢印で実行するコードの行を示します。

overlay-arrow-string Variable
この変数は、特定の行に注意を向けるために表示する文字列を保持する。 矢印機能を使っていなければnilである。

overlay-arrow-position Variable
この変数は、オーバレイ矢印を表示する箇所を表すマーカを保持する。 行頭を指すこと。 矢印のテキストはその行の先頭に現れ、 その場所に本来現れるべきテキストを隠す。 矢印は普通は短く、行には字下げがあるので、 重要なものは普通はなにも上書きされない。

オーバレイ文字列は、マーカが指すバッファでのみ表示される。 したがって、ある時点では、1つのバッファだけにオーバレイ矢印を表示できる。

同様のことは、属性before-stringのオーバレイを 作成してもできます。 See Overlay Properties


Node:Temporary Displays, Next:, Previous:Overlay Arrow, Up:Display

一時的な表示

一時的な表示は、 出力をバッファに置き編集目的にではなく ユーザーに読むように提示するために Lispプログラムが使います。

with-output-to-temp-buffer buffer-name forms... Special Form
この関数は、buffer-nameという名前のバッファに formsの任意の出力が挿入されるように準備して formsを実行する。 そのバッファは適当なウィンドウに表示されるが、 そのバッファは選択されない。

文字列buffer-nameは、既存である必要はない一時的なバッファを指定する。 引数は、バッファではなく文字列であること。 (問い合わせずに)はじめにバッファを消去し、 with-output-to-temp-bufferが終了すると未変更と印を付ける。

with-output-to-temp-bufferは、 standard-outputに一時的なバッファを束縛し、 formsのフォーム群を評価する。 forms内で用いたLisp出力関数からの出力は デフォルトでそのバッファに入る (しかし、スクリーン表示やエコー領域のメッセージは、 用語の一般的な意味で『出力』であるが、 影響されない。) see Output Functions

formsの最後のフォームの値を返す。

---------- Buffer: foo ----------
 This is the contents of foo.
---------- Buffer: foo ----------

(with-output-to-temp-buffer "foo"
    (print 20)
    (print standard-output))
=> #<buffer foo>

---------- Buffer: foo ----------
20

#<buffer foo>

---------- Buffer: foo ----------

temp-buffer-show-function Variable
この変数がnil以外であると、 ヘルプバッファを表示するために with-output-to-temp-bufferがこの値を関数として呼び出す。 関数は1つの引数、つまり、表示すべきバッファを受け取る。

この関数では、 save-window-excursionを使いウィンドウとバッファを選択した内側で、 with-output-to-temp-bufferが普通に行うように temp-buffer-show-hookを呼び出すのがよい。

temp-buffer-show-hook Variable
このノーマルフックは、ヘルプバッファを表示後に with-output-to-temp-bufferが実行する。 フックを実行するときには、 ヘルプバッファがカレントバッファであり、 それを表示しているウィンドウが選択されているウィンドウである。

momentary-string-display string position &optional char message Function
この関数は、カレントバッファ内の位置positionに 文字列stringを瞬間的に表示する。 アンドゥリストやバッファの変更状態には影響しない。

瞬間的な表示は、つぎの入力イベントまで持続する。 つぎの入力イベントがcharであると、 momentary-string-displayはそれを無視して戻る。 さもなければ、そのイベントは入力として使われるように保存される。 したがって、charを打つと文字列の表示が単に消えるだけであるが、 (たとえば)C-fを打つと文字列の表示が消えるだけでなく (たぶん)ポイントを進めることになる。 引数charはデフォルトでは空白である。

momentary-string-displayの戻り値に意味はない。

文字列stringにコントロール文字が含まれなければ、 属性before-stringのオーバレイを作成(のちに削除)することで より一般的な方法で同じことを行える。 see Overlay Properties

messagenil以外であると、 stringをバッファに表示中には、 messageをエコー領域に表示する。 nilであると、デフォルトは 「継続するには文字charを打つこと」 といったメッセージである。

つぎの例では、ポイントは始めは2行目の先頭に位置している。

---------- Buffer: foo ----------
This is the contents of foo.
-!-Second line.
---------- Buffer: foo ----------

(momentary-string-display
  "**** Important Message! ****"
  (point) ?\r
  "Type RET when done reading")
=> t

---------- Buffer: foo ----------
This is the contents of foo.
**** Important Message! ****Second line.
---------- Buffer: foo ----------

---------- Echo Area ----------
Type RET when done reading
---------- Echo Area ----------


Node:Overlays, Next:, Previous:Temporary Displays, Up:Display

オーバレイ

ユーザーに提示するためにスクリーン上でのバッファのテキストの見た目を 変えるためにオーバレイ(overlay)を使えます。 オーバレイは、特定のバッファに属するオブジェクトであり、 指定された開始位置と終了位置があります。 また、調べたり設定できる属性もあります。 これらの属性は、オーバレイの内側のテキストの表示に影響します。


Node:Overlay Properties, Next:, Up:Overlays

オーバレイ属性

オーバレイ属性はある意味でテキスト属性に似ていて、 どちらの属性でも文字の表示方法を変更できます。 しかし、多くの点で異なります。 テキスト属性は、テキストの一部であるとみなされますが、 オーバレイはテキストの一部とはみなしません。 したがって、さまざまなバッファや文字列のあいだでテキストをコピーしても テキスト属性は保存されますが、オーバレイは保存されません。 バッファ内のテキスト属性を変更するとバッファを変更済みと印を付けますが、 オーバレイを移動したりその属性を変更しても バッファの変更とは考えません。 テキスト属性の変更と異なり、 オーバレイの変更はバッファのアンドゥリストには記録されません。 比較のためにSee Text Properties

priority
この属性の値(非負の数であること)は、 オーバレイの優先順位を決定する。 優先順位は、複数のオーバレイが同じ文字を覆い、 いずれも表示用のフェイスを指定している場合に意味を持つ。 priorityの値の大きなものが他に優先し、 そのフェイス属性が他の低い順位の属性のフェイス属性に優先する。

現在、すべてのオーバレイ属性はテキスト属性に優先する。 負の優先順位の意味を決めかねているので、負の優先順位は避けてほしい。

window
属性windownil以外であると、 オーバレイをそのウィンドウだけに適用する。
category
オーバレイに属性categoryがあると、 それをオーバレイのカテゴリ(category)と呼ぶ。 これはシンボルであること。 シンボルの属性がオーバレイの属性のデフォルトの役割を果たす。
face
この属性は、テキストの表示方法、たとえば、 フォントや表示色を制御する。 その値は、フェイス名であるかフェイス名のリストである。 詳しくは、see Faces

属性値がリストであると、その要素は、 (foreground-color . color-name)(background-color . color-name)の形でもよい。 これらの要素は、前景色だけや背景色だけを指定する。 したがって、使用する各色を表すフェイスを作成する必要はない。

mouse-face
この属性は、マウスがオーバレイの範囲に入っているときに faceのかわりに使われる。
modification-hooks
この属性の値は、オーバレイの内側の文字を変更したり、 オーバレイの内側にテキストを挿入したときに 呼び出される関数のリストである。

フック関数は、各変更の前後に呼び出される。 関数が受け取った情報を保存し呼び出しごとに比較すれば バッファテキストにどのような変更が行われたかを正確に判定できる。

変更前に呼ばれるときには、各関数は4つの引数を受け取る。 オーバレイ、nil、変更対象のテキスト範囲の先頭と末尾である。

変更後に呼ばれるときには、各関数は5つの引数を受け取る。 オーバレイ、t、変更済みのテキスト範囲の先頭と末尾、 その範囲の変更前のテキストの長さである。 (挿入では変更前の長さはゼロである。 削除では変更前の長さは削除された文字数であり、 変更後の先頭位置と末尾位置は同じである。)

insert-in-front-hooks
この属性の値は、オーバレイの開始位置へのテキスト挿入の前後に 呼び出される関数のリストである。 呼び出し方法はmodification-hooksの関数群と同じである。
insert-behind-hooks
この属性の値は、オーバレイの終了位置へのテキスト挿入の前後に 呼び出される関数のリストである。 呼び出し方法はmodification-hooksの関数群と同じである。
invisible
属性invisibleは、オーバレイ内のテキストを不可視にする。 つまり、それらはスクリーン上に現れない。 詳しくは、see Invisible Text
intangible
属性intangibleは、オーバレイにおいて テキスト属性intangibleと同様に働く。 詳しくは、see Special Properties
isearch-open-invisible
この属性は、インクリメンタルサーチに対して、 一致箇所がオーバレイに重なったときに 不可視なオーバレイを恒久的に可視にする方法を指示する。 see Invisible Text
isearch-open-invisible-temporary
この属性は、インクリメンタルサーチに対して、 探索中に不可視なオーバレイを一時的に可視にする方法を指示する。 see Invisible Text
before-string
この属性の値は、オーバレイの先頭位置に追加表示する文字列である。 文字列はいかなる意味においてもバッファには現れず、 スクリーン上のみに現れる。 文字列は1コラムで表示される文字のみであること。 タブや改行を含むコントロール文字を含むと奇妙な結果を生じる。
after-string
この属性の値は、オーバレイの末尾位置に追加表示する文字列である。 文字列はいかなる意味においてもバッファには現れず、 スクリーン上のみに現れる。 文字列は1コラムで表示される文字のみであること。 タブや改行を含むコントロール文字を含むと奇妙な結果を生じる。
evaporate
この属性がnil以外であると、 オーバレイが空に(つまり覆う文字がなく)なると、 自動的にオーバレイを削除する。
local-map
この属性がnil以外であると、当該部分のテキストに対する キーマップを指定する。 ポイントの直後の文字がオーバレイに入っていると、 属性の値はバッファローカルなキーマップに置き換わる。 see Active Keymaps

つぎは、オーバレイの属性を読み書きするための関数です。

overlay-get overlay prop Function
この関数は、オーバレイoverlayに記録されている 属性propの値をあれば返す。 overlayにそのような属性に対する値が記録されていなくても、 属性categoryがありそれがシンボルであれば、 そのシンボルの属性propを使う。 さもなければ値はnilである。

overlay-put overlay prop value Function
この関数は、オーバレイoverlayに属性propの値として valueを設定する。 valueを返す。

与えられた文字のオーバレイ属性とテキスト属性の両方を調べる 関数codeget-char-propertyも参照してください。 See Examining Properties


Node:Managing Overlays, Previous:Overlay Properties, Up:Overlays

オーバレイの管理

本節では、オーバレイを作成、削除、移動したり、 それらの内容を調べる関数について述べます。

make-overlay start end &optional buffer front-advance rear-advance Function
この関数は、バッファbufferに属する startからendまでを覆うオーバレイを作成しそれを返す。 startendのどちらもバッファ内位置を指定する 整数かマーカであること。 bufferを省略すると、カレントバッファにオーバレイを作成する。

引数front-advancerear-advanceは、 オーバレイの開始位置と終了位置における挿入型を指定する。 see Marker Insertion Types

overlay-start overlay Function
この関数は、オーバレイoverlayの開始位置を整数で返す。

overlay-end overlay Function
この関数は、オーバレイoverlayの終了位置を整数で返す。

overlay-buffer overlay Function
この関数は、オーバレイoverlayが属するバッファを返す。

delete-overlay overlay Function
この関数は、オーバレイoverlayを削除する。 Lispオブジェクトとしてはオーバレイは存在し続けるが、 それが属したバッファとの対応付けは消失し、 表示上の効果もなくなる。

削除したオーバレイは恒久的に無意味ではない。 move-overlayを呼び出して新たなバッファ内位置をそれに与えられる。

move-overlay overlay start end &optional buffer Function
この関数は、オーバレイoverlayをバッファbufferに移し、 startからendを覆うようにする。 startendのどちらもバッファ内位置を指定し、 整数かマーカである。 bufferを省略すると、オーバレイは同じバッファに留まる。

戻り値はoverlayである。

これは、オーバレイの端を変更する唯一の正しい方法である。 オーバレイのマーカを手で修正しようとしないこと。 他の重要なデータ構造を更新しそこない、 いくつかのオーバレイを『失う』ことにもなりかねない。

overlays-at pos Function
この関数は、カレントバッファの位置posを覆うすべての オーバレイのリストを返す。 このリスト内の順番に意味はない。 オーバレイが位置posかそのまえで始まり、かつ、 位置posかそのうしろで終るときに、 オーバレイは位置posを覆う。

overlays-in beg end Function
この関数は、begからendまでの領域と 重なり合っているすべてのオーバレイのリストを返す。 『重なり合っている』とは、 少なくとも1文字がオーバレイに覆われていて、かつ、 その文字が指定された領域に入っていることを意味する。 しかし、空のオーバレイであっても それがbegにあるかbegendのあいだにあれば、 空のオーバレイも結果に含まれる。

next-overlay-change pos Function
この関数は、位置posのうしろにある オーバレイのつぎの開始位置か終了位置を返す。

previous-overlay-change pos Function
この関数は、位置posのまえにある オーバレイのまえの開始位置か終了位置を返す。


Node:Width, Next:, Previous:Overlays, Up:Display

表示幅

すべての文字が同じ表示幅ではありませんから、 これらの関数で文字の表示幅を検査できます。 関連する関数については、Primitive IndentとSee Screen Lines

char-width char Function
この関数は、文字charを選択されているウィンドウで カレントバッファに表示した場合のコラム幅を返す。

string-width string Function
この関数は、文字列stringを選択されているウィンドウで カレントバッファに表示した場合のコラム幅を返す。

truncate-string-to-width string width &optional start-column padding Function
この関数は、幅widthに収まる文字列stringの部分を 新たな文字列として返す。

stringが幅widthに満たない場合、 stringの終りで結果は終る。 string内の1つの複数コラム文字がコラムwidthを越える場合には、 その文字は結果に含めない。 したがって、結果はwidthより短くなりえるがそれを越えることはない。

省略可能な引数start-columnは、開始コラムを指定する。 これがnil以外であると、文字列のはじめの start-columnコラムを結果から省く。 string内の1つの複数コラム文字がコラムstart-columnを越える場合には、 その文字は結果に含めない。

省略可能な引数paddingnil以外であると、 結果の文字列の先頭や末尾に付加して ちょうどwidthコラムにするためのパディング文字である。 widthより短くなる場合に 結果の末尾にパディング文字を使う。 複数コラム文字がコラムstart-columnを越える場合には、 結果の先頭にパディング文字を使う。

(truncate-string-to-width "\tab\t" 12 4)
     => "ab"
(truncate-string-to-width "\tab\t" 12 4 ?\ )
     => "    ab  "


Node:Faces, Next:, Previous:Width, Up:Display

フェイス

フェイス(face)とは、図形的な属性、つまり、 フォント、前景色、背景色、下線 の名前付きの集合体です。 フェイスはスクリーン上のテキストの表示を制御します。

各フェイスには固有のフェイス番号(face number)があり、 Emacs内部の下位レベルでフェイスを区別するために使われます。 しかし、ほとんどの目的には、 Lispプログラムでは名前でフェイスを参照できます。

facep object Function
この関数は、objectがフェイスを指名するシンボル (あるいは、フェイスデータを記録するために内部的に使われる種類のベクトル) であるとtを返す。 さもなければnilを返す。

各フェイス名はすべてのフレームで有効であり、 デフォルトではすべてのフレームで同じ意味を持ちます。 しかし、望みの1つのフレームで特定のフェイス名に 特定の意味を持たせることもできます。


Node:Standard Faces, Next:, Up:Faces

標準フェイス

つぎの表はすべての標準フェイスとその用途です。

default
このフェイスは通常のテキストに対して使う。
modeline
このフェイスはモード行とメニューバーに対して使う。
region
このフェイスは、暫定マーク(transient-mark)モードでリージョンを 強調表示するために使う。
secondary-selection
このフェイスは、指定した任意の二次セレクションを示すために使う。
highlight
このフェイスは、さまざま目的向けに強調表示するために使う。
underline
このフェイスは、テキストに下線を引く。
bold
このフェイスは、可能ならば太字(bold)フォントを使う。 フレームのフォントに太字(bold)変種があればそれを使う。 太字変種を使用したい場合には、 太字フォント変種を有するデフォルトフォントを選ぶのは読者の責任である。
italic
このフェイスは、フレームのフォントに 斜体(italic)変種があればそれを使う。
bold-italic
このフェイスは、フレームのフォントに 太字斜体(bold-italic)変種があればそれを使う。


Node:Defining Faces, Next:, Previous:Standard Faces, Up:Faces

フェイスを定義する

新たなフェイスを定義する方法は、deffaceを使うことです。 これは、カスタマイズバッファ (see Easy Customization) を用いてユーザーがカスタマイズできる カスタマイズ項目(see Customization)の一種を作成します。

defface face spec doc [keyword value]... Macro
specに従ったデフォルトを持つカスタマイズ可能なフェイスとして faceを宣言する。 シンボルfaceをクォートしないこと。 引数docは、フェイスの説明文字列を指定する。

deffaceを実行すると、specに従ったフェイスを定義し、 ファイル.emacsから読み取った任意のカスタマイズを specの指定に優先させる。

specの目的は、異なる種類の端末でフェイスがどのような 見た目になるかを指定することである。 (display atts)の形の要素から成る 連想リストであること。 要素のCARdisplayは端末の種類を指定する。 CDRattsはフェイスの属性とその値のリストであり、 その種類の端末上でそのフェイスがどのように見えるかを指定する。 可能な属性は、custom-face-attributesの値で定義される。

specの要素のdisplay部分は、要素を適用するフレームを決定する。 specの1つより多くの要素が指定されたフレームに一致する場合、 そのフレームに一致した最初の要素だけを用いる。 displayには2つの可能性がある。

t
specの要素はすべてのフレームで一致する。 したがって、specの以降の要素をけっして使わない。 通常、tspecの最後の(あるいは唯一)の要素に使う。
リスト
displayがリストであると、 各要素は(characteristic value...)の形であること。 ここで、characteristicはフレームの分類方法であり、 valuedisplayを適用すべき分類とみなす値である。 特性characteristicの可能な値はつぎのとおりである。
type
フレームが使用するウィンドウシステムの種類であり、 xpc(MS-DOSのコンソール)、 w32(MS Windows 9X/NT)、ttyのいずれかである。
class
フレームで扱える表示色の種類であり、 colorgrayscalemonoのいずれかである。
background
背景の種類であり、lightdarkのいずれかである。

displayの1つの要素において、 指定されたcharacteristicに 1つより多くのvalueを指定すると、 それらのいずれの値でも受け入れる。 displayに1つより多くの要素がある場合、 各要素は異なるcharacteristicを指定すること。 そうすれば、フレームの特性は displayに指定されたそのフレーム向けの valueの1つに一致するはずである。

標準フェイスregiondeffaceで 定義するとつぎのようになります。

(defface region
         ((((class color) (background dark))
           (:background "blue"))
          (t (:background "gray")))
  "Used for displaying the region.")

内部的にはdeffaceは、 deffaceに指定されたフェイス属性の記録には シンボルの属性face-defface-spec、 カスタマイズバッファでユーザーが保存した属性の記録には saved-face、 説明文字列の記録にはface-documentationを使います。

frame-background-mode User Option
このオプションがnil以外であると、 フェイスの定義を解釈する際に用いる背景の型を指定する。 これがdarkであると、 実際の背景色に関わらずEmacsはすべてのフレームの背景は暗いとみなす。 これがlightであると、 Emacsはすべてのフレームの背景は明るいとみなす。


Node:Merging Faces, Next:, Previous:Defining Faces, Up:Faces

表示向けにフェイスを併合する

テキストの表示に使用するフェイスを指定する方法はつぎのとおりです。

ある文字に対してこれらのさまざまな指定が 1つより多くのフェイスを指定する場合、 Emacsは指定されたさまざまなフェイスの属性を併合します。 特別な字形のフェイスが最初です。 適切ならば、つぎはリージョンの強調表示のフェイスです。 そのつぎはオーバレイのフェイスの属性、 さらにテキスト属性のフェイスが続き、 最後はデフォルトのフェイスです。

複数のオーバレイが1つの文字を覆う場合、 高い優先順位のオーバレイが低いものに優先します。 See Overlays

フォントや表示色のような属性がうえのどれでも指定されていない場合には、 フレーム独自のフォントや表示色を使います。


Node:Face Functions, Previous:Merging Faces, Up:Faces

フェイスを扱う関数

フェイスの属性で指定できるのは、フォント、前景色、背景色、下線です。 フェイスでは値nilを指定することでこれらを未指定にできます。

以下は、フェイスを作成したり変更する基本関数です。

make-face name Function
この関数は、すべての属性をnilとした nameという名前の新たなフェイスを定義する。 nameという名前のフェイスが既存ならばなにもしない。

face-list Function
この関数は、定義済みのすべてのフェイス名のリストを返す。

copy-face old-face new-name &optional frame new-frame Function
この関数は、既存のold-faceという名前のフェイスのコピーとして フェイスnew-nameを定義する。 new-nameが既存でなければ、フェイスnew-nameを作成する。

省略可能な引数フレームframeを指定すると、 この関数はそのフレームだけに適用する。 さもなければ、各フレームにおいて個別に、 そのフレームのold-faceの属性を 同じフレームのnew-faceにコピーする。

省略可能な引数フレームnew-frameを指定すると、 copy-faceは フレームframeold-faceの属性を フレームnew-framenew-faceにコピーする。

以下の関数を使って既存のフレームの属性を変更できます。 フレームframeを指定すると、そのフレームだけに影響します。 さもなければ、新たなフレームに適用されるデフォルトに加えて すべてのフレームに影響します。

set-face-foreground face color &optional frame Function
set-face-background face color &optional frame Function
これらの関数は、フェイスfaceの前景色(あるいは背景色)として colorを設定する。 引数colorは、表示色名の文字列であること。

白黒スクリーンでは、濃淡は点猫パターンで実現する。

set-face-stipple face pattern &optional frame Function
この関数は、フェイスfaceの背景点猫パターンとして patternを設定する。 引数patternは、Xサーバーで定義された背景点猫パターンの名前であること。 あるいは、点猫を使わないことを意味するnilであること。

白黒階調の特定の濃淡を扱うために自動的に点猫パターンを使うため、 普通は点猫パターンに注意する必要はない。

set-face-font face font &optional frame Function
この関数は、フェイスfaceのフォントを設定する。 引数fontは、読者のシステムの正しいフォント名か Emacsのフォントセット名(see Fontsets)の文字列であること。 フォントを明示的に設定するとつねに正確にそれを使うため、 太字(bold)や斜体(italic)の属性の効果は消失することに注意。

set-face-bold-p face bold-p &optional frame Function
この関数は、フェイスfaceの太字(bold)の属性を設定する。 nil以外は太字あり、nilは太字なしを意味する。

set-face-italic-p face italic-p &optional frame Function
この関数は、フェイスfaceの斜体(italic)の属性を設定する。 nil以外は斜体あり、nilは斜体なしを意味する。

set-face-underline-p face underline-p &optional frame Function
この関数は、フェイスfaceの下線の属性を設定する。 nil以外は下線あり、nilは下線なしを意味する。

invert-face face &optional frame Function
フェイスfaceの前景色と背景色を入れ換える。 フェイスに前景色と背景色の両者が設定されていないと、 その前景色と背景色にはデフォルトの背景色と前景色を設定する。

つぎの関数は、フェイスの属性を調べます。 フレームframeを指定しない場合、 新たなフレーム向けのデフォルトのデータを参照します。

face-foreground face &optional frame Function
face-background face &optional frame Function
この関数は、フェイスfaceの前景色(あるいは背景色)を 文字列で返す。

face-stipple face &optional frame Function
この関数は、フェイスfaceの背景点猫パターンの名前を返す。 なければnilを返す。

face-font face &optional frame Function
この関数はフェイスfaceのフォントの名前を返す。

face-bold-p face &optional frame Function
この関数はフェイスfaceの太字(bold)属性を返す。

face-italic-p face &optional frame Function
この関数はフェイスfaceの斜体(italic)属性を返す。

face-underline-p face &optional frame Function
この関数はフェイスfaceの下線属性を返す。

face-id face Function
この関数はフェイスfaceのフェイス番号を返す。

face-documentation face Function
この関数はフェイスfaceの説明文字列を返す。 なければnilを返す。

face-equal face1 face2 &optional frame Function
この関数は、フェイスface1face2が 表示上の同じ属性を持てばtを返す。

face-differs-from-default-p face &optional frame Function
この関数は、フェイスfaceの表示がデフォルトのフェイスの表示と 異なる場合にはtを返す。 フェイスの各属性がデフォルトフェイスの対応する属性に等しいか (デフォルトから継承すること意味する)nilであると、 フェイスはデフォルトのフェイスと『等しい』とみなす。

region-face Variable
この変数の値は、リージョンが活性(暫定マーク(transient-mark)モードのみ) の場合にリージョン内の文字の表示に使用するフェイス番号を指定する。 リージョン内の文字では、これが指定するフェイスが テキスト属性やオーバレイのすべてのフェイスに優先する。 暫定マーク(transient-mark)モードについて詳しくは、see The Mark

通常、値はregionという名前のフェイスのフェイス番号である。

frame-update-face-colors frame Function
この関数は、フレームframeの前景色や背景色を変更後に フレームframe上のフェイスの表示を更新する。


Node:Blinking, Next:, Previous:Faces, Up:Display

括弧を点滅する

本節では、ユーザーが閉じ括弧を挿入したときに Emacsが対応する開き括弧を指し示す機構について述べます。

blink-paren-function Variable
この変数の値は、閉じ括弧構文の文字が挿入されるたびに 呼び出される(引数なしの)関数であること。 blink-paren-functionの値がnilであると、なにもしない。

blink-matching-paren User Option
この変数がnilであると、blink-matching-openはなにもしない。

blink-matching-paren-distance User Option
この変数は、対応する括弧の走査を諦めるまでの最大距離を指定する。

blink-matching-delay User Option
この関数は、対応する括弧にカーソルを留める秒数を指定する。 秒未満を指定してもしばしば結果は良好であるが、 デフォルトはすべてのシステムで動作する1である。

blink-matching-open コマンド
この関数は、blink-paren-functionのデフォルト値である。 閉じ括弧構文の文字のうしろにポイントがあることを仮定し、 カーソルを対応する開き括弧へ一時的に移動する。 その文字がスクリーン上になければ、 その文字が現れる文脈をエコー領域に表示する。 遅れが大きくならないように、 blink-matching-paren-distance文字より離れては探さない。

つぎは、この関数を明示的に呼び出す例である。

(defun interactive-blink-matching-open ()
  "Indicate momentarily the start of sexp before point."
  (interactive)
  (let ((blink-matching-paren-distance
         (buffer-size))
        (blink-matching-paren t))
    (blink-matching-open)))


Node:Inverse Video, Next:, Previous:Blinking, Up:Display

反転表示

inverse-video User Option
この変数は、スクリーン上のすべてのテキストに 反転表示を使うかどうかを制御する。 nil以外は使うことを意味し、 nilは使わないことを意味する。 デフォルトはnilである。

mode-line-inverse-video User Option
この変数は、モード行に反転表示を使うかどうかを制御する。 nil以外であると、モード行を反転表示する。 さもなければ、テキストと同様にモード行を普通に表示する。 デフォルトはtである。

ウィンドウフレームでは、 modelineという名前のフェイスを使ってモード行を表示する。 このフェイスは、変更していなければ、デフォルトフェイスの反転表示である。


Node:Usual Display, Next:, Previous:Inverse Video, Up:Display

通常の画面表示慣習

通常の画面表示慣習は、各文字コードをどのように表示するかを定義します。 表示テーブル(see Display Tables)を設定すれば、 これらの慣習を無効にできます。 通常の画面表示慣習をつぎに示します。

通常の画面表示慣習は、たとえ表示テーブルがあっても、 活性な表示テーブルにおいてその文字に対する項目がnilであるような 文字すべてに適用されます。 したがって、表示テーブルを設定するときには、 特別なふるまいをさせたい文字だけを指定すればよいのです。

これらの変数は、特定の文字群のスクリーンへの表示方法に影響します。 これらは文字が占めるコラム数を変化させるので、 字下げ関数にも影響します。 これらの変数は、モード行の表示方法にも影響します。 新たな値を用いてモード行の再表示を強制したいときには、 関数force-mode-line-update(see Mode Line Format)を 呼び出します。

ctl-arrow User Option
このバッファローカルな変数は、 コントロール文字の表示方法を制御する。 nil以外であると、^Aのように カレットに続けて文字を表示する。 nilであると、\001のように バックスラッシュに続けて3桁の8進数字で表示する。

default-ctl-arrow Variable
この変数の値は、ctl-arrowを書き換えていないバッファ向けの ctl-arrowのデフォルト値である。 see Default Value

tab-width User Option
この変数の値は、Emacsのバッファ内のタブ文字の表示に使う タブストップの間隔である。 デフォルトは8である。 この機能は、コマンドtab-to-tab-stopで設定する ユーザー設定可能なタブストップとはまったく独立であることに注意。 see Indent Tabs


Node:Display Tables, Next:, Previous:Usual Display, Up:Display

表示テーブル

表示テーブル(display table)機能を使って、 すべての可能な文字コードのスクリーンへの表示方法を制御できます。 これは、ASCII文字集合にない文字を用いる ヨーロッパの言語を表示するのに有用です。

表示テーブルは、各文字コードを字形(glyph)の列に対応付けます。 各字形は、スクリーン上で1文字を占める像です。 字形テーブル(glyph table)を使えば、 読者の端末に各字形を表示する方法を定義することもできます。

表示テーブルは、モード行の表示方法にも影響します。 新たな表示テーブルを用いてモード行の再表示を強制したいときには、 関数force-mode-line-update(see Mode Line Format)を 呼び出します。


Node:Display Table Format, Next:, Up:Display Tables

表示テーブルの書式

表示テーブルは、実際にはサブタイプがdisplay-tableである 文字テーブル(see Char-Tables)です。

make-display-table Function
表示テーブルを作成して返す。 テーブルのすべての要素の初期値はnilである。

表示テーブルの通常の要素は、文字コードで添字付けします。 添字cの要素は、文字コードcの表示方法を指定します。 値はnilであるか、字形の値のベクトル(see Glyphs)です。 要素がnilであると、その文字を通常の画面表示慣習 (see Usual Display)に従って表示する指定です。

表示テーブルを使って改行文字の表示を変更すると、 バッファ全体は長い1つの『行』として表示されます。

表示テーブルには6つの『追加スロット』もあり、 それらは特別な目的を果たします。 それらの意味をつぎに示します。 スロットの内容がnilであると、 そのスロットに対して以下に述べる デフォルトを使うことを意味します。

0
切り詰めたスクリーン行の末尾に使う字形 (デフォルトは$)。 see Glyphs
1
継続している行の末尾に使う字形 (デフォルトは\)。
2
文字を8進数文字コードで表示したことを表す字形 (デフォルトは\)。
3
コントロール文字を表す字形 (デフォルトは^)。
4
符可視な行があることを表す字形のベクトル (デフォルトは...)。 see Selective Display
5
左右に隣り合ったウィンドウの境界に使う字形 (デフォルトは|)。 see Splitting Windows

たとえば、ctl-arrownil以外の値を設定した効果を 模倣する表示テーブルの作成方法をつぎに示します。

(setq disptab (make-display-table))
(let ((i 0))
  (while (< i 32)
    (or (= i ?\t) (= i ?\n)
        (aset disptab i (vector ?^ (+ i 64))))
    (setq i (1+ i)))
  (aset disptab 127 (vector ?^ ??)))

display-table-slot display-table slot Function
この関数は表示テーブルdisplay-tableの 追加スロットslotの値を返す。 引数slotは0から5までの数であるか、 スロット名(シンボル)であること。 正しいシンボルは、truncationwrapescapecontrolselective-displayvertical-borderである。

set-display-table-slot display-table slot value Function
この関数は表示テーブルdisplay-tableの 追加スロットslotに値valueを保存する。 引数slotは0から5までの数であるか、 スロット名(シンボル)であること。 正しいシンボルは、truncationwrapescapecontrolselective-displayvertical-borderである。


Node:Active Display Table, Next:, Previous:Display Table Format, Up:Display Tables

活性な表示テーブル

各ウィンドウに表示テーブルを指定でき、 各バッファにも表示テーブルを指定できます。 バッファbがウィンドウwに表示されているとき、 ウィンドウwに表示テーブルがあればそれを使って表示します。 さもなければ、バッファbに表示テーブルがあればそれを使います。 それ以外では、標準の表示テーブルがあればそれを使います。 選択されている表示テーブルを活性な表示テーブルと呼びます。

window-display-table window Function
この関数は、ウィンドウwindowの表示テーブルを返す。 windowに表示テーブルが割り付けられていなければnilを返す。

set-window-display-table window table Function
この関数は、ウィンドウwindowの表示テーブルとして tableを設定する。 引数tableは、表示テーブルであるかnilであること。

buffer-display-table Variable
この変数はすべてのバッファで自動的にバッファローカルである。 バッファでの値は、そのバッファに対して用いる表示テーブルを指定する。 それがnilであると、バッファに表示テーブルを 割り付けていないことを意味する。

standard-display-table Variable
この変数の値はデフォルトの表示テーブルであり、 ウィンドウに表示テーブルがなく そのウィンドウのバッファにも表示テーブルがない場合に使われる。 この変数はデフォルトではnilである。

特定のウィンドウにおいて使用する表示テーブルがない場合には、 つまり、ウィンドウで未指定であり、そのバッファでも未指定であり、 standard-display-tablenilである場合には、 そのウィンドウ内のすべての文字コードには通常の画面表示慣習を使います。 See Usual Display


Node:Glyphs, Previous:Active Display Table, Up:Display Tables

字形

字形(glyph)は、文字を一般化したものです。 スクリーン上で1文字を占める像を表します。 文字と同様に、字形はLispでは整数で表現します。

字形としての各整数の意味は、字形テーブルで定義されます。 これは変数glyph-tableの値です。

glyph-table Variable
この変数の値は、現在の字形テーブルである。 これはベクトルであること。 g番目の要素は、字形コードgを定義する。 値がベクトルではなくnilであると、 すべての字形は単純(下記参照)である。

字形テーブルの要素として可能な型はつぎのとおりです。

string
この字形を出力するために端末へstringの文字群を送出する。 これは文字端末では使えるがウィンドウシステムでは使えない。
integer
この字形コードを字形コードintegerの別称として定義する。 字形に対してフェイスコードを指定するために別称を使うことができる。 下記参照。
nil
この字形は単純である。 通常の端末では、字形コード mod 524288 は出力すべき文字である。 ウィンドウシステムでは、字形コード mod 524288 は出力すべき文字あり、 字形コードを524288で除した値は出力中に使用すべきフェイス番号 (see Face Functions)である。 (524288は see Faces

字形コードが字形テーブルの長さに等しいか大きいと、 そのコードは自動的に単純とします。


Node:Beeping, Next:, Previous:Display Tables, Up:Display

ベルを鳴らす

本節では、ユーザーの注意を引くためにEmacsにベルを鳴らせる (あるいはスクリーンを点滅させる)方法について述べます。 ベルを鳴らす頻度はなるべく控えめにしてください。 頻繁にベルが鳴るとわずらわしいものです。 エラーを通知するほうがふさわしいときには、 単にベルを鳴らさないように注意してください。 (see Errors。)

ding &optional do-not-terminate Function
この関数は、ベルを鳴らすかスクリーンを点滅する (下記のvisible-bellを参照)。 また、do-not-terminatenilであると 現在実行中のキーボードマクロを終了する。

beep &optional do-not-terminate Function
dingの同義語。

visible-bell User Option
この変数は、ベルを鳴らすかわりにスクリーンを点滅させるかどうかを決定する。 nil以外であると点滅するを意味し、 nilであると点滅しないを意味する。 これは、ウィンドウシステムを用いている場合か、 端末のtermcapの定義にビジュアルベル機能(vb)がある 文字端末で有効である。

ring-bell-function Variable
これがnil以外であると、 Emacsに『ベルを鳴らす』方法を指定する。 この値は、引数なしの関数であること。


Node:Window Systems, Previous:Beeping, Up:Display

ウィンドウシステム

Emacsはいくつかのウィンドウシステムで、 特にXウィンドウシステムで動作します。 EmacsもXも用語『ウィンドウ』を使いますが、用法は異なります。 Emacsの1つのフレームは、Xでは1つのウィンドウです。 Emacsの個々のウィンドウについては、Xはまったくわかりません。

window-system Variable
この変数は、Emacsが動作しているウィンドウシステムの種類を Lispプログラムに伝える。 可能な値はつぎのとおりである。
x
Xを用いて表示している。
pc
MSDOSを用いて表示している。
w32
Windows NTかWindows 95を用いて表示している。
nil
文字ベースの端末を用いて表示している。

window-setup-hook Variable
この変数は、Emacsが初期化ファイルを処理したあとに実行する ノーマルフックである。 読者のファイル.emacs、(あれば)デフォルトの初期化ファイル、 端末固有のLispコードをすべてロードし、 フックterm-setup-hookを実行し終えてから、 このフック実行する。

このフックは内部目的用であり、 ウィンドウシステムとの通信を設定し、最初のウィンドウを作成する。 ユーザーが干渉すべきではない。


Node:Calendar, Next:, Previous:Display, Up:Top

カレンダーと日誌のカスタマイズ

カレンダーや日誌を個人の好みに合わせるための カスタマイズ項目がたくさんあります。


Node:Calendar Customizing, Next:, Up:Calendar

カレンダーのカスタマイズ

変数view-diary-entries-initiallytを設定しておくと、 カレンダーを呼び出すと現在の日に対する日誌記録を自動的に表示できます。 その日がウィンドウで見える場合に限って日誌記録が表示されます。 つぎの行、

(setq view-diary-entries-initially t)
(calendar)

を個人のファイル.emacsに入れておくと、 Emacsを起動するたびに、カレンダーと日誌の両者のウィンドウを表示します。

同様に、変数view-calendar-holidays-initiallytを設定しておくと、 カレンダーに入ると自動的に3か月分の祝祭日一覧を表示します。 祝祭日一覧は別のウィンドウに現れます。

変数mark-diary-entries-in-calendartを設定すると、 日誌に入れてある日付に印を付けられます。 カレンダーのウィンドウ内容を再計算するときにこの効果が現れます。 これらの日付に印を付ける方法は2つあります。 ディスプレイで使えるならばフェイス(see Faces)を変更するか、 日付にプラス記号(+)を付加します。

同様に、変数mark-holidays-in-calendartを設定すると、 フェイスを変えるかアスタリスク(*)を付加することで 祝祭日に印を付けられます。

変数calendar-holiday-markerは、 祝祭日の日付にどのように印を付けるかを指定します。 その値は、日付に付加する文字か日付の表示に使うフェイス名です。 同様に、変数diary-entry-markerは、 日誌に入っている日付にどのように印を付けるかを指定します。 カレンダー(calendar)モードは、このような目的のために holiday-facediary-faceという名前のフェイスを作成します。 Emacsが端末で複数のフェイスを扱える場合には、 これらの変数のデフォルト値はこれらのシンボルです。

変数calendar-load-hookは、 (カレンダーを実際に表示し始めるまえに)カレンダーパッケージを初めて ロードしたときに実行されるノーマルフックです。

カレンダーを開始するとノーマルフックinitial-calendar-window-hookを 実行します。 カレンダーの表示を再計算してもこのフックは実行されません。 しかし、コマンドqでカレンダーを抜けてから再度カレンダーに入ると このフックを再度実行します。

変数today-visible-calendar-hookは、 今日の日付がウィンドウで見えるときに カレンダーバッファにカレンダーの準備を終えてから実行される ノーマルフックです。 このフックの1つの用途は、今日の日付をアスタリスクで置き換えることです。 それにはフック関数calendar-star-dateを使います。

(add-hook 'today-visible-calendar-hook 'calendar-star-date)

他の標準的なフック関数は、フェイスを変更するかアスタリスクを付加することで 現在の日付に印を付けます。 つぎのように使います。

(add-hook 'today-visible-calendar-hook 'calendar-mark-today)

変数calendar-today-markerは、 今日の日付の印の付け方を指定します。 その値は、日付に付加する文字か日付の表示に使うフェイス名です。 この目的のためにcalendar-today-faceという名前のフェイスがあります。 Emacsが端末で複数のフェイスを扱える場合には、 この変数のデフォルト値はこのシンボルです。

同様なノーマルフックtoday-invisible-calendar-hookは、 現在の日付がウィンドウで見えないときに実行されます。


Node:Holiday Customizing, Next:, Previous:Calendar Customizing, Up:Calendar

祝祭日のカスタマイズ

Emacsは、複数のリストの中の1つのリストに入っている項目群で 定義される祝祭日を把握しています。 これらの祝祭日のリストに祝祭日を追加したり削除して 個人の目的に合うようにカスタマイズできます。 Emacsが使用する祝祭日のリストは、 一般祝祭日(general-holidays)、 地域祝祭日(local-holidays)、 キリスト教祝祭日(christian-holidays)、 ヘブライ(ユダヤ教)祝祭日(hebrew-holidays)、 イスラム(回教徒)祝祭日(islamic-holidays)、 その他の祝祭日(other-holidays)です。

一般祝祭日は、デフォルトでは、合州国に共通の祝祭日です。 これらの祝祭日を削除するには、general-holidaysnilを設定します。

デフォルトの地域祝祭日はありません(サイトによってはある)。 以下に述べるように、 変数local-holidaysに祝祭日の任意のリストを設定できます。

デフォルトでは、Emacsが承知している宗教のすべての祝祭日が Emacsに入っているのではなく、世俗的なカレンダーに共通するものだけです。 宗教上の祝祭日を網羅的に入れるには、 all-christian-calendar-holidaysall-hebrew-calendar-holidaysall-islamic-calendar-holidaysの変数のいずれか(あるいは、すべて)に tを設定します。 宗教上の祝祭日を削除するには、対応する christian-holidayshebrew-holidaysislamic-holidaysの変数のいずれか(あるいは、すべて)に nilを設定します。

変数other-holidaysには、祝祭日の任意のリストを設定できます。 このリストは、普通は空ですが、個人的な使用を意図しています。

リスト(general-holidayslocal-holidayschristian-holidayshebrew-holidaysislamic-holidaysother-holidays)のおのおのは、 祝祭日(あるいは祝祭日のリスト)を記述する 祝祭日形式(holiday form)から成るリストです。

可能な祝祭日形式の一覧をつぎに示します。 月と日は1から数えますが、『曜日』は日曜日を0と数えます。 要素stringは、文字列で表した祝祭日の名称です。

(holiday-fixed month day string)
グレゴリオ暦の固定した日付。
(holiday-float month dayname k string)
グレゴリオ暦のmonth月のk番目の曜日dayname。 (日曜日はdayname=0、…。) kが負であると、月末から数える。
(holiday-hebrew month day string)
ヘブライ暦の固定した日付。
(holiday-islamic month day string)
イスラム暦の固定した日付。
(holiday-julian month day string)
ユリウス暦の固定した日付。
(holiday-sexp sexp string)
Lisp式sexpで計算される日付。 計算式では、年として変数yearを使い、祝祭日の日付を返す。 あるいは、その年に該当する祝祭日がなければnilを返す。 sexpの値は、(month day year)の形の リストで表した日付であること。
(if condition holiday-form)
条件conditionが真である場合にのみ祝祭日になる。
(function [args])
引数argsで関数functionを呼び出して計算される日付のリスト。

たとえば、フランスで7月14日に祝われる革命記念日(Bastille Day)を 扱えるようにするにはつぎのようにします。

(setq other-holidays '((holiday-fixed 7 14 "Bastille Day")))

祝祭日形式 (holiday-fixed 7 14 "Bastille Day")は、 7の月(7月)の14日目を指定します。

多くの祝祭日は、特定の月の特定の週にあります。 バージン諸島で4月の第4月曜日に祝われる ハリケーン祈願日(Hurricane Supplication Day)を記述する 祝祭日形式はつぎのようになります。

(holiday-float 8 1 4 "Hurricane Supplication Day")

ここで、8は8月、1は月曜日(日曜日は0、火曜日は2といった具合)、4は その月の4回目(1は最初、2は2回目、-1は最後、-2は最後の1つまえ といった具合)を意味します。

ヘブライ暦、イスラム暦、ユリウス暦の固定した日付の祝祭日も指定できます。 たとえば、

(setq other-holidays
      '((holiday-hebrew 10 2 "Last day of Hanukkah")
        (holiday-islamic 3 12 "Mohammed's Birthday")
        (holiday-julian 4 2 "Jefferson's Birthday")))

は、ハヌカー祭の最終日(ヘブライ暦の月はニサンNisanを1と数える)、 イスラムが祝うモハメッドの誕生日 (イスラム暦の月はムハラMuharramを1と数える)、 ユリウス暦の1743年4月2日のトーマスジェファーソンの誕生日を 追加します。

条件付きの祝祭日を含めるには、Emacs Lispのifholiday-sexpを 使います。 たとえば、アメリカ大統領選挙は、4で割り切れる年の11月の第1月曜日の あとの最初の火曜日に行われます。

(holiday-sexp (if (= 0 (% year 4))
                   (calendar-gregorian-from-absolute
                    (1+ (calendar-dayname-on-or-before
                          1 (+ 6 (calendar-absolute-from-gregorian
                                  (list 11 1 year))))))
              "US Presidential Election"))

あるいは、

(if (= 0 (% displayed-year 4))
    (fixed 11
           (extract-calendar-day
             (calendar-gregorian-from-absolute
               (1+ (calendar-dayname-on-or-before
                     1 (+ 6 (calendar-absolute-from-gregorian
                              (list 11 1 displayed-year)))))))
           "US Presidential Election"))

特別な計算を必要とする祝祭日は、これまでの形式にあてはまりません。 そのような場合、計算を行うLisp関数を書く必要があります。 たとえば、日食月食を含めるには、 other-holidays(eclipses)を追加して、 以下のような形でカレンダーウィンドウの見えている範囲の期間内の 対応するグレゴリオ暦の日付の(空である可能性もある)リストを 返すEmacs Lisp関数(eclipses)を書きます。

(((6 27 1991) "Lunar Eclipse") ((7 11 1991) "Solar Eclipse") ... )


Node:Date Display Format, Next:, Previous:Holiday Customizing, Up:Calendar

日付表示書式

日誌、モード行、メッセージに現れる日付の表示方法は、 calendar-date-display-formを設定することでカスタマイズできます。 この変数は、 文字列で表した数字が入ったmonthdayyearの各変数と、 英字の文字列が入ったmonthnamedaynameの各変数を 用いた式のリストを保持しています。 アメリカスタイルでは、このリストのデフォルト値はつぎのようになります。

((if dayname (concat dayname ", ")) monthname " " day ", " year)

一方、ヨーロッパスタイルでは、この値のデフォルトはつぎのようになります。

((if dayname (concat dayname ", ")) day " " monthname " " year)

ISO規格の日付の表記法はつぎのとおりです。

(year "-" month "-" day)

典型的なアメリカの書式はつぎのとおりです。

(month "/" day "/" (substring year -2))


Node:Time Display Format, Next:, Previous:Date Display Format, Up:Calendar

時刻表示書式

カレンダーと日誌はデフォルトではアメリカスタイル、 つまり、12時制で時刻を表示します。 ヨーロッパスタイルやアメリカ軍の24時制を好むならば、 変数calendar-time-display-formを変更します。 この変数は、 文字列で表した数字が入った12-hours24-hoursminutesの各変数と、 英字の文字列が入ったam-pmtime-zoneの各変数を 用いた式のリストを保持しています。 calendar-time-display-formのデフォルト値はつぎのとおりです。

(12-hours ":" minutes am-pm
          (if time-zone " (") time-zone (if time-zone ")"))

つぎの値では、ヨーロッパスタイルの時刻になります。

(24-hours ":" minutes
          (if time-zone " (") time-zone (if time-zone ")"))


Node:Daylight Savings, Next:, Previous:Time Display Format, Up:Calendar

夏時間

Emacsは、標準時間と夏時間の違いを理解しています。 つまり、日出入時刻、夏至冬至、春分秋分、朔弦望ではその違いを考慮します。 夏時間の規則は、地域ごと、年ごとに変わりえます。 正しく扱うためには、どの規則が適用されるかをEmacsが知っている必要があります。

読者の居住地域に適用される規則を記録している オペレーティングシステムもあります。 これらのシステム上では、Emacsは自動的にシステムから必要な情報を得られます。 この情報の一部やすべてが欠落していると、 GNU世界の中心であるマサチューセッツ州ケンブリッジで 現在使用している規則で補います。

デフォルトで選んだ規則が読者の地域に適切でないときには、 変数calendar-daylight-savings-startscalendar-daylight-savings-endsに設定してEmacsに伝えます。 これらの値は、変数yearを使ったLisp式である必要があります。 これらの式を評価すると、夏時間を開始/終了するグレゴリオ暦の日付を表す (month day year)の形のリストに なる必要があります。 夏時間をとらない場合には、値はnilであるべきです。

Emacsは、これらの式を用いて夏時間の開始と終了を判定し、 祝祭日や太陽/月に関する時刻を補正します。

マサチューセッツ州ケンブリッジに対する値は、つぎのとおりです。

(calendar-nth-named-day 1 0 4 year)
(calendar-nth-named-day -1 0 10 year)

つまり、指定されたyear年の4月の最初の日曜日と その年の10月の最後の日曜日です。 10月1日に夏時間を始めると変更したとすると、 変数calendar-daylight-savings-startsに つぎのように設定します。

(list 10 1 year)

より複雑な例として、ヘブライ暦のニサンの初日に夏時間が始まるとしましょう。 calendar-daylight-savings-startsには、 つぎの値を設定します。

(calendar-gregorian-from-absolute
  (calendar-absolute-from-hebrew
    (list 1 1 (+ year 3760))))

これは、ニサンはヘブライ暦の最初の月であり、 ヘブライ暦年とグレゴリオ暦年はニサンで3760年違うからです。

読者の地域で夏時間をとっていなかったり、 つねに標準時間を望む場合には、 calendar-daylight-savings-startscalendar-daylight-savings-endsnilを設定します。

変数calendar-daylight-time-offsetは、 夏時間と標準時間の分で計った差を指定します。 ケンブリッジに対する値は60です。

変数calendar-daylight-savings-starts-timecalendar-daylight-savings-ends-timeは、 夏時間と標準時間との移行が行われる 地方時の真夜中の0時からの経過分を指定します。 ケンブリッジでは、どちらの変数の値も120です。


Node:Diary Customizing, Next:, Previous:Daylight Savings, Up:Calendar

日誌のカスタマイズ

通常、日誌用バッファのウィンドウのモード行には、 日誌記録の日付に一致する祝祭日があれば表示されます。 祝祭日を検査する処理には数秒を要するので、 祝祭日情報を含めると日誌用バッファの表示に遅れが生じます。 祝祭日情報をなくして日誌用バッファの表示を速くしたい場合には、 変数holidays-in-diary-buffernilを設定します。

変数number-of-diary-entriesは、 一度に表示する日誌記録の日数を制御します。 これは、view-diary-entries-initiallytであるときの 最初の表示に影響します。 たとえば、デフォルト値は1で、現在の日付の日誌記録のみを表示します。 値が2であると、現在とつぎの日付の日誌記録を表示します。 この値は7要素のベクトルでもかまいません。 たとえば、値が[0 2 2 2 2 4 1]であると、 日曜日には日誌記録をなにも表示せず、 月曜日から木曜日には現在とつぎの日付の日誌記録を表示し、 金曜日には金曜日から月曜日の日誌記録を表示し、 土曜日にはその日だけの日誌記録を表示します。

変数print-diary-entries-hookは、 日誌用バッファで現在見えている日誌記録のみを収めた一時的なバッファの 準備ができると実行されるノーマルフックです。 (他の関係ない日誌記録は一時的なバッファには入っていない。 日誌用バッファではそれらは隠されている。) このフックのデフォルト値は、コマンドlpr-bufferで印刷します。 別のコマンドで印刷したい場合には、単にこのフックの値を変更します。 別の用途は、たとえば、行を日付と時刻で並び替えることです。

diary-date-formsに設定すれば、 目的に合うように個人の日誌ファイル内の日付の書式を アメリカスタイルやヨーロッパスタイルにカスタマイズできます。 この変数は、日付を認識するパターンのリストです。 各パターンは、正規表現(see Regular Expressions)や monthdayyearmonthnamedaynameのシンボルを要素とするリストです。 これらの要素すべては、日誌ファイル内の特定種類のテキストに一致する パターンとして働きます。 全体として日付パターンとして一致するには、 すべての要素が順に一致する必要があります。

日付パターンの正規表現は、*を単語構成文字に変更した 標準の構文テーブルを用いて通常どおりに一致をとります。

monthdayyearmonthnamedaynameの シンボルは、対象にしている月、日、年、月の名前、曜日です。 数に一致するシンボルは、数の先頭にある0を許します。 名前に一致するシンボルは、3文字の省略形や大文字で始まることを許します。 日誌記録では*は『任意の日』『任意に月』などを表し、 対象とする日付に関係なく一致するべきなので、 すべてのシンボルは*に一致できます。

アメリカスタイルのdiary-date-formsのデフォルト値はつぎのとおりです。

((month "/" day "[^/0-9]")
 (month "/" day "/" year "[^0-9]")
 (monthname " *" day "[^,0-9]")
 (monthname " *" day ", *" year "[^0-9]")
 (dayname "\\W"))

リスト内の日付パターンは、互いに排他的であり、 日誌記録の日付と1つの白文字以外には他の部分に一致してはいけません。 互いに排他的であるためには、 パターンは日付を終える白文字を越えて日誌記録本文に一致する必要があります。 それには、日付パターンの最初の要素はbackupである必要があります。 これにより、日付を認識する処理では、 一致し終えてから日誌記録の現在の単語の先頭に戻ります。 たとえbackupを使ったとしても、 日付パターンは日誌本体の最初の単語を越えて一致してはいけません。 ヨーロッパスタイルのdiary-date-formsのデフォルト値は、 つぎのとおりです。

((day "/" month "[^/0-9]")
 (day "/" month "/" year "[^0-9]")
 (backup day " *" monthname "\\W+\\<[^*0-9]")
 (day " *" monthname " *" year "[^0-9]")
 (dayname "\\W"))

ここでは、3番目のパターンでbackupを使っています。 4番目のパターンと区別するために、 日付のつぎの単語の一部と一致する必要があるからです。


Node:Hebrew/Islamic Entries, Next:, Previous:Diary Customizing, Up:Calendar

ヘブライ暦日付やイスラム暦日付の日誌記録

日誌ファイルには、世界標準のグレゴリオ暦日付に加えて、 ヘブライ暦日付やイスラム暦日付を入れることもできます。 しかし、そのような記録の認識には時間がかかり、 ほとんどの人はそれらを使わないので、 それらは明示的にオンにする必要があります。 日誌でヘブライ暦日付の日誌記録を認識できるように望むなら、 たとえば、つぎのようにする必要があります。

(add-hook 'nongregorian-diary-listing-hook 'list-hebrew-diary-entries)
(add-hook 'nongregorian-diary-marking-hook 'mark-hebrew-diary-entries)

イスラム暦日付の日誌記録を望むなら、つぎのようにします。

(add-hook 'nongregorian-diary-listing-hook 'list-islamic-diary-entries)
(add-hook 'nongregorian-diary-marking-hook 'mark-islamic-diary-entries)

ヘブライ暦日付やイスラム暦日付の日誌記録は、 グレゴリオ暦日付と同じ形式ですが、 ヘブライ暦日付のまえにはH、 イスラム暦日付のまえにはIがある点が異なります。 さらに、ヘブライ暦やイスラム暦の月は、最初の3文字で一意に決まらないため、 月の省略形は使えません。 たとえば、ヘブライ暦日付Heshvan 25の日誌記録はつぎのようになります。

HHeshvan 25 Happy Hebrew birthday!

これはヘブライ暦日付Heshvan 25に対する任意の日誌に現れます。 イスラム暦日付Dhu al-Qada 25に一致する日誌記録はつぎのようになります。

IDhu al-Qada 25 Happy Islamic birthday!

グレゴリオ暦日付の日誌記録では、 ヘブライ暦日付とイスラム暦日付の記録は、 それらの前にアンパサンド(&)があると印付けされません。

ヘブライ暦やイスラム暦において 指定した日付や似た日付に一致する日誌記録を作成するための カレンダーのコマンド一覧をつぎに示します。

i h d
選択した日付に対応するヘブライ暦日付に日誌記録を追加する (insert-hebrew-diary-entry)。
i h m
選択した日付に対応するヘブライ暦月の日に日誌記録を追加する (insert-monthly-hebrew-diary-entry)。 この日誌記録は、選択した日付のヘブライ暦の月内の日と同じ 任意の日付に一致する。
i h y
選択した日付のヘブライ暦年の日に日誌記録を追加する (insert-yearly-hebrew-diary-entry)。 この日誌記録は、選択した日付のヘブライ暦の月とその月内の日と同じ 任意の日付に一致する。
i i d
選択した日付に対応するイスラム暦日付に日誌記録を追加する (insert-islamic-diary-entry)。
i i m
選択した日付に対応するイスラム暦の月内の日に日誌記録を追加する (insert-monthly-islamic-diary-entry)。
i i y
選択した日付のイスラム暦年の日に日誌記録を追加する (insert-yearly-islamic-diary-entry)。

これらのコマンドは、日誌記録の対応する普通のコマンドと同様に働きます。 カレンダーウィンドウにおいてポイントがある日付に作用し、 日誌記録の日付に関する部分のみを挿入します。 日誌記録の本文は自分で入力する必要があります。


Node:Fancy Diary Display, Next:, Previous:Hebrew/Islamic Entries, Up:Calendar

装飾日誌表示

日誌表示は、日誌用バッファを準備してからフックdiary-display-hookを 実行することで動作します。 このフックのデフォルト値(simple-diary-display)は、 関係ない日誌記録を隠してからバッファを表示します。 しかし、つぎのようにフックを指定すると

(add-hook 'diary-display-hook 'fancy-diary-display)

装飾日誌表示を行えます。 日誌記録と祝祭日を表示専用の特別なバッファにコピーして表示します。 別のバッファにコピーするので、表示テキストが綺麗になるように変更できます。 たとえば、日付順に記録をソートするなどです。

単純な日誌表示では、print-diary-entriesでバッファ内容を印刷できます。 1週間分の毎日の日誌を印刷するには、 その週の日曜日にポイントを置いて7 dと打ってから M-x print-diary-entriesを行います。 祝祭日が入っていると表示が遅くなりますが、 変数holidays-in-diary-buffernilを設定すると速くできます。

通常、装飾日誌用バッファでは、 たとえ祝祭日であっても日誌記録がない日は表示しません。 そのような日を装飾日誌用バッファに表示するには、 変数diary-list-include-blankstを設定します。

装飾日誌表示を使うときには、 ノーマルフックlist-diary-entries-hookを使って 各日誌記録を時刻でソートできます。 つぎのようにします。

(add-hook 'list-diary-entries-hook 'sort-diary-entries t)

これは、各日ごとに認識できる時刻で始まる日誌記録をソートします。 各日の先頭には時刻のついていない日誌項目がきます。

装飾日誌表示には、取り込んだ日誌ファイルを処理する能力もあります。 これにより、グループのメンバは、グループに共通な行事を記述した 日誌ファイルを共有できます。 つぎのような行を日誌ファイルに書きます。

#include "filename"

そうすると、ファイルfilenameから 日誌記録を装飾日誌用バッファに取り込みます。 取り込み機構は再帰的ですから、 取り込んだファイル内で別のファイルを取り込むことができます。 もちろん、取り込みが循環しないように注意してください。 取り込み機能をオンにするにはつぎのようにします。

(add-hook 'list-diary-entries-hook 'include-other-diary-files)
(add-hook 'mark-diary-entries-hook 'mark-included-diary-files)

通常の日誌表示は個人の日誌ファイルの記録を直接表示するため、 取り込み機構は装飾日誌表示でのみ動作します。


Node:Sexp Diary Entries, Next:, Previous:Fancy Diary Display, Up:Calendar

S式項目と装飾日誌表示

S式を使った日誌記録は、 複雑な条件で適用される日誌記録を作る以上のことができます。 装飾日誌表示を使っている場合には、S式日誌項目は、 日付に依存した記録テキストを生成できます。 たとえば、記念日の記録では、テキストに何回目の記念日であるかを入れられます。 したがって、つぎの日誌記録の%dは年齢で置き換えられます。

%%(diary-anniversary 10 31 1948) Arthur's birthday (%d years old)

つまり、装飾日誌用バッファでは、1990年10月31日の項目はつぎのようになります。

Arthur's birthday (42 years old)

日誌ファイルにつぎの項目が入っていると、

%%(diary-anniversary 10 31 1948) Arthur's %d%s birthday

装飾日誌用バッファでは、1990年10月31日の項目はつぎのようになります。

Arthur's 42nd birthday

同様に、周期的な日誌項目では繰り返し回数を計算できます。

%%(diary-cyclic 50 1 1 1990) Renew medication (%d%s time)

は、1990年9月8日の装飾日誌表示ではつぎのようになります。

Renew medication (5th time)

当日の日誌項目としてだけでなく、 それよりまえの日の日誌項目にも含めるためのS式日誌項目があります。 たとえば、記念日の1週間前に督促がほしいときには、 つぎのようにします。

%%(diary-remind '(diary-anniversary 12 22 1968) 7) Ed's anniversary

すると、装飾日誌には、12月15日と12月22日に

Ruth & Ed's anniversary

と表示されます。

関数diary-dateは、整数や整数のリストやtで指定した 月、日、年の組み合わせで表される日付に適用されます。 たとえば、

%%(diary-date '(10 11 12) 22 t) Rake leaves

により、装飾日誌には、各年の10月22日、11月22日、12月22日には

Rake leaves

と表示されます。

関数diary-floatにより、 11月の第3金曜日とか4月の最後の火曜日といった 日付に適用する日誌記録を記述できます。 パラメータは、月month、曜日dayname、添字nです。 日曜日をdayname=0、月曜日をdayname=1、…として、 month月のn番目の曜日daynameに項目が現れます。 nが負であると、month月の月末から数えます。 monthは、月のリストでも、1つの月でも、全部の月を指定するtでも かまいません。 省略可能なパラメータdayを指定して、 month月のn番目の曜日daynameの 前後のday日を指定できます。 nが正だとdayのデフォルトは1であり、 nが負だとdayのデフォルトはmonth月の月末です。 たとえば、

%%(diary-float t 1 -1) Pay rent

は、装飾日誌に各月の最後の月曜日に

Pay rent

を表示します。

S式日誌項目の一般性により、アルゴリズムで日誌項目を指定できます。 S式日誌項目には、項目を当該日に適用するどうかを計算する式を含められます。 その値がnil以外であると、その項目を当該日に適用します。 その式では、対象とする日付を知るために変数dateを使えます。 この変数の値は、グレゴリオ暦で表した リスト(month day year)です。

毎月のウィークデイである21日か、 21日が週末の場合にはそのまえの金曜日に給料を支払われるとしましょう。 そのような日付に一致するS式日誌項目はつぎのように書けます。

&%%(let ((dayname (calendar-day-of-week date))
         (day (car (cdr date))))
      (or (and (= day 21) (memq dayname '(1 2 3 4 5)))
          (and (memq day '(19 20)) (= dayname 5)))
         ) Pay check deposited

以下のS式日誌項目は、日付に依存して変わるテキストを 日誌項目に入れる機能を(装飾日誌表示で)利用できます。

%%(diary-sunrise-sunset)
今日の地方時での日出入時刻に対する日誌項目を作る。
%%(diary-phases-of-moon)
月に朔弦望に対する日誌項目を作る。
%%(diary-day-of-year)
年内の通算日数と残り日数で今日の日誌項目を作る。
%%(diary-iso-date)
今日に対応するISO商用暦の日誌項目を作る。
%%(diary-julian-date)
今日に対応するユリウス暦の日誌項目を作る。
%%(diary-astro-day-number)
今日に対応する天文通算日(ユリウス日)の日誌項目を作る。
%%(diary-hebrew-date)
今日に対応するヘブライ暦の日誌項目を作る。
%%(diary-islamic-date)
今日に対応するイスラム暦の日誌項目を作る。
%%(diary-french-date)
今日に対応するフランス革命暦の日誌項目を作る。
%%(diary-mayan-date)
今日に対応するマヤ暦の日誌項目を作る。

したがって、

&%%(diary-hebrew-date)

を含んだ日誌項目は、装飾日誌表示を使っていると、 毎日の日誌表示に対応するヘブライ暦の日付を含めることになります。 (単純な日誌表示では、行&%%(diary-hebrew-date)は すべての日付の日誌に現れるが、特別なことはなにもしない。)

つぎの関数は、ある標準的な方法でヘブライ暦に基づく S式日誌項目を構成するために使えます。

%%(diary-rosh-hodesh)
各ヘブライ月の礼拝の始まりと終りを教える日誌項目を作る。
%%(diary-parasha)
毎週のシナゴーグ朗読会を教える土曜日の日誌項目を作る。
%%(diary-sabbath-candles)
安息日のたそがれの地方時を教える金曜日の日誌項目を作る。
%%(diary-omer)
適切ならばオーメル13 の回数を与える日誌項目を作る。
%%(diary-yahrzeit month day year) name
命日に対応した日誌項目を作る。 命日の日付はグレゴリオ暦で指定する。 正しいヘブライ暦の追悼日とその前日に日誌項目が現れる。 (ヨーロッパスタイルでは、パラメータの順序を daymonthyearと変える。)


Node:Appt Customizing, Previous:Sexp Diary Entries, Up:Calendar

約束の警告表示のカスタマイズ

Emacsにどのように約束の警告表示を行わせ、 どの程度前から行わせるかは、つぎの変数に設定することで正確に指定できます。

appt-message-warning-time
約束の警告表示を開始する時間を分で表したもの。 デフォルトは10分である。
appt-audible
これがnil以外であると、Emacsは約束の警告表示として端末のベルを鳴らす。 デフォルトはt
appt-visible
これがnil以外であると、Emacsは約束のメッセージをエコー領域に表示する。 デフォルトはt
appt-display-mode-line
これがnil以外であると、Emacsは約束までの残り分数をモード行に表示する。 デフォルトはt
appt-msg-window
これがnil以外であると、 Emacsは約束のメッセージを別のウィンドウに表示する。 デフォルトはt
appt-disp-window-function
この変数は、約束のメッセージを表示するウィンドウを作るための関数を保持する。
appt-delete-window-function
この変数は、時間が過ぎたら 約束のメッセージを表示したウィンドウを削除するための関数を保持する。
appt-display-duration
約束のメッセージを表示する秒数。 デフォルトは5秒である。


Node:Tips, Next:, Previous:System Interface, Up:Top

ヒントと慣習

本章では、Emacs Lispの機能についてさらに述べることはしません。 かわりに、前章までに述べてきた機能を効率よく使うための助言や Emacs Lispプログラマが従うべき慣習について述べます。


Node:Coding Conventions, Next:, Up:Tips

Emacs Lispのコーディングの慣習

ここでは、読者が広く使われることを意図した Emacs Lispコードを書く場合に従うべき慣習について述べます。


Node:Compilation Tips, Next:, Previous:Coding Conventions, Up:Tips

コンパイル済みコードを速くするヒント

バイトコンパイルしたLispプログラムの実行速度を改良する方法を示します。


Node:Documentation Tips, Next:, Previous:Compilation Tips, Up:Tips

説明文字列に関するヒント

説明文字列を書くうえでのヒントや慣習を述べます。 コマンドM-x checkdoc-minor-modeを実行して、 これらの慣習の多くを確認できます。


Node:Comment Tips, Next:, Previous:Documentation Tips, Up:Tips

コメントの書き方のヒント

コメントを置く場所とそれらの字下げ方法については以下のような慣習を推奨します。

;
1つのセミコロン;で始まるコメントは、 ソースコードの右側で同じコラム位置に揃えること。 そのようなコメントは、その行のコードの動作を説明する。 lispモードやその関連するモードでは、 コマンドM-;indent-for-comment)で 自動的に右側の正しい位置に;を挿入したり、 そのようなコメントが既存ならば整列できる。

つぎとその下の例は、Emacsのソースから持ってきたものである。

(setq base-version-list                 ; there was a base
      (assoc (substring fn 0 start-vn)  ; version to which
             file-version-assoc-list))  ; this looks like
                                        ; a subversion

;;
2つのセミコロン;;で始まるコメントは、 その部分のコードの字下げに揃えること。 そのようなコメントは、その後続の行の目的や その箇所でのプログラムの状態を記述する。
(prog1 (setq auto-fill-function
             ...
             ...
  ;; update mode line
  (force-mode-line-update)))

説明文字列を持たない各関数 (所属するパッケージで内部向けにのみ使用される関数)では、 関数が行うことと正しい呼び出し方を記述した 2つのセミコロンで始まるコメントを関数のまえに書くこと。 各引数の意味とその可能な値を関数がどのように解釈するかを正確に説明すること。

;;;
3つのセミコロン;;;で始まるコメントは、左端に揃えること。 そのようなコメントは、関数定義の外側で使い、 プログラムの設計原理を説明する一般的な表明である。 たとえばつぎのとおり。
;;; This Lisp code is run in Emacs
;;; when it is to operate as a server
;;; for other processes.

3つのセミコロンで始まるコメントの別の使い方は、 関数内の行をコメントにする場合である。 そのような行が左端に留まるように3つのセミコロンを使うのである。

(defun foo (a)
;;; This is no longer necessary.
;;;  (force-mode-line-update)
  (message "Finished with %s" a))

;;;;
4つのセミコロン;;;;で始まるコメントは、 左端に揃えて、プログラムの主要な部分のヘッダに使う。 たとえばつぎのとおり。
;;;; The kill ring

M-;indent-for-comment)や <TAB>(lisp-indent-line)などの Emacsのlispモードの字下げコマンドは、 これらの慣習にしたがって自動的にコメントを字下げします。 See Comments


Node:Library Headers, Previous:Comment Tips, Up:Tips

Emacsライブラリのヘッダの慣習

Emacsには、コメントをいくつかの部分に分けて作者などの情報を与えるために、 Lispライブラリの特別なコメントに対する慣習があります。 本節ではそれらの慣習について述べます。 まず、例を示します。

;;; lisp-mnt.el --- minor mode for Emacs Lisp maintainers

;; Copyright (C) 1992 Free Software Foundation, Inc.

;; Author: Eric S. Raymond <esr@snark.thyrsus.com>
;; Maintainer: Eric S. Raymond <esr@snark.thyrsus.com>
;; Created: 14 Jul 1992
;; Version: 1.2
;; Keywords: docs

;; This file is part of GNU Emacs.
...
;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.

最初の行はつぎの形式であるべきです。

;;; filename --- description

この記述は1行で完全になるようにします。

著作権表示のあとには、;; header-name:で始まる いくつかのヘッダコメント(header comment)行が続きます。 header-nameに使う可能性のある慣習の一覧を以下に示します。

Author
この行では、少なくともライブラリの主作者の 氏名とネットワークアドレスを明記する。

複数の作者がいる場合には、以下のように、 ;;とタブ文字で始めた継続行に その人達を列挙する。

;; Author: Ashwin Ram <Ram-Ashwin@cs.yale.edu>
;;      Dave Sill <de5@ornl.gov>
;;      Dave Brennan <brennan@hal.com>
;;      Eric Raymond <esr@snark.thyrsus.com>

Maintainer
この行には、作者行(Author)のように1人の氏名とアドレス、 アドレスのみ、文字列FSFのいずれかを書く。 保守者行(Maintainer)がない場合には、 作者行の人達が保守していると仮定する。 上の例は、保守者行が冗長であり、少々いんちきである。

作者行(Author)と保守者行(Maintainer)の考えは、 手作業で名前を探さずに『保守者にメイルを送る』ようなLisp関数を 作れるようにするためである。

ネットワークアドレスに加えて人の氏名も書く場合には、 ネットワークアドレスを<...>で必ず囲むこと。

Created
この行は省略できるが、ファイルの作成日時を書く。 歴史的な意味だけである。
Version
各Lispプログラムの版番号を記録しておきたい場合に、 この行に版番号を書く。
Adapted-By
このヘッダ行では、(たとえば、スタイルの慣習に適合するように変更したなどの) インストールのためにライブラリを受理した人の名前を書く。
Keywords
この行には、ヘルプコマンドfinder-by-keyword向けの キーワードを書く。 意味のあるキーワードを理解するためにこのコマンドを試してほしい。

この部分は重要である。 人々が特定の話題で探して読者のパッケージをみつけるであろう。 キーワードは空白やカンマで区切る。

ほとんどのLispライブラリには、 AuthorKeywordsのヘッダコメント行が必要です。 残りのものは必要に応じて使います。 別の名前のヘッダ行があってもかまいません。 それらには標準的な意味はありませんが、害になることもありません。

ライブラリファイルの内容を分割するために形式を定めたコメントも使います。 それらを以下に示します。

;;; Commentary:
ライブラリの動作を説明する入門的なコメントを始める。 著作権表示の直後にきて、 Change LogHistoryCodeのいずれかのコメント行で終る。 このテキストはパッケージfinderが使うので、 その文脈で意味があるようにすること。
;;; Documentation
;;; Commentary:のかわりに使っているファイルもあるが、 ;;; Commentary:のほうが好ましい。
;;; Change Log:
(変更履歴をライブラリに収める場合の) ライブラリファイルに収めた変更記録情報を始める。 Emacsで配布されるほとんどのLispファイルでは、 変更履歴はファイルChangeLogに収めてあり、 ソースファイルには収めない。 それらのファイルには;;; Change Log:行はない。
;;; Code:
プログラムの実際のコードを始める。
;;; filename ends here
これは最終行(footer line)であり、ファイルの末尾に現れる。 その目的は、最終行が欠如していることでファイルが切り詰められていることが わかるようにするのである。


Node:GNU Emacs Internals, Next:, Previous:Tips, Up:Top

GNU Emacsの内部

本章では、Lispライブラリをあらかじめロードした実用的なEmacsの実行形式の ダンプ方法、メモリ領域の割り当て方、 Cプログラマに興味があるようなGNU Emacsの内部について述べます。


Node:Building Emacs, Next:, Up:GNU Emacs Internals

Emacsの構築方法

本節では、Emacsの実行形式を構築する手順を説明します。 メイクファイルが自動的にこれらすべてを行うので、 Emacsを構築してインストールするために本節のことがらを 読者が知っている必要はありません。 本節の内容は、Emacsの保守者向けです。

ディレクトリsrcのCソースファイル群をコンパイルすると、 temacsと呼ばれる実行形式ファイルが作られます。 これは裸のインピュアEmacs(bare impure Emacs)とも呼びます。 これには、Emacs Lispインタープリタと入出力ルーティンが含まれますが、 編集コマンドは入っていません。

コマンドtemacs -l loadupで、 実用的なEmacsの実行形式を作るためにtemacsを使います。 これらの引数は、temacsに対して ファイルloadup.elで指定したLispファイル群を評価するように指示します。 これらのファイルはEmacsの通常の編集環境を作り上げ、 その結果、Emacsは裸ではありませんがまだインピュアです。

標準のLispファイル群をロードするにはかなり時間が必要です。 しかし、読者がEmacsを実行するたびにこれを行う必要はありません。 temacsは、必要なファイルをあらかじめロードしたemacsという 実行形式プログラムとしてダンプできます。 emacsはファイル群をロードする必要がないので素早く起動します。 これが通常インストールされるEmacsの実行形式です。

emacsを作るにはコマンドtemacs -batch -l loadup dumpを使います。 ここでの-batchの目的は、 temacsが端末に関するデータを初期化しないようにするためです。 これにより、ダンプしたEmacsでは端末情報の表が空であることを保証できます。 引数dumpは、emacsという名前の新たな実行形式を ダンプするようにloadup.elに指示します。

ダンプできないオペレーティングシステムもあります。 そのようなシステムでは、Emacsを使うたびに コマンドtemacs -l loadupでEmacsを起動する必要があります。 これにはかなり時間がかかりますが、多くても1日に1回、あるいは、 ログアウトしなのであれば週に1回Emacsを起動する必要があるだけでしょうから、 余分な時間は重大問題にはならないでしょう。

あらかじめロードしておく追加のファイルは、 それらをロードするsite-load.elという名前のライブラリを 書くことで指定できます。 追加データのための領域を確保するために src/puresize.hPURESIZEの値を増やす必要があるかもしれません。 (十分な大きさになるまで20000ずつ増やして試すこと。) しかし、マシンが速くなればなるほど、あらかじめロードしておくファイルを 追加することの利点は減少します。 最近のマシンでは、このようにする必要はないでしょう。

loadup.elsite-load.elを読み終えると、 Snarf-documentation(see Accessing Documentation)を呼び出して、 基本関数やあらかじめロードした関数(および変数)の説明文字列を それらの説明文字列を格納したファイルetc/DOCから探します。

ダンプする直前に実行すべきList式を指定するには、 site-init.elという名前のライブラリにそれらのLisp式を入れておきます。 このファイルは、説明文字列を探し終えてから実行されます。

関数定義や変数定義をあらかじめロードしたいときには、 それを行ってあとでEmacsを実行したときにそれらの説明文字列を 参照できるようにする方法が3つあります。

無変更の普通のEmacsにユーザーが期待する機能を変更するようなものを site-load.elsite-init.elに入れることは勧められません。 読者のサイトでは普通の機能に優先させるべきであると思うときには、 default.elでそれを行います。 そうすれば、ユーザーは好みに応じて読者が行った変更を無効にできます。 See Start-up Summary

dump-emacs to-file from-file Function
この関数は、Emacsの現在の状態を 実行形式ファイルto-fileへダンプする。 from-file(これは普通は実行形式ファイルtemacs)から シンボルを取り出す。

すでにダンプしたEmacsでこの関数を使うときには、 -batchを指定してEmacsを実行すること。


Node:Pure Storage, Next:, Previous:Building Emacs, Up:GNU Emacs Internals

ピュアメモリ

Emacs Lispでは、ユーザーが作成したLispオブジェクト向けに 2種類のメモリ、普通メモリ(normal storage)と ピュアメモリ(pure storage)を使います。 普通メモリは、Emacsセッション中に新たに作成されるすべてのデータを置く場所です。 普通メモリに関する情報は以下の節を参照してください。 ピュアメモリは、あらかじめロードした標準Lispファイル群の特定のデータ、 つまり、Emacsの実行中にけっして変化しないデータを収めるために使います。

ピュアメモリは、temacsがあらかじめロードする標準Lispライブラリを ロードしている最中にのみ割り当てられます。 ファイルemacsでは読み出し専用 (これができるオペレーティングシステムでは)と印が付けられ、 当該マシンで同時に実行されているすべてのEmacsのジョブで メモリ領域を共有できるようにします。 ピュアメモリは拡張できません。 Emacsをコンパイルしたときに固定サイズが割り当てられ、 あらかじめロードするライブラリに対して十分な大きさがないと temacsはクラッシュします。 その場合には、ファイルsrc/puresize.hのコンパイルパラメータ PURESIZEを増やす必要があります。 あらかじめロードするライブラリを追加したり標準機能に機能を追加しなければ、 そのようなことは普通は起こらないはずです。

purecopy object Function
この関数は、ピュアメモリ内にobjectをコピーしそれを返す。 文字列のコピーでは、ピュアメモリ内に同じ文字の新たな文字列を単純に作る。 ベクトルやコンスセルの内容は再帰的にコピーする。 シンボルなどの他のオブジェクトはコピーせずに無変更でそれらを返す。 マーカをコピーしようとするとエラーを通知する。

この関数は、Emacsを構築してダンプするとき以外ではなにもしない。 普通はファイルemacs/lisp/loaddefs.elでのみ呼び出されるが、 あらかじめロードするとこれを呼び出すようなパッケージも少数だがある。

pure-bytes-used Variable
この変数の値は、割り当て済みのピュアメモリのバイト数である。 典型的には、ダンプしたEmacsでは この値は利用可能なピュアメモリの総量にとても近い。 そうでない場合には、あらかじめロードしたライブラリが少ないのであろう。

purify-flag Variable
この変数は、defunが関数定義をピュアメモリに コピーすべきかどうかを決定する。 nil以外であると、関数定義をピュアメモリにコピーする。

Emacsを構築中の初期段階ですべての基本的な関数をロード中には (これらの関数を共有してガベッジコレクションの対象にしないように)、 このフラグはtである。 実行形式としてEmacsをダンプするときには、 ダンプ前後の実際の値には関係なくこの変数にはnilを書く。

実行中のEmacsでこのフラグを変更するべきではない。


Node:Garbage Collection, Next:, Previous:Pure Storage, Up:GNU Emacs Internals

ガベッジコレクション

プログラムがリストを作成したり、(ライブラリをロードするなどして) ユーザーが新たに関数を定義すると、 それらのデータは普通メモリへ置かれます。 普通メモリが足りなくなると、Emacsはオペレーティングシステムに 1kバイトの倍数のブロックでメモリ割り当てを要求します。 各ブロックは1つの種類のLispオブジェクトに使いますから、 シンボル、コンスセル、マーカなどはメモリの異なるブロックに分離されます。 (ベクトル、長い文字列、バッファ、特定の編集向けデータ型などの 比較的大きなものは各オブジェクトごとに独立のブロックを割り当てるが、 短い文字列は8kバイトのブロックに詰め込む。)

あるメモリ部分をしばらく使ってから、 (たとえば)バッファを削除したり オブジェクトに対する最後の参照を削除するなどして 当該メモリを解放することはよくあることです。 Emacsには、このような放置されたメモリを回収する ガベッジコレクタ(garbage collector)があります。 (この名前は伝統的だが、 『ガベッジリサイクル』のほうがこの機能を直観的に表すかもしれない。)

ガベッジコレクタは、Lispプログラムから現時点で参照可能な すべてのLispオブジェクトを探して印を付けることで動作します。 まず、すべてのシンボル、それらの値、それらに関連付けられた関数定義、 および、スタック上の任意のデータは参照可能であると仮定します。 参照可能なオブジェクトから間接的に辿れる任意のオブジェクトも 参照可能です。

印付けが終ったときには、無印であるすべてのオブジェクトは ゴミ(ガベッジ)です。 Lispプログラムやユーザーがなにをしようと、 無印のオブジェクトに辿り着く方法はないのでそれらを参照することは不可能です。 無印のオブジェクトを使っているものはいないので、 それらのメモリ領域は再利用できます。 ガベッジコレクタの2段目の動作(『掃く』(sweep))は、 無印のオブジェクトのメモリ領域を再利用できるようにすることです。

掃き作業では、未使用のコンスセルを自由リスト(free list)に入れて、 将来の割り当てに備えます。 シンボルやマーカについても同様です。 参照可能な文字列は8kバイトのブロックより小さな領域を占めるように詰め込み、 不要になった8kバイトのブロックは解放します。 ベクトル、バッファ、ウィンドウ、他の大きなオブジェクトは、 mallocfreeを使って個別に割り当てたり解放します。

Common Lispに関した注意: 他のLispと異なり、GNU Emacs Lispでは、 自由リストが空になってもガベッジコレクタを呼び出さない。 そのかわりに、オペレーティングシステムにメモリ割り当てを単純に要求し、 gc-cons-thresholdバイトを使い尽くすまでは処理を継続する。

つまり、ガベッジコレクタを明示的に呼び出した直後のLispプログラムの部分では、 (プログラムのその部分で2度目にガベッジコレクタを呼び出すほど 多くのメモリを使わないと仮定すれば) その部分を実行中にはガベッジコレクタが呼ばれないことを保証できるのである。

garbage-collect コマンド
このコマンドはガベッジコレクタを実行し、 使用中のメモリ量に関する情報を返す。 (まえのガベッジコレクタの起動後に gc-cons-thresholdバイト以上のLispデータを使うと 自発的なガベッジコレクタの起動を引き起こす。)

garbage-collectが返すリストにはつぎの情報が含まれる。

((used-conses . free-conses)
 (used-syms . free-syms)
 (used-miscs . free-miscs)
 used-string-chars
 used-vector-slots
 (used-floats . free-floats)
 (used-intervals . free-intervals))

例を示す。

(garbage-collect)
     => ((106886 . 13184) (9769 . 0)
                (7731 . 4651) 347543 121628
                (31 . 94) (1273 . 168))

各要素の意味はつぎのとおりである。

used-conses
使用中のコンスセルの個数。
free-conses
オペレーティングシステムから得たメモリであるが 現在未使用なコンスセルの個数。
used-syms
使用中のシンボルの個数。
free-syms
オペレーティングシステムから得たメモリであるが 現在未使用なシンボルの個数。
used-miscs
その他の使用中のオブジェクトの個数。 マーカ、オーバレイ、ユーザーに見えないある種のオブジェクトを含む。
free-miscs
オペレーティングシステムから得たメモリであるが 現在未使用なその他のオブジェクトの個数。
used-string-chars
使用中の文字列の総文字数。
used-vector-slots
存在するベクトルの要素の総個数。
used-floats
使用中の浮動小数点数の個数。
free-floats
オペレーティングシステムから得たメモリであるが 現在未使用な浮動小数点数の個数。
used-intervals
使用中のインターバルの個数。 インターバルとはテキスト属性を表現するために使う内部データ構造である。
free-intervals
オペレーティングシステムから得たメモリであるが 現在未使用なインターバルの個数。

garbage-collection-messages User Option
この変数がnil以外であると、 Emacsはガベッジコレクションの始まりと終りにメッセージを表示する。 デフォルト値はnilであり、そのようなメッセージを表示しない。

gc-cons-threshold User Option
この変数の値は、ガベッジコレクションのあとで つぎにガベッジコレクションを起こすまでに Lispオブジェクトに割り当てるべきメモリバイト数である。 コンスセルは8バイト、 文字列は1文字1バイトと数バイトのオーバヘッドといった具合である。 バッファの内容に割り当てたメモリ量は数えない。 この閾値を越えてもただちにつぎのガベッジコレクションは起こらず、 つぎにLispのエバリュエータが呼ばれときに起きる。

最初の閾値は400,000である。 より大きな値を指定すると、ガベッジコレクションの起動回数が少なくなる。 ガベッジコレクションに費す時間を減少できるが、 全体のメモリ使用量を増加させる。 大量のLispデータを作成するようなプログラムを実行するときに設定する。

10,000までの小さな値を指定すると、 ガベッジコレクションの回数を増やせる。 10,000未満の値が意味を持つのはつぎにガベッジコレクションが起きるまでである。 garbage-collectは閾値を10,000に戻す。

garbage-collectが返す値は、データ型ごとのLispデータのメモリ使用量です。 対照的に、関数memory-limitは、 Emacsが現在使用中のメモリ総量に関する情報を与えます。

memory-limit Function
この関数は、Emacsが最後に割り当てた最終バイトのアドレスを 1024で割ったものを返す。 値を1024で割るのは、Lispの整数に収めるためである。

読者の操作がメモリ使用量にどのように影響するかを調べるのに使える。


Node:Memory Usage, Next:, Previous:Garbage Collection, Up:GNU Emacs Internals

メモリ使用量

これらの変数は、Emacsが割り当てたデータ型ごとのメモリ総量に関する 情報を与えます。 これらと(garbage-collect)が返す値との違いに注意してください。 (garbage-collect)の値は現存するオブジェクトを数えますが、 これらの変数は、すでに解放したオブジェクトを含めて 割り当てたオブジェクトの個数やサイズを数えます。

cons-cells-consed Variable
このEmacsセッションでこれまでに割り当てたコンスセルの総数。

floats-consed Variable
このEmacsセッションでこれまでに割り当てた浮動小数点数の総数。

vector-cells-consed Variable
このEmacsセッションでこれまでに割り当てたベクトルセルの総数。

symbols-consed Variable
このEmacsセッションでこれまでに割り当てたシンボルの総数。

string-chars-consed Variable
このEmacsセッションでこれまでに割り当てた文字列の総文字数。

misc-objects-consed Variable
このEmacsセッションでこれまでに割り当てたその他のオブジェクトの総数。 マーカやオーバレイ、ユーザーに見えないある種のオブジェクトを含む。

intervals-consed Variable
このEmacsセッションでこれまでに割り当てたインターバルの総数。


Node:Writing Emacs Primitives, Next:, Previous:Memory Usage, Up:GNU Emacs Internals

Emacs基本関数の書き方

Lisp基本関数は、Cで実装したLisp関数です。 Lispから呼び出すためのCの関数とのインターフェイスの詳細は、 数個のCのマクロで処理しています。 新たにCのコードを書く方法をほんとうに理解する唯一の方法は、 ソースを読むことですが、ここではその一部を説明します。

スペシャルフォームの例は、eval.cから引用したorの定義です。 (普通の関数も同じように見える。)

DEFUN ("or", For, Sor, 0, UNEVALLED, 0,
  "Eval args until one of them yields non-nil; return that value.\n\
The remaining args are not evalled at all.\n\
If all args return nil, return nil.")
  (args)
     Lisp_Object args;
{
  register Lisp_Object val;
  Lisp_Object args_left;
  struct gcpro gcpro1;

  if (NULL (args))
    return Qnil;

  args_left = args;
  GCPRO1 (args_left);

  do
    {
      val = Feval (Fcar (args_left));
      if (!NULL (val))
        break;
      args_left = Fcdr (args_left);
    }
  while (!NULL (args_left));

  UNGCPRO;
  return val;
}

マクロDEFUNの引数の詳しい説明から始めます。 その雛型はつぎのとおりです。

DEFUN (lname, fname, sname, min, max, interactive, doc)
lname
関数名として定義するLispシンボルの名前である。 上の例では、orである。
fname
この関数のCの関数としての名前である。 この関数をCのコードから呼び出すときに使う名前である。 慣習により、Lispでの名前のまえにFを付けるが、 Lispでの名前のダッシュ(-)はすべて下線に置き換える。 したがって、Cのコードからこの関数を呼び出すには、Forを呼び出す。 引数はLisp_Object型である必要があることに注意してほしい。 ファイルlisp.hでは、 Lisp_Object型の値を作成するためのさまざまなマクロや関数を宣言してある。
sname
これは、Lispでの関数を表現するsubrオブジェクト向けのデータを保持する 構造体に使うCの変数名である。 この構造体は、シンボルを作成しその定義としてsubrオブジェクトを保存する 初期化ルーティンへLispのシンボル名を運ぶ構造体である。 慣習により、この名前はつねに fnameFSに置き換えたものである。
min
関数が必要とする引数の最小の個数である。 関数orは最小0個の引数を許す。
max
関数が許す引数の最大の個数に制限があるときの引数の最大の個数である。 あるいは、評価していない引数を受け取るスペシャルフォームであることを 表すUNEVALLED、 評価済みの引数を何個でも受け取ることを表すMANY&restに等価)でもよい。 UNEVALLEDMANYもマクロである。 maxが数であるときには、 それはminより小さくなく、かつ、7より大きくないこと。
interactive
この関数の対話指定であり、 Lisp関数においてinteractiveの引数に使う文字列である。 orの場合には0(空ポインタ)であり、 orは対話的に呼び出せないことを表す。 値""は、対話的に呼び出されると この関数は引数を受け取らないことを表す。
doc
説明文字列である。 各行末に\n\と書く必要があることを除けば、 Lispで定義する関数の説明文字列のように書く。 特に、最初の行は1つの文であること。

マクロDEFUNの呼び出しのあとには、 Cの関数に必須な引数名の並びを書き、引数に対する普通のCの宣言を続けます。 引数の最大個数が固定されている関数では、 各Lisp引数向けにCの引数宣言を書き、 それらをすべてLisp_Object型にします。 Lisp関数に引数の個数に上限がないとき、 それを実装するCの関数は実際には2つの引数を受け取ります。 第1引数はLisp引数の個数であり、 第2引数はそれらの値を収めたブロックのアドレスです。 引数の型はintLisp_Object *です。

関数For自身の内側では、 マクロGCPRO1UNGCPROを使っていることに注意してください。 GCPRO1は、ガベッジコレクションから変数を『保護』するために使います。 つまり、ガベッジコレクタに対してこの変数を調べてその内容を 参照可能なオブジェクトとみなすように指示します。 FevalFevalを直接/間接的に呼び出すものを呼ぶときには、 このようにする必要があります。 そのような場面では、再度参照する意図がある任意のLispオブジェクトは 保護する必要があります。 UNGCPROは、この関数での変数の保護を取り消します。 これは明示的に行う必要があります。

ほとんどのデータ型では、少なくともそのオブジェクトへの1つのポインタを 保護すれば十分であり、そのオブジェクトに循環がない限り、 そのオブジェクトへのすべてのポインタは正しく保たれます。 文字列にはこれはあてはまりません。 ガベッジコレクタがそれらを移動するからです。 ガベッジコレクタが文字列を移動すると、 それに対する既知のポインタをすべて再配置し、 それ以外のポインタは不正になります。 したがって、ガベッジコレクタが動く可能性のある任意の部分では、 文字列へのすべてのポインタを保護する必要があります。

マクロGCPRO1は1つのローカル変数のみを保護します。 2つ保護したい場合にはかわりにGCPRO2を使います。 GCPRO1を繰り返しても働きません。 GCPRO3GCPRO4のマクロもあります。

これらのマクロはgcpro1などのローカル変数を暗黙のうちに使いますが、 読者はこれらを型struct gcproで明示的に宣言する必要があります。 したがって、GCPRO2を使う場合には、 gcpro1gcpro2を宣言する必要があります。 残念ですが、ここではすべての詳細は説明しきれません。

Emacsをいったんダンプしたあとでも静的やグローバルな変数に書き込むのであれば、 それらの変数にはCの初期化構文を使ってはいけません。 初期化構文を伴うそれらの変数は、Emacsをダンプすると (オペレーティングシステムによっては)その結果として 読み出し専用のメモリ領域に割り当てられます。 See Pure Storage

関数の内側では静的変数を使わずに、 すべての静的変数はファイルのトップレベルに置きます。 オペレーティングシステムによっては Emacsはキーワードstaticを空のマクロと定義することもあるので、 これは必要なことなのです。 (このような定義を使うのは、そのようなシステムは、 初期化構文があろうとなかろうと静的と宣言した変数を ダンプ後には読み出し専用にしてしまうからである。)

Cの関数を定義しただけではLisp基本関数としては使えません。 基本関数に対するLispシンボルを作成し、 その関数セルに適切なsubrオブジェクトを保存する必要があります。 そのコードはつぎのようになります。

defsubr (&subr-structure-name);

ここで、subr-structure-nameDEFUNの第3引数に使った名前です。

すでにLisp基本関数が定義されているファイルに新たな基本関数を追加するときには、 (ファイルの末尾近くで)syms_of_somethingという名前の関数を探し、 それにdefsubrの呼び出しを追加します。 ファイルにこの関数がなかったり、新たなファイルを作成した場合には、 syms_of_filename(たとえばsyms_of_myfile)を追加します。 そして、ファイルemacs.cでこれらの関数を呼び出している箇所を探して、 そこにsyms_of_filenameの呼び出しを追加します。

関数syms_of_filenameは、 Lisp変数として見える任意のCの変数を定義する場所でもあります。 DEFVAR_LISPは、Lispから見えるLisp_Object型のCの変数を作ります。 DEFVAR_INTは、Lispからはつねに整数を値として見える int型のCの変数を作ります。 DEFVAR_BOOLは、Lispからはtnilを値として見える int型のCの変数を作ります。

ファイルだけに有効なLisp_Object型のCの変数を定義した場合には、 つぎのようにして、syms_of_filenameの中でstaticproを 呼び出してその変数をガベッジコレクションから保護する必要があります。

staticpro (&variable);

つぎは、少々複雑な引数を取る別の関数の例です。 これはwindow.cから取ったもので、 マクロとLispオブジェクトを操作する関数の使い方を例示します。

DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
  Scoordinates_in_window_p, 2, 2,
  "xSpecify coordinate pair: \nXExpression which evals to window: ",
  "Return non-nil if COORDINATES is in WINDOW.\n\
COORDINATES is a cons of the form (X . Y), X and Y being distances\n\
...
If they are on the border between WINDOW and its right sibling,\n\
   `vertical-line' is returned.")
  (coordinates, window)
     register Lisp_Object coordinates, window;
{
  int x, y;

  CHECK_LIVE_WINDOW (window, 0);
  CHECK_CONS (coordinates, 1);
  x = XINT (Fcar (coordinates));
  y = XINT (Fcdr (coordinates));

  switch (coordinates_in_window (XWINDOW (window), &x, &y))
    {
    case 0:			/* NOT in window at all. */
      return Qnil;

    case 1:			/* In text part of window. */
      return Fcons (make_number (x), make_number (y));

    case 2:			/* In mode line of window. */
      return Qmode_line;

    case 3:			/* On right border of window.  */
      return Qvertical_line;

    default:
      abort ();
    }
}

Cのコードでは、関数がCで定義されていない限り、 関数をその名前で呼び出せないことに注意してください。 Lispで書かれた関数を呼び出す方法は、Lispの関数funcallを 内蔵するFfuncallを使うことです。 Lisp関数funcallは任意個数の引数を受け付けるので、 Cでは2つの引数、Lispレベルの引数の個数と それらの値を収めた一次元の配列を受け取ります。 Lispレベルの最初の引数は呼び出すべきLisp関数であり、 残りはそれに渡す引数です。 Ffuncallはエバリュエータを呼び出すので、 Ffuncallを呼び出す周りでは、 ガベッジコレクションからポインタを保護する必要があります。

Cの関数、call0call1call2などは、 固定個数の引数を受け取るLisp関数を簡便に呼び出す手軽な方法です。 これらはFfuncallを呼び出して動作します。

eval.cは例を調べるにはとてもよいファイルです。 lisp.hには重要なマクロや関数の定義が入っています。


Node:Object Internals, Previous:Writing Emacs Primitives, Up:GNU Emacs Internals

オブジェクトの内部

GNU Emacs Lispは、さまざまな型のデータを扱います。 実際のデータはヒープに保存されていて、 プログラムはポインタを介してそれらを参照します。 ほとんどの実装では、ポインタは32ビット長です。 Emacsをコンパイルしたオペレーティングシステムやマシンの種類に依存しますが、 オブジェクトのアドレスには28ビットを使い、 残りのビットはガベッジコレクションの印や オブジェクトの型を表す識別子であるタグに使います。

Lispオブジェクトはタグ付ポインタとして表現しますから、 任意のオブジェクトのLispデータ型を判定することが可能です。 CのデータLisp_Objectは、任意のデータ型のLispオブジェクトを保持できます。 普通の変数はLisp_Object型ですから、 Lispの任意の値の任意の型を保持できます。 実際のデータ型は、実行中にのみ判定できます。 関数引数についても同じことがいえます。 特定の型の引数のみを受け付る関数が必要な場合には、 適切な述語(see Type Predicates) を使って型を明示的に検査する必要があります。


Node:Buffer Internals, Next:, Up:Object Internals

バッファの内部

バッファには、Lispプログラマが直接には参照できないフィールドがあります。 それらをCのコードで使っている名前で以下に述べます。 多くはLisp基本関数を介してLispプログラムから間接的に参照できます。

name
バッファ名はバッファを指名する文字列である。 これは一意であることが保証される。 see Buffer Names
save_modified
このフィールドは、バッファが最後に保存された時刻を整数で保持する。 see Buffer Modification
modtime
このフィールドは、訪問しているファイルの更新時刻を保持している。 これはファイルを読み書きしたときに設定される。 バッファをファイルに書き込むたびに、 このフィールドとファイルの更新時刻を比較する。 see Buffer Modification
auto_save_modified
このフィールドは、バッファを最後に自動保存した時刻を保持する。
last_window_start
このフィールドは、バッファをウィンドウに最後に表示したときの バッファのwindow-start(表示開始)位置を保持する。
undo_list
このフィールドは、バッファのアンドゥリストを保持する。 see Undo
syntax_table_v
このフィールドは、バッファの構文テーブルを保持する。 see Syntax Tables
downcase_table
このフィールドは、テキストを小文字に変換するための変換表を保持する。 see Case Tables
upcase_table
このフィールドは、テキストを大文字に変換するための変換表を保持する。 see Case Tables
case_canon_table
このフィールドは、大文字小文字を区別しない探索のために テキストを正則にするための変換表を保持する。 see Case Tables
case_eqv_table
このフィールドは、大文字小文字を区別しない探索のための 同値テーブルを保持する。 see Case Tables
display_table
このフィールドは、バッファの表示テーブルを保持する。 表示テーブルがなければnilである。 see Display Tables
markers
このフィールドは、バッファを現在指しているすべてのマーカの連鎖を 保持している。 バッファからテキストを削除したり、バッファのギャップが移動すると、 これらのマーカのおのおのを検査し更新する必要がある。 see Markers
backed_up
このフィールドは、このバッファで訪問しているファイルの バックアップファイルを作成したかどうかを表すフラグである。
mark
このフィールドは、バッファのマークを保持する。 マークはマーカであり、そのためリストmarkersにも含まれている。 see The Mark
mark_active
バッファのマークが活性であれば、 このフィールドはnil以外である。
local_var_alist
このフィールドは、このバッファにバッファローカルな変数を記述した 連想リストを保持している。 バッファオブジェクトに特別な場所がある組み込みのバッファローカルな変数は 含まない。 (それらはこの一覧では省いた。) see Buffer-Local Variables
base_buffer
このフィールドは、(間接バッファであれば)バッファの基底バッファ、あるいは、 nilを保持する。
keymap
このフィールドは、バッファのローカルキーマップを保持する。 see Keymaps
overlay_center
このフィールドは、現在のオーバレイの中央位置を保持する。 see Overlays
overlays_before
このフィールドは、バッファの現在のオーバレイの中央位置か それよりまえで終るこのバッファのオーバレイのリストを保持している。 それらは終了位置が減る順に並んでいる。
overlays_after
このフィールドは、バッファの現在のオーバレイの中央位置より うしろで終るこのバッファのオーバレイのリストを保持している。 それらは開始位置が増える順に並んでいる。
enable_multibyte_characters
このフィールドは、enable-multibyte-charactersの バッファローカルな値を保持しており、 tnilである。


Node:Window Internals, Next:, Previous:Buffer Internals, Up:Object Internals

ウィンドウの内部

ウィンドウには以下のような参照可能なフィールドがあります。

frame
このウィンドウがあるフレーム。
mini_p
このウィンドウがミニバッファ用ウィンドウであればnil以外。
buffer
このウィンドウで表示しているバッファ。 これはウィンドウの生存期間中にしばしば変化する。
dedicated
このウィンドウがそのバッファ専用であるとnil以外である。
pointm
これは、このウィンドウが選択されていたときの カレントバッファのポイント値である。 選択されていないときには、まえの値が保持される。
start
ウィンドウに表示する最初の文字のバッファ内位置である。
force_start
このフラグがnil以外であると、 Lispプログラムが明示的にウィンドウをスクロールしたことを表す。 ポイントがスクリーンからはみ出しているとつぎの再表示の動作に影響する。 ポイントの周りのテキストをウィンドウに表示するようにスクロールするかわりに、 スクリーン上に位置するようにポイントを移動する。
last_modified
このウィンドウの最後の再表示が完了した時点での ウィンドウのバッファのフィールドmodifiedである。
last_point
このウィンドウの最後の再表示が完了した時点での バッファのポイント値である。
left
コラム数で数えたウィンドウの左端である。 (スクリーンの最左端コラムは0コラム目。)
top
行数で数えたウィンドウの上端である。 (スクリーンの最上端行は0行目。)
height
行数で数えたウィンドウの高さ。
width
コラム数で数えたウィンドウの幅。
next
これは、兄弟関係でつぎのウィンドウである。 兄弟関係で最右端か最下端であるウィンドウではnilである。
prev
これは、兄弟関係でまえのウィンドウである。 兄弟関係で最左端か最上端であるウィンドウではnilである。
parent
内部的にはEmacsはウィンドウを木に並べている。 兄弟関係の各グループには親ウィンドウがあり、 親ウィンドウの領域はその兄弟すべての領域を含む。 このフィールドはウィンドウの親を指す。

親ウィンドウはバッファを表示せず、 その子ウィンドウの形以外には、表示に関してはなんの役割も持たない。 Emacs Lispプログラムでは親ウィンドウを参照せず、 バッファを実際に表示する木の葉にあるウィンドウを操作する。

hscroll
これは、ウィンドウの表示を水平方向左向きにスクロールしているコラム数。 これは普通は0である。
use_time
これは、このウィンドウが選択されていた最後の時刻。 関数get-lru-windowがこのフィールドを使う。
display_table
ウィンドウの表示テーブル。 指定されていなければnilである。
update_mode_line
nil以外であると、ウィンドウのモード行を更新する必要があることを表す。
base_line_number
バッファの特定の位置の行番号である。 あるいはnil。 これは、モード行にポイント位置の行番号を表示するために使われる。
base_line_pos
行番号が既知のバッファ内位置。 既知でなければnilである。
region_showing
このウィンドウでリージョン(やその一部)を強調表示しているときには、 このフィールドは、当該リージョンの一方の端を表すマーク位置を保持している。 さもなければこのフィールドはnilである。


Node:Process Internals, Previous:Window Internals, Up:Object Internals

プロセスの内部

プロセスにはつぎのようなフィールドがあります。

name
プロセスの名前である文字列。
command
このプロセスを開始するために使用されたコマンド引数から成るリスト。
filter
バッファのかわりにプロセスからの出力を受け取るために使用する関数。 あるいはnil
sentinel
プロセスがシグナルを受け取るたびに呼ばれる関数。 あるいはnil
buffer
プロセスに対応付けられたバッファ。
pid
UNIXのプロセスIDである整数。
childp
フラグであり、これが実際に子プロセスであるとnil以外である。 ネットワーク接続であるとnil以外。
mark
プロセスからの最後の出力をバッファに挿入した箇所の末尾位置を表すマーカ。 これはしばしばバッファの末尾であるが、つねにではない。
kill_without_query
これがnil以外であると、このプロセスが動作中にEmacsを終了しようとしても プロセスをキルすることに関して確認を求めない。
raw_status_low
raw_status_high
これらの2つのフィールドは、 システムコールwaitで返されるプロセス状態の各16ビットを記録する。
status
process-statusが返すべきプロセス状態。
tick
update_tick
この2つのフィールドが等しくないと、 番兵を実行するかプロセスのバッファにメッセージを挿入するかして、 プロセスの状態変化を報告する必要がある。
pty_flag
サブプロセスとの通信にPTY(疑似端末)を 使用している場合にはnil以外であり、 パイプを使用している場合にはnilである。
infd
このプロセスからの入力用ファイル記述子。
outfd
このプロセスへの出力用ファイル記述子。
subtty
サブプロセスが使用している端末のファイル記述子。 (これを記録する必要のないシステムもあり、その場合には値はnilである。)
tty_name
サブプロセスが使用している端末の名前。 パイプを使用しているときにはnilである。


Node:Standard Errors, Next:, Previous:GNU Emacs Internals, Up:Top

標準のエラー

以下は、概念ごとにまとめた標準Emacsのエラーシンボルの完全な一覧です。 一覧には、各シンボルの(シンボルの属性error-messageにある)メッセージと そのようなエラーが生起する場面の記述への相互参照を示しました。

各エラーシンボルには、属性error-conditionsがあり、 これはシンボルのリストです。 通常、このリストは、エラーシンボルそのものとシンボルerrorを含みます。 しばしば、追加のシンボルも含みます。 それらは中間的な分類種別であり、errorより細分化したものですが、 エラーシンボルそのものよりは大分類です。 たとえば、ファイル参照に関するすべてのエラーには、 条件file-errorが入っています。 以下で、特定のエラーシンボルにおいて追加のシンボルを言及していないときには、 そのエラーには追加シンボルがないことを意味します。

特別な例外ですが、エラーシンボルquitには 条件errorがありません。 これは、中断(quit)をエラーとみなさないからです。

エラーが生起する場面とその処理方法については、See Errors

シンボル
文字列; 参照
error
"error"
see Errors
quit
"Quit"
see Quitting
args-out-of-range
"Args out of range"
see Sequences Arrays Vectors
arith-error
"Arithmetic error"
Numbers/%を参照。
beginning-of-buffer
"Beginning of buffer"
see Motion
buffer-read-only
"Buffer is read-only"
see Read Only Buffers
cyclic-function-indirection
"Symbol's chain of function indirections\
contains a loop"

see Function Indirection
end-of-buffer
"End of buffer"
see Motion
end-of-file
"End of file during parsing"
これはファイル入出力ではなくLispリーダに関連することなので、 file-errorではないことに注意。
see Input Functions
file-already-exists
これはfile-error
see Writing to Files
file-date-error
これはfile-errorの小分類。 copy-fileで、 出力ファイルの最終更新日付の設定に失敗すると生起する。
see Changing Files
file-error
このエラーとその小分類にはエラー文字列がない。 エラー条件file-errorがあると、 データ項目のみからエラーメッセージを作るからである。
see Files
file-locked
これはfile-error
see File Locks
file-supersession
これはfile-error
see Modification Time
invalid-function
"Invalid function"
see Classifying Lists
invalid-read-syntax
"Invalid read syntax"
see Input Functions
invalid-regexp
"Invalid regexp"
see Regular Expressions
mark-inactive
"Mark inactive"
see The Mark
no-catch
"No catch for tag"
see Catch and Throw
scan-error
"Scan error"
これは、構文解析関数が不正な構文や対応していない括弧を みつけると生起する。
List Motion、および、see Parsing Expressions
search-failed
"Search failed"
see Searching and Matching
setting-constant
"Attempt to set a constant symbol"
シンボルnilt、および、 :で始まる任意のシンボルは変更できない。
see Variables that Never Change
undefined-color
"Undefined color"
see Color Names
void-function
"Symbol's function definition is void"
see Function Cells
void-variable
"Symbol's value as variable is void"
see Accessing Variables
wrong-number-of-arguments
"Wrong number of arguments"
see Classifying Lists
wrong-type-argument
"Wrong type argument"
see Type Predicates

arith-errorの特別な場合に分類された以下の種類のエラーは、 数学関数を不正に使ったときに特定のシステムで生起します。

domain-error
"Arithmetic domain error"
see Math Functions
overflow-error
"Arithmetic overflow error"
see Math Functions
range-error
"Arithmetic range error"
see Math Functions
singularity-error
"Arithmetic singularity error"
see Math Functions
underflow-error
"Arithmetic underflow error"
see Math Functions


Node:Standard Buffer-Local Variables, Next:, Previous:Standard Errors, Up:Top

バッファローカルな変数

以下は、各バッファにおいて、自動的にバッファローカルになる Emacsの汎用目的の変数一覧です。 ほとんどのものは、設定したときにだけバッファローカルになります。 これらのごく少数は、各バッファでつねにローカルになります。 多くのLispパッケージで内部使用向けにこのような変数を定義しますが、 それらすべてをここに示すことはしていません。

abbrev-mode
see Abbrevs
auto-fill-function
see Auto Filling
buffer-auto-save-file-name
see Auto-Saving
buffer-backed-up
see Backup Files
buffer-display-count
see Displaying Buffers
buffer-display-table
see Display Tables
buffer-file-format
see Format Conversion
buffer-file-name
see Buffer File Name
buffer-file-number
see Buffer File Name
buffer-file-truename
see Buffer File Name
buffer-file-type
see MS-DOS File Types
buffer-invisibility-spec
see Invisible Text
buffer-offer-save
see Saving Buffers
buffer-read-only
see Read Only Buffers
buffer-saved-size
see Point
buffer-undo-list
see Undo
cache-long-line-scans
see Text Lines
case-fold-search
see Searching and Case
ctl-arrow
see Usual Display
comment-column
see Comments
default-directory
see System Environment
defun-prompt-regexp
see List Motion
enable-multibyte-characters
see Non-ASCII Characters
fill-column
see Auto Filling
goal-column
see Moving Point
left-margin
see Indentation
local-abbrev-table
see Abbrevs
local-write-file-hooks
see Saving Buffers
major-mode
see Mode Help
mark-active
see The Mark
mark-ring
see The Mark
minor-modes
see Minor Modes
mode-line-buffer-identification
see Mode Line Variables
mode-line-format
see Mode Line Data
mode-line-modified
see Mode Line Variables
mode-line-process
see Mode Line Variables
mode-name
see Mode Line Variables
overwrite-mode
see Insertion
paragraph-separate
see Standard Regexps
paragraph-start
see Standard Regexps
point-before-scroll
マウスコマンドとスクロールコマンドの通信に使う。
require-final-newline
see Insertion
selective-display
see Selective Display
selective-display-ellipses
see Selective Display
tab-width
see Usual Display
truncate-lines
see Truncation
vc-mode
see Mode Line Variables


Node:Standard Keymaps, Next:, Previous:Standard Buffer-Local Variables, Up:Top

標準のキーマップ

以下のシンボルは、さまざまなキーマップの名前として使われています。 これらの一部はEmacsの始動時に存在しますが、 他のものは関連するモードを使ったときにのみロードされます。 以下は、完全な一覧ではありません。

これらのマップのほとんどすべては、ローカルマップとして使われます。 もちろん、存在するモードの中で、グローバルキーマップを変更するのは Vipモードと端末(terminal)モードだけです。

Buffer-menu-mode-map
バッファメニュー(buffer-menu)モードで使う完全なキーマップ。
c-mode-map
Cモードで使う疎なキーマップ。
command-history-map
コマンド履歴(command-history)モードで使う完全なキーマップ。
ctl-x-4-map
プレフィックスC-x 4の下位コマンド用の疎なキーマップ。
ctl-x-5-map
プレフィックスC-x 5の下位コマンド用の疎なキーマップ。
ctl-x-map
C-xコマンド用の完全なキーマップ。
debugger-mode-map
デバッガモードで使う完全なキーマップ。
dired-mode-map
dired-modeバッファで使う完全なキーマップ。
edit-abbrevs-map
edit-abbrevsで使う疎なキーマップ。
edit-tab-stops-map
edit-tab-stopsで使う疎なキーマップ。
electric-buffer-menu-mode-map
エレクトリックバッファメニュー(electric-buffer-menu)モードで 使う完全なキーマップ。
electric-history-map
エレクトリックコマンド履歴(electric-command-history)モードで 使う完全なキーマップ。
emacs-lisp-mode-map
emacs-lispモードで使う疎なキーマップ。
facemenu-menu
テキスト属性メニューを表示するキーマップ。
facemenu-background-menu
テキスト属性メニューのBackground Colorサブメニューを表示するキーマップ。
facemenu-face-menu
テキスト属性メニューのFaceサブメニューを表示するキーマップ。
facemenu-foreground-menu
テキスト属性メニューのForeground Colorを表示するキーマップ。
facemenu-indentation-menu
テキスト属性メニューのIndentaionサブメニューを表示するキーマップ。
facemenu-justification-menu
テキスト属性メニューのJustificationサブメニューを表示するキーマップ。
facemenu-special-menu
テキスト属性メニューのSpecial Propsサブメニューを 表示するキーマップ。
function-key-map
キーパッドやファンクションキーの変換用のキーマップ。
それらがなければ、この変数は空の疎なキーマップである。 see Translating Input
fundamental-mode-map
基本(fundamental)モード用のローカルキーマップ。
これは空であり、変更すべきでない。
Helper-help-map
ヘルプユーティリティパッケージが使う完全なキーマップ。
この変数の値セルと関数セルには同一のキーマップが入っている。
Info-edit-map
infoのeコマンドで使う疎なキーマップ。
Info-mode-map
infoコマンドを収めた疎なキーマップ。
isearch-mode-map
インクリメンタルサーチ中に打鍵できる文字を定義するキーマップ。
key-translation-map
キー変換用のキーマップ。 これは、function-key-mapと違って、 もとのキーバインディングに優先する。 see Translating Input
lisp-interaction-mode-map
Lispモードで使う疎なキーマップ。
lisp-mode-map
Lispモードで使う疎なキーマップ。
menu-bar-edit-menu
メニューバーのEditメニューを表示するキーマップ。
menu-bar-files-menu
メニューバーのFilesメニューを表示するキーマップ。
menu-bar-help-menu
メニューバーのHelpメニューを表示するキーマップ。
menu-bar-mule-menu
メニューバーのMuleメニューを表示するキーマップ。
menu-bar-search-menu
メニューバーのSearchメニューを表示するキーマップ。
menu-bar-tools-menu
メニューバーのToolsメニューを表示するキーマップ。
mode-specific-map
C-cに続く文字用のキーマップ。 これはグローバルマップの中にあることに注意。 このマップは実際にはモード固有ではない。 プレフィックスキーC-cの主要な使い方を記述する C-h bdisplay-bindings)において、 ユーザーに有益なようにこの名前を選んだ。
occur-mode-map
出現(occur)モードで使うローカルキーマップ。
query-replace-map
query-replaceやその関連コマンドの応答用に使うキーマップ。 y-or-n-pmap-y-or-n-pもこれを使う。 このマップを使う関数は、プレフィックスキーを使わない。 一度に1つのイベントを探す。
text-mode-map
テキスト(text)モードで使う疎なキーマップ。
view-mode-map
閲覧(view)モードで使う完全なキーマップ。


Node:Standard Hooks, Next:, Previous:Standard Keymaps, Up:Top

標準のフック

以下は、Emacsから適切な場面に呼び出される関数を 読者が指定するためのフック変数の一覧です。

これらのほとんどの変数の名前は-hookで終ります。 これらは、run-hooksで実行される ノーマルフック(normal hooks)です。 そのようなフックの値は関数のリストです。 関数は引数なしで呼び出され、その値は完全に無視します。 このようなフックに新たな関数を追加する推奨方法は、 add-hookを呼び出すことです。 フックの使い方について詳しくは、See Hooks

-hooks-functionsで終る名前の変数は、 普通、アブノーマルフック(abnormal hooks)です。 それらの値も関数のリストですが、 それらの関数は特別な方法(引数を渡したり、戻り値を使用したり)で 呼び出されます。 これらの変数のごく少数は実際にはノーマルフックですが、 ノーマルフックの名前を-hookで終えるという慣行を 確立するまえに命名したものです。

-functionで終る名前の変数では、その値は1つの関数です。 (Emacsの旧版では、ノーマルフックでないにも関わらず、 -hookで終る名前の変数があった。 しかしながら、それらはすべて改名した。)

activate-mark-hook
after-change-function
after-change-functions
after-init-hook
after-insert-file-functions
after-make-frame-hook
after-revert-hook
after-save-hook
auto-fill-function
auto-save-hook
before-change-function
before-change-functions
before-init-hook
before-make-frame-hook
before-revert-hook
blink-paren-function
buffer-access-fontify-functions
c-mode-hook
calendar-load-hook
change-major-mode-hook
command-history-hook
command-line-functions
comment-indent-function
deactivate-mark-hook
diary-display-hook
diary-hook
dired-mode-hook
disabled-command-hook
echo-area-clear-hook
edit-picture-hook
electric-buffer-menu-mode-hook
electric-command-history-hook
electric-help-mode-hook
emacs-lisp-mode-hook
find-file-hooks
find-file-not-found-hooks
first-change-hook
fortran-comment-hook
fortran-mode-hook
ftp-setup-write-file-hooks
ftp-write-file-hook
indent-mim-hook
initial-calendar-window-hook
kill-buffer-hook
kill-buffer-query-functions
kill-emacs-hook
kill-emacs-query-functions
LaTeX-mode-hook
ledit-mode-hook
lisp-indent-function
lisp-interaction-mode-hook
lisp-mode-hook
list-diary-entries-hook
local-write-file-hooks
m2-mode-hook
mail-mode-hook
mail-setup-hook
mark-diary-entries-hook
medit-mode-hook
menu-bar-update-hook
minibuffer-setup-hook
minibuffer-exit-hook
news-mode-hook
news-reply-mode-hook
news-setup-hook
nongregorian-diary-listing-hook
nongregorian-diary-marking-hook
nroff-mode-hook
outline-mode-hook
plain-TeX-mode-hook
post-command-hook
pre-abbrev-expand-hook
pre-command-hook
print-diary-entries-hook
prolog-mode-hook
protect-innocence-hook
redisplay-end-trigger-functions
rmail-edit-mode-hook
rmail-mode-hook
rmail-summary-mode-hook
scheme-indent-hook
scheme-mode-hook
scribe-mode-hook
shell-mode-hook
shell-set-directory-error-hook
suspend-hook
suspend-resume-hook
temp-buffer-show-function
term-setup-hook
terminal-mode-hook
terminal-mode-break-hook
TeX-mode-hook
text-mode-hook
today-visible-calendar-hook
today-invisible-calendar-hook
vi-mode-hook
view-hook
window-configuration-change-hook
window-scroll-functions
window-setup-hook
window-size-change-functions
write-contents-hooks
write-file-hooks
write-region-annotate-functions


Node:Index, Next:, Previous:Standard Hooks, Up:Top

索引


Node:New Symbols, Previous:Index, Up:Top

旧版以降の新しいシンボル

Table of Contents


Footnotes

  1. 【注意】 現在、このバージョン2の発行者(FSF)住所は、正式に新しい住所の
     59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
    に変わっている。

  2. 【注意】現在、このバージョン2の発行者(FSF)住所は、 正式に新しい住所の 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA に変わっている。

  3. 【訳注】日本語訳: 『Emacs Lispプログラミング入門』、アスキー出版局、ISBN 4-7561-1805-4

  4. 【訳注】日本語訳: 『GNU Emacsマニュアル』、アスキー出版局、ISBN 4-7561-3002-X

  5. 【訳注】ベクトルのみの誤り?

  6. この『キー』の使い方は、『キー列』とは無関係。 キーとは、表の項目を探すために使う値を意味する。 ここでは、表は連想リストであり、項目は連想リストの連想値である。

  7. 『環境』のこの定義は、プログラムの結果に影響する すべてのデータを含むことは意図していない。

  8. 「ボタン押し下げ」は、「ドラッグ」の対句。

  9. rightは垂直の区切り行やスクロールバーを含むが、 (window-width)はそれらを含まないため、 完全に等しくはない。

  10. 【訳注】シェルのもとで動いているプロセス群

  11. 【訳注】協定世界時。旧グリニッジ標準時に相当。

  12. 【訳注】fortnightは2週間のこと。

  13. omer: 過ぎ越しの祝い(Passover)の二日目から七週の祭(Shabuoth)の前日 までの49日間