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

20. プログラムの編集

Emacsには, LispやCといったプログラム言語の構文を 理解するように設計されたコマンドが数多くあります. 以下のことを行えます.

単語/文/段落を扱うコマンドは, 自然言語のテキストを編集するのが本来の目的ですが, コードを編集する場合にもおおいに役立ちます. なぜなら, たいていのシンボルは単語ですし(see section 単語), 文は文字列やコメントの中にも含まれるからです(see section ). 段落は本質的にはコードの中には存在しませんが, プログラム言語向けのメジャーモードでは, 段落は空行で始まり空行で終わると定義するので, 段落コマンドも役立ちます(see section 段落). 空行をうまく使ってプログラムが整然と見えるようにすると, 段落コマンドもうまく働きます.

選択的表示機能は, 関数の全体構成を眺めるのに便利です (see section 選択的な表示). この機能は, 指定幅以内の字下げ幅の行だけを表示します.


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

20.1 プログラム言語向けメジャーモード

Emacsには, Lisp, Scheme(Lispの方言の1つ), Awk, C, C++, Fortran, Icon, Java, Objective-C, Pascal, Perl, Pike, CORBA IDL, Tclといった各種プログラム言語向けのメジャーモードがあります. makefile用のメジャーモード, makefileモードもあります. Perl向けの別のモードとして, cperlモードもあります.

理想的には, Emacsで編集する可能性のあるすべてのプログラム言語に対して, それぞれのメジャーモードを実装すべきです. しかし, ある言語向けのモードが, 構文的に類似した他の言語にも 使えることがよくあります. 既存の言語モード群は, 誰かがわざわざ書こうと決心したものです.

Lispモードにはいくつか変種がありますが, Lispを実行する際のインターフェイス方法が異なります. See section Lisp式の実行.

各プログラム言語向けメジャーモードでは, その言語の慣用的な字下げ方法を理解し 現在行をそのように字下げする関数を実行するように <TAB>キーを定義します. たとえば, Cモードでは, <TAB>はc-indent-lineにバインドされています. また, C-jは, <RET>に続けて<TAB>を実行するように 定義されています. つまり, モードに固有の字下げも行います.

多くのプログラム言語では, 行ごとに字下げ量が異なります. そのため, そのような言語向けのメジャーモードでは, (コマンドbackward-delete-char-untabifyを使って) タブ文字を等価な個数の空白と同じに扱うように<DEL>を再定義しています. その結果, 字下げが空白かタブのどちらで構成されているのか気にせずに, 1度に1桁ずつ消去することが可能となります. そのようなモードでは, ポイントの直前にあるタブ文字を削除するには C-b C-dを使います.

プログラム言語向けモードでは, 段落は空行で分割されると定義するので, 段落コマンドも便利に使えます. プログラム言語向けメジャーモードで 自動詰め込み(auto-fill)モードがオンのときには, 新たに行を作ると自動的に字下げも行われます.

メジャーモードに入ると, モードフック(mode hook)と 呼ばれるノーマルフックが実行されます. モードフックは, Lisp変数の値です. 各メジャーモードにはモードフックがあり, フック名はつねにモードに入るためのコマンド名に‘-hook’を付加したものです. たとえば, Cモードに入るとフックc-mode-hookが実行され, Lispモードではフックlisp-mode-hookが実行されます. See section フック.


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

20.2 リストとS式

慣習として, 釣り合った式を扱うEmacsのキーは, 普通, コントロール・メタ文字です. これらは, コントロールやメタだけの対応したキーの機能に似せてあります. これらは, プログラム言語の式だけに関係したコマンドだと考えられがちですが, ある種の括弧が存在する(自然言語も含めた)任意の言語に対しても有益なものです.

これらのコマンドは, 2つのグループに分けられます. 一方は(括弧でまとめた)リスト(list)(31)だけを扱うもので, 丸括弧, 角括弧, 中括弧(使用言語において対応が取れている必要がある括弧)と, それらをクォートするエスケープ文字だけに注目するコマンド群です.

もう一方は, 式あるいはS式(sexp)を扱うコマンド群です. 「sexp」という用語は, Lispの式を意味する古くからの用語s-expressionに由来します. Emacsでは「S式」の概念をLispに限定しません. プログラムを記述した言語が何であっても, その式をS式と呼びます. 各プログラム言語には独自のメジャーモードがあり, そこでは, その言語の式をS式とみなすように構文テーブルを調整してあります.

一般にS式には, 丸括弧, 角括弧, 中括弧に囲まれた部分だけでなく, シンボル, 数値, 文字列定数も含まれます.

Cのように前置演算子と中置演算子を使う言語では, すべての式をS式として扱うことは不可能です. たとえば, Cモードでは, ‘foo + bar’はCの式ですが, S式としては認識しません. かわりに, ‘foo’と‘bar’をそれぞれ1つのS式として認識し, ‘+’はあいだにある句読点として認識します. これは根本的に曖昧なのです. たとえば, ポイントが‘f’にあるとき, 横断すべきS式としては, ‘foo + bar’でも‘foo’でも正当な選択肢です. ‘(foo + bar)’は, Cモードにおいて単一のS式であることに注意してください.

式の構文が曖昧なために, Emacsが正しく解釈できるようにしようなどとは誰も思わない言語もあります.


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

20.3 リストとS式に対するコマンド

C-M-f

S式を横断して前向きに移動する(forward-sexp).

C-M-b

S式を横断して後向きに移動する(backward-sexp).

C-M-k

前向きにS式をキルする(kill-sexp).

C-M-<DEL>

後向きにS式をキルする(backward-kill-sexp).

C-M-u

リスト構造を1レベル上がって後向きに移動する(backward-up-list).

C-M-d

リスト構造を1レベル下がって前向きに移動する(down-list).

C-M-n

リストを横断して前向きに移動する(forward-list).

C-M-p

リストを横断して後向きに移動する(backward-list).

C-M-t

式を入れ替える(transpose-sexps).

C-M-@

つぎの式の直後にマークを設定する(mark-sexp).

S式を横断して前向きに移動するには, C-M-fforward-sexp)を使います. ポイントに続く最初の意味ある文字が開き区切り (Lisp では‘(’, Cでは‘(’や‘[’や‘{’)であれば, 対応する閉じ区切りのうしろに移動します. シンボル, 文字列, 数値を始める文字の場合には, それらを横断してその末尾に移動します.

コマンドC-M-bbackward-sexp)は, S式を横断して後向きに移動します. 移動の詳しい規則は上記のC-M-fと同様ですが, 方向は逆です. S式のまえに接頭辞文字(Lispではシングルクォート, バッククォート, コンマ)が ある場合には, それらも横断します. ほとんどのモードでは, S式コマンドはコメントを空白であるかのように 飛び越えます.

C-M-fC-M-bに引数を指定すると, 指定された回数だけ動作を繰り返します. 負の引数では, 逆向きに移動します.

1つのS式全体をキルするには, C-M-kkill-sexp)や C-M-<DEL>backward-kill-sexp)で行います. C-M-kC-M-fで横断するだけの文字をキルし, C-M-<DEL>C-M-bで横断するだけの文字をキルします.

S式コマンドと同様に, リストコマンドはリストを横断しますが, リスト以外のS式(シンボルや文字列など)は飛び越します. これらのコマンドは, C-M-nforward-list)と C-M-pbackward-list)です. これらのコマンドが便利である主な理由は, (コメントにはリストが何も含まれないのが普通なので) コメントを無視するからです.

C-M-nC-M-pは, 可能な限り同じレベルの括弧にとどまります. 1つ(あるいはnだけ)上のレベルに移動するには, C-M-ubackward-up-list)を使います. C-M-uは, 対応の取れていない開き区切りのまえへ後向きに移動して, 1つレベルを上げます. 正の引数は反復回数になります. 負の引数は, 移動を逆向きにしますが, やはり反復回数です. つまり, 前向きに移動して, 1つ以上レベルを上げます.

リスト構造中でのレベルに移動するには, C-M-ddown-list)を使います. Lispモードでは, ‘(’が唯一の開き区切りなので, このコマンドは‘(’を探索するのとほとんど同じです. 引数は下がるべき括弧のレベルを指定します.

本当は役に立つのに, 何の役に立つのだろうと思われるコマンドが C-M-ttranspose-sexps)です. これはポイントのまえにあるS式を, つぎにあるS式を越えて移動するコマンドです. 引数は反復回数となり, 負の引数では後向きにS式を移動します (つまり正の引数を指定したC-M-tの効果を打ち消せる). 引数が0の場合は, 何もしないのではなくて, ポイントのあとにあるS式とマークのあとにあるS式を入れ替えます.

バッファ内でつぎにあるS式の周りにリージョンを設定するには, C-M-@mark-sexp)を使います. このコマンドは, C-M-fによる移動先にマークを設定します. C-M-@は, C-M-fと同様に引数を取ります. とりわけ, 負の引数は, 直前のS式の先頭にマークを設定するのに便利です.

リストおよびS式コマンドが行う構文の解釈は, 構文テーブルに完全に支配されます. たとえば, 任意の文字を開き区切りとして宣言できて, そうすると開き括弧のようにふるまうようになります. See section 構文テーブル.


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

20.4 関数定義(defun)

Emacsでは, トップレベルの括弧でグループ化したものは 関数定義(defun)と呼ばれます. この名前は, Lispファイルではトップレベルにあるリストの大半が スペシャルフォームdefunであるという事実に由来します. しかし, その中身が何であろうとも, また, 使用プログラム言語が何であろうとも, Emacs流には, トップレベルの括弧でグループ化されたものは すべて関数定義(defun)です. たとえば, Cの関数定義の本体は関数定義(defun)です.

C-M-a

現在の関数定義, あるいは, 直前の関数定義の先頭に移動する (beginning-of-defun).

C-M-e

現在の関数定義, あるいは, つぎの関数定義の末尾に移動する (end-of-defun).

C-M-h

現在の関数定義, あるいは, つぎの関数定義を囲むリージョンを設定する (mark-defun).

現在の関数定義の先頭や末尾に移動するコマンドは, C-M-abeginning-of-defun)と C-M-eend-of-defun)です.

現在の関数定義を操作したいのであれば, C-M-hmark-defun)を使って, 現在の関数定義かつぎの関数定義の先頭にポイントを置き, その末尾にマークを設定します. たとえば, 関数定義をテキストの別の位置に移動する準備をするには, このコマンドを使うのがもっとも簡単な方法です. Cモードでは, C-M-hc-mark-functionを実行しますが, mark-defunとほとんど同じです. 違いは, 引数宣言, 関数名, 戻り値の型名と遡って, Cの関数全体をリージョンに含めることです. See section テキストオブジェクトをマークするコマンド.

Emacsは, もっとも左の桁でみつけた任意の開き括弧を 関数定義の始まりであると仮定します. したがって, トップレベルのリストの始まりでない限り, Lispファイルの中では左端に開き括弧を置いてはいけません. また, 関数本体の始まりを表すのでない限り, Cのコードの行頭に開き中括弧や開き区切りを置いてはいけません. もっとも起こりやすい場面は, 文字列の途中で, 行頭に開き区切りを入れたい場合です. トラブルを避けるために, 開き区切りのまえに エスケープ文字(CやEmacs Lispでは ‘\’, その他のLisp方言のいくつかでは‘/’)を入れてください. これで文字列の内容が影響を受けることはありません.

大昔のもともとのEmacsでは, 関数定義を探すために, より上位レベルの括弧がなくなるまで遡っていました. この方法では, たとえ小さな関数であっても, バッファの先頭まで遡って走査することがつねに必要でした. これを高速化するために, 左端内の任意の‘(’ (あるいは, 開き区切りと宣言された任意の文字)が 関数定義の始まりであると仮定するように, Emacsを変更しました. この発見的手法で, ほとんど正しく処理できて, 時間のかかる走査を回避できます. しかし, 上述の約束事は必要です.


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

20.5 プログラムの字下げ

正しく字下げされた状態にプログラムを保つ最良の方法は, 変更したらEmacsに字下げをやり直させることです. Emacsには, 1行の字下げ, 指定された行数の字下げ, あるいは, 括弧でグループ化した内部のすべての行の字下げを行うコマンドがあります.

Emacsでは, ライブラリppにLispのプリティプリンタ(32) もあります. このプログラムは, 美しく見えるように字下げを施してLispオブジェクトを 清書するプログラムです.


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

20.5.1 プログラムの字下げ基本コマンド

<TAB>

現在行の字下げを調整する.

C-j

<RET>に続けて<TAB>と打鍵するのと同じ (newline-and-indent).

基本的な字下げコマンドは<TAB>です. 直前の数行から判断した正しい字下げを現在行に施します. <TAB>が実行する関数は, メジャーモードに依存します. たとえば, Lispモードではlisp-indent-line, Cモードではc-indent-lineが実行されます. これらの関数はそれぞれの言語の構文を解釈しますが, どれも同じことを行うためのものです. プログラム言語向けメジャーモードにおいては, <TAB>は, 現在行のどこにポイントがあっても, 現在行の先頭に白文字を挿入したり削除したりします. ポイントが行頭の白文字の中にあったときは, <TAB>は最後の白文字のうしろにポイントを置きます. そうでなければ, <TAB>を打ったときの文字のところに留まります.

ポイント位置にタブを挿入するには, C-q <TAB>を使います.

新たにソースコード行を入力するときには, C-jnewline-and-indent)を使ってください. これは, <RET>に続けて<TAB>を打鍵することと等価です. C-jは, 空行を作ってから, その行で適切な字下げを行います.

括弧でグループにまとめたところでは, <TAB>は, 2行目以降の行をそれぞれ直前の行の真下にくるように字下げします. したがって, ある行を非標準的な字下げにすると, 以降の行もその字下げに従うことになります. <TAB>による標準的な字下げが, 特定の行では美しくないので無視したい場合には, 字下げのこのようなふるまいが便利です.

(字下げ処理を含めて)Emacsは, 左端にある, 開き丸括弧, 開き中括弧, および, その他の開き区切りを関数の始まりと仮定することを 覚えておきましょう. たとえ文字列の中であっても, 関数の始まりでない開き区切りをけっして0桁目に置いてはいけません. この制約は字下げコマンドを高速にするためにきわめて重要です. 無条件で受け入れてください. これに関してより詳しくは, See section 関数定義(defun).


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

20.5.2 複数行の字下げ

変更した複数行や, リスト構造中の異なるレベル箇所へ移した複数の行を 字下げし直すには, いくつかのコマンドを利用できます.

C-M-q

リスト内のすべての行を字下げし直す(indent-sexp).

C-u <TAB>

リストの最初の行が正しい字下げ位置にくるように, リストのすべての行を横にそのまま動かす.

C-M-\

リージョン内のすべての行を字下げし直す(indent-region).

1つのリストの中身を字下げし直すには, リストの始まり位置にポイントを置いて C-M-q(Lispモードではindent-sexp, Cモードではc-indent-exp, 他のモードでは適切なコマンドにバインドされている)と打ちます. S式が始まる行の字下げは変化しません. つまり, リスト内の相対的な字下げが変化するだけで, リストの位置は変わりません. リストの開始位置も直すには, C-M-qのまえに<TAB>を打ってください.

リスト内の相対的な字下げは正しいけれども, リストの開始行の字下げが正しくない場合には, その行に移動してC-u <TAB>と打ちます. <TAB>に数引数を指定すると, 通常どおり現在行を字下げしてから, その行から始まるリスト内のすべての行にも同じ量の字下げを加えます. いいかえれば, グループ全体をひとまとめに字下げし直します. ただし, このコマンドは賢くて, 文字列の中の行は移動しませんし, Cモードではプリプロセッサ行を移動しません.

字下げし直す範囲を指定するには, リージョンを使うこともできます. コマンドC-M-\indent-region)は, ポイントとマークのあいだに 行の先頭文字が含まれるすべての行について<TAB>を実行します.


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

20.5.3 Lispの字下げのカスタマイズ

Lisp式に対する字下げの仕方を, その式から呼ばれる関数と関係付けることができます. 各Lisp関数に対して, あらかじめ定義された字下げパターンの中から選んだり, Lispプログラムで任意のものを定義したりできます.

字下げの標準パターンは, つぎのとおりです. 式の開始行に関数呼び出しの引数がある場合は, 最初の引数の直下に2行目がくるように字下げします. それ以外の場合は, 関数名の直下に2行目がくるように字下げします. 続く各行は, 入れ子の深さが同じである行の字下げと同じになります.

変数lisp-indent-offsetnil以外ならば, 式の2行目に対する通常の字下げパターンを無効にして, 式の開始桁からつねにlisp-indent-offsetだけ字下げします.

標準パターンが使用されない関数もいくつかあります. 名前がdefで始まる関数に対しては, 式を開始する開き括弧の桁位置にlisp-body-indentを加えた桁位置へ 2行目がくるように字下げします.

関数名の属性lisp-indent-functionを変更すれば, 各関数ごとに標準パターン以外の字下げを施せます. この属性が取りえる値にはつぎの4つがあります.

nil

属性がないのと同じ. 標準の字下げパターンを使用する.

defun

名前がdefで始まる関数に用いる字下げパターンを使用する.

数値 number

関数の最初のnumber個の引数を区別された引数と呼び, 残りを式の本体と呼ぶ. 行の最初の引数が区別された引数かどうかによって, 各行の字下げが異なる. 引数が本体の一部ならば, それを含んだ式を開始する開き括弧の桁位置に lisp-body-indentを加えた桁位置へ字下げする. 引数が区別された引数で最初か2番目ならば, lisp-body-indent2倍を加えた桁位置へ字下げする. 引数が区別された引数であっても3番目以降ならば, 標準パターンを適用する.

シンボルsymbol

symbolは関数名であること. この関数は, 当該式の字下げ幅を計算する. この関数はつぎの2つの引数を受け取る.

state

当該行の先頭までを解析したときのparse-partial-sexp (字下げと入れ子の計算を行うLispの基本的な関数)の戻り値.

pos

字下げ対象の行の開始位置.

この関数は, 当該行に対する字下げ幅の桁数, あるいは, リストのcarがそのような数値であるリストを返す必要がある. 数値を返した場合は, 括弧の入れ子レベルが同じ行に対しては 同じ字下げ幅を意味する. リストを返した場合は, 後続の行に対しては字下げ幅が異なる可能性を意味する. このような差異は, C-M-qで字下げを計算するときに現れる. 数値が返された場合, C-M-qは, リストの末尾に達するまでは, 字下げの再計算を行う必要がない.


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

20.5.4 Cの字下げコマンド

ここでは, Cモードとその関連モードにおける字下げコマンドを紹介します.

C-c C-q

現在のトップレベルの関数定義, あるいは, 型宣言の集まりを字下げし直す (c-indent-defun).

C-M-q

ポイントのうしろにある釣り合った式の中の各行を字下げし直す (c-indent-exp). 前置引数を指定すると, 不正な構文に対する検査をせずに, 警告メッセージも発しない.

<TAB>

現在行を字下げし直すか, タブ文字を挿入する (c-indent-command).

c-tab-always-indenttならば, 現在行を字下げし直すだけで, 他には何もしない. これがデフォルト.

この変数がnilならば, ポイントが左端か字下げの余白部分にある場合に限り, 字下げし直す. さもなければ, タブ (あるいは, indent-tabs-modenilならば, 等価な個数の空白)を挿入する.

上記の(nilt)以外の値であれば, 通常どおり字下げし直す. ただし, コメント, 文字列, プリプロセッサ指令の内側では, タブを挿入する.

C-u <TAB>

現在行の構文に従って現在行を字下げし直す. なお, 現在行から始まる式を構成する行も同じ幅だけ字下げし直す. see section 複数行の字下げ.

カレントバッファ全体を字下げし直すには, C-x h C-M-\と打ちます. これは, まず, バッファ全体をリージョンとしてから, そのリージョンを字下げし直します.

カレントブロックを字下げし直すには, C-M-u C-M-qと打ちます. これは, まず, ブロックの先頭に移動してから, ブロック全体を字下げし直します.


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

20.5.5 Cの字下げのカスタマイズ

Cモードとその関連モードでは, 字下げのカスタマイズには, 単純ですが柔軟性のある機構を用いています. この機構は2段階で動作します. まず, 行をその内容と文脈から構文的に分類します. つぎに, 構文構成要素の各種類に, カスタマイズ可能な字下げのオフセットを対応させます.


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

20.5.5.1 第1段階−−構文解析

第1段階では, Cの字下げ機構は, 字下げしようとしているまえの行を調べて, その行を構成する構文上の構成要素を決定します. つまり, 構文シンボルとバッファ内の相対位置を要素とする 構文構成要素のリストを組み立てます. 構文シンボルには, statement(文)や substatement(部分文)のように 文法要素を記述するものと, class-open(クラス開始)や knr-argdecl(K&R版引数宣言)のように文法要素のあいだの位置を 記述するものがあります.

概念的には, Cのコード行は, バッファ中でそれよりまえに あるいずれかの行に対して必ず相対的に字下げされます. これは構文構成要素リストの中にあるバッファ内位置として表現されます.

以下に例を示します. つぎのコードが, C++モードのバッファに入っているとしましょう (実際にバッファに行番号が表示されるわけではない).

 
1: void swap (int& a, int& b)
2: {
3:   int tmp = a;
4:   a = b;
5:   b = tmp;
6: }

4行目で(c-show-syntactic-informationを実行する) C-c C-sを打つと, その行に対する字下げ機構の結果が表示されます.

 
((statement . 32))

これは, その行が文であり, バッファ内位置32に対して相対的に字下げされていることを示します. バッファ内位置32は, 3行目のintの‘i’にあたります. カーソルを3行目に動かしてC-c C-sと打つと, 今度はつぎのように表示されます.

 
((defun-block-intro . 28))

この結果は, int行がブロックの最初の文であり, バッファ内位置28に対して相対的に字下げされていることを示しています. バッファ内位置28は, 関数ヘッダの直後の中括弧にあたります.

別の例を見てみましょう.

 
1: int add (int val, int incr, int doit)
2: {
3:   if (doit)
4:     {
5:       return (val + incr);
6:     }
7:   return (val);
8: }

4行目でC-c C-sと打つと, つぎのように表示されます.

 
((substatement-open . 43))

これは, 中括弧が部分文のブロックを始めていることを示しています. ところで, 部分文とは, if, else, while, do, switch, for, try, catch, finally, synchronizedのあとの行を表します.

Cの字下げコマンドにおいては, 字下げのために行を構文解析し終えると, 変数c-syntactic-contextには解析結果を表すリストが入ります. このリストの各要素は構文構成要素であり, 構文シンボルと(省かれるかもしれない)対応するバッファ内位置の コンスセルです. 構文構成要素リストには, 複数の要素が含まれることもあります. また, 典型的には, バッファ内位置を持つ要素は1つだけです.


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

20.5.5.2 第2段階−−字下げ計算

Cの字下げ機構は, 構文解析で得られた構文構成要素リスト c-syntactic-contextを使って, 現在行の字下げ幅を計算します. このリストの各要素は, 構文シンボルを含むコンスセルですが, バッファ内位置を含んでいる場合もあります.

リストの各要素は, 最終的な総字下げ量に2つの方法で寄与します. まず, 各構文シンボルに字下げオフセットを対応付ける連想リスト c-offsets-alistから要素を探すために構文シンボルが使われます. 各構文構成シンボルのオフセットを総字下げ量に加えます. つぎに, リストの要素にバッファ内位置が含まれていれば, その箇所の桁位置を字下げ量に加えます. これらのオフセットと桁数をすべて加えることで, 総字下げ量が求まります.

以下の例でCの字下げ機構の動作を説明しましょう.

 
1: void swap (int& a, int& b)
2: {
3:   int tmp = a;
4:   a = b;
5:   b = tmp;
6: }

3行目にポイントがあって, そこで<TAB>と打って字下げし直すとしましょう. 上(see section 第1段階−−構文解析)でも説明しましたが, その行に対する構文構成要素リストはつぎのようになります.

 
((defun-block-intro . 28))

ここでは, まず, 連想リストc-offsets-alistから defun-block-introを探すことから始めます. その結果が整数値2であったとしましょう. この値を計算中の合計(0で初期化されている)に加えて, 総字下げ量は空白2文字と更新されます.

つぎの段階は, バッファ内位置28の桁位置を求めることです. バッファ内位置28の中括弧は0桁目にあるので, 0を計算中の合計に加えます. 3行目には構文要素が1つしかないので, 総字下げ量は空白2文字となります.

 
1: int add (int val, int incr, int doit)
2: {
3:   if (doit)
4:     {
5:       return(val + incr);
6:     }
7:   return(val);
8: }

4行目で<TAB>と打つと, 同じ過程を繰り返しますが, 異なる値を使って計算されます. この行に対する構文構成要素リストはつぎのとおりです.

 
((substatement-open . 43))

まずは, シンボルsubstatement-openを連想リスト c-offsets-alistから探します. このシンボルに対するオフセットが2であったとしましょう. この時点で計算中の合計は2(0 + 2 = 2)です. つぎに, バッファ内位置43(3行目のifの‘i’の位置)の 桁位置2を加えます. 結果として, 空白4文字という総字下げ量が求まります.

行を解析した結果, c-offsets-alistに現れない構文シンボルが みつかった場合, そのシンボルは無視します. しかし, 変数c-strict-syntax-pnil以外の値であれば, エラーを報告します.


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

20.5.5.3 字下げスタイルの変更

C流のモードの字下げをカスタマイズする方法は2つあります. 1つは, あらかじめ定義されているスタイルから選択する方法です. それぞれのスタイルでは, 各構文シンボルに対するオフセットが定められています. もう1つはより柔軟な方法で, 各構文シンボルの扱い方をカスタマイズできます. 定義されている構文シンボルの一覧については, See section 構文シンボル.

M-x c-set-style <RET> style <RET>

あらかじめ定義されている字下げスタイルstyleを選択する. styleを入力する際に?と打てば, 定義済みのスタイル一覧を見ることができる. スタイルの見栄えを調べるには, そのスタイルを選択して, 適当なCのコードを字下げし直してみる.

C-c C-o symbol <RET> offset <RET>

構文シンボルsymbolに対する字下げのオフセットを設定する (c-set-offset). 2番目の引数offsetで, 字下げのオフセットを指定する.

変数c-offsets-alistは, 各構文シンボルに与える字下げ量を制御します. この変数の値は連想リストであり, 各要素は(syntactic-symbol . offset)の形をしています. さまざまな構文シンボルに対するオフセットを変えることで, 字下げを細かくカスタマイズできます. 連想リストを変更するには, c-set-offsetを使います(下記参照).

c-offsets-alist内の各オフセットには, 整数, 関数名や変数名, あるいは, 変数c-basic-offsetの値の正負の倍数を表すシンボルである +, -, ++, --, *, /のいずれかを設定できます. したがって, 基本の字下げ幅を空白2文字から3文字に変更したければ, c-basic-offsetに3を設定します.

オフセットに関数を用いると, 字下げのカスタマイズに究極の柔軟性を持たせられます. この関数は, 構文シンボルとバッファ内位置があればそれをconsしたものを 引数として呼ばれます. 戻り値としては, 整数値のオフセットを返す必要があります.

オフセットの値がリストの場合, 各要素は, nil以外の値がみつかるまで上の規則にしたがって処理されます. その後, その値は, 通常のように, 字下げの総量に加えられます. これは, 主に, 複数の関数の結果を組み合わせるために使われます.

対話的に設定するにしてもファイル‘~/.emacs’で設定するにしても, オフセットを設定するもっとも簡単な方法は, コマンドC-c C-oc-set-offset)を使うことです. 最初の引数は構文シンボル, 2番目の引数は希望のオフセットです. 有効な構文シンボル名とその意味の一覧は, See section 構文シンボル.


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

20.5.5.4 構文シンボル

Cモードや関連するモードの字下げに対して有効な構文シンボルを, 構文上の意味とともに, 以下に示します. これらのほとんどのシンボルには, c-offsets-alistでオフセットが与えられています.

string

複数行におよぶ文字列の内側.

c

複数行におよぶCスタイルのブロックコメントの内側.

defun-open

関数定義を開始する中括弧.

defun-close

関数定義を終了する中括弧.

defun-block-intro

トップレベルの関数定義の最初の行.

class-open

クラス定義を開始する中括弧.

class-close

クラス定義を終了する中括弧.

inline-open

クラス内のインラインメソッドを開始する中括弧.

inline-close

クラス内のインラインメソッドを終了する中括弧.

extern-lang-open

外部言語ブロックを開始する中括弧.

extern-lang-close

外部言語ブロックを終了する中括弧.

func-decl-cont

関数定義の引数リストと関数定義の本体を開始する中括弧のあいだの領域. ただし, K&R版の関数定義を除く. Cでは, この部分に空文字やコメント以外は置けない. C++やJavaでは, throws宣言などを置ける.

knr-argdecl-intro

K&R版Cの引数宣言の最初の行.

knr-argdecl

K&R版Cの引数宣言の2行目以降.

topmost-intro

最上位の言語構成要素の最初の行.

topmost-intro-cont

最上位の言語構成要素の2行目以降.

member-init-intro

(構造体の)メンバ初期化リストの最初の行.

member-init-cont

(構造体の)メンバ初期化リストの2行目以降.

inher-intro

多重継承リストの最初.

inher-cont

多重継承リストの2行目以降.

block-open

文ブロックを開始する中括弧.

block-close

文ブロックを終了する中括弧.

brace-list-open

enumのリストや静的配列の初期化リストを開始する中括弧.

brace-list-close

enumのリストや静的配列の初期化リストを終了する中括弧.

brace-list-intro

enumのリストや静的配列の初期化リストの最初の行.

brace-list-entry

enumのリストや静的配列の初期化リストの2行目以降.

brace-entry-open

行が開き中括弧で始まるときの, enumのリストや静的配列の初期化リストの2行目以降.

statement

通常の文.

statement-cont

文の継続行.

statement-block-intro

新規文ブロックの最初の行.

statement-case-intro

caseブロックの最初の行.

statement-case-open

中括弧で始まるcaseブロックの最初の行.

inexpr-statement

式の内側にある文ブロック. これは, C言語のGNU拡張や, 文ブロックを引数としてとるPikeの特殊関数に用いる.

inexpr-class

式の内側にあるクラス定義. これは, Javaの無名クラスや無名配列の初期化式に用いる.

substatement

if, while, for, do, elseの直後の最初の行

substatement-open

substatementのブロックを開始する中括弧.

case-label

caseまたはdefaultラベルを表す.

access-label

C++のアクセス指定子private, protected, publicを表す.

label

通常のラベル.

do-while-closure

do-while文のwhile.

else-clause

if-else文のelse.

catch-clause

C++やJavaのtrycatch構成の catch行やfinally行.

comment-intro

コメントの導入部分だけを含んだ行.

arglist-intro

引数リストの最初の行.

arglist-cont

引数リストを開始する括弧の行に引数がない場合, 引数リストの2行目以降.

arglist-cont-nonempty

引数リストを開始する括弧の行に少なくとも1つの引数がある場合, 引数リストの2行目以降.

arglist-close

引数リストを終了する括弧.

stream-op

ストリーム演算子を用いた式が継続する行.

inclass

クラス定義の内側に入れ子になった言語構成要素. 字下げは, クラス定義の開き中括弧に相対である.

inextern-lang

外部言語ブロックの内側に入れ子になった言語構成要素.

inexpr-statement

式の内側の文ブロックの最初の行. これは, 構文({ … })を使うCに対するGCC拡張に用いる. 文ブロックを引数としてとるPikeの特殊関数にも用いる.

inexpr-class

式の内側のクラス定義の最初の行. これは, Javaの無名クラスや無名配列の初期化式に用いる.

cpp-macro

cppマクロの開始.

friend

C++のfriend宣言.

objc-method-intro

Objective-Cのメソッド定義の最初の行.

objc-method-args-cont

Objective-Cのメソッド定義を継続する行.

objc-method-call-cont

Objective-Cのメソッド呼び出しを継続する行.

inlambda

inclassと同様だが, ラムダ(つまり, 無名)関数の内側に用いる. Pikeのみで用いる.

lambda-intro-cont

キーワードlambdaと関数本体のあいだの, ラムダ関数のヘッダーの継続行. Pikeのみで用いる.


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

20.5.5.5 Cの字下げのための変数

本節では, Cモードとその関連モードの字下げ動作を制御する, モードに固有な変数について説明します.

c-offsets-alist

構文シンボルとその字下げオフセットの連想リスト. このリストに直接に値を設定するのではなく, c-set-offsetを使うこと. 詳細については, see section 字下げスタイルの変更.

c-style-alist

字下げスタイルを定義している変数. 下記参照.

c-basic-offset

c-offsets-alistの中で, シンボル+-が用いるオフセットの基本量.

c-special-indent-hook

ユーザー定義の特別な字下げ調整用のフック. このフックは, Cモードやその関連モードが行の字下げを終えたあとに呼ばれる.

変数c-style-alistは, あらかじめ定義された字下げスタイルを保持します. 各要素は(name variable-setting…)の形をしていて, nameはスタイル名です. また, 各variable-settingは, (variable . value)の形をしています. variableには, Cモードが使用するカスタマイズ用変数の1つを指定します. valueは, 選択されたスタイルが使われるときのvariableの値です.

variablec-offsets-alistである場合は, 特殊なケースです. c-offsets-alistの値をvalueの値で置き換えるのではなく, c-offsets-alistの値の先頭にvalueを追加します. したがって, valueにすべての構文シンボルを設定する必要はありません. デフォルトと異なる構文シンボルだけを単に設定すればよいのです.

コメントだけを含んだ行の字下げも, 変数c-comment-only-line-offset (see section Cモードのコメント)に影響されます.


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

20.5.5.6 Cの字下げスタイル

Cスタイルとは, カスタマイズされた字下げスタイルの集合です. Emacsには, Cモードや関連するモードのためにあらかじめ定義された, gnu, k&r, bsd, stroustrup, linux, python, java, whitesmith, ellemtel, cc-modeといった字下げスタイルがあります. デフォルトのスタイルはgnuです.

望みのスタイルを選択するには, コマンドM-x c-set-styleを使います. 引数としてスタイル名を指定します (Cスタイル名では大文字小文字は区別しない). 選択したスタイルは新たに訪問したバッファにだけ影響し, すでに編集中のバッファには影響しません. さまざまなメジャーモードのスタイルを指定するために 変数c-default-styleを設定することもできます. その値は連想リストである必要があり, その各要素は, 1つのメジャーモードと そのモードで使う字下げスタイルを指定します. たとえば,

 
(setq c-default-style
      '((java-mode . "java") (other . "gnu")))

は, Javaモードには対しては選択を明示し, 他のC流モードには‘gnu’をデフォルトとします.

Cの字下げスタイルを新たに定義するには, 関数c-add-styleを呼びます.

 
(c-add-style name values use-now)

ここで, nameは新しいスタイルの名前(文字列), valuesは要素が(variable . value)の形をした 連想リストです. variableには, Cの字下げのための変数に 書かれているものを指定してください.

use-nownil以外ならば, 新しいスタイルの定義後すぐにそれに切り替えます.


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

20.6 対応している括弧の自動表示

Emacsの括弧の対応付け機能は, テキスト中でどのように括弧が 対応しているか自動的に表示するよう設計されています. 閉じ区切りである自己挿入文字を打つと, それに対応する開き区切りが画面上にあれば, その箇所にほんのしばらくカーソルが移動します. 画面上になければ, エコー領域にその箇所の近くにある文字列を表示します. いずれにしても, 1つのまとまりが閉じたことが判ります.

Lispでは, 括弧だけに対して自動的な対応付けを行います. Cでは, 中括弧や角括弧も対象となります. Emacsは, メジャーモードが設定する構文テーブルに基づいて, どの文字が対応関係にある区切りであるか判定します. See section 構文テーブル.

[x)’のように, 開き区切りと閉じ区切りが対応しない場合, エコー領域に警告メッセージを表示します. 正しい対応関係は構文テーブルで指定します.

括弧の対応表示を制御する変数は3つあります. blink-maching-parenは, 対応表示機能をオンまたはオフにします. nilを設定すると対応表示機能はオフになりますが, デフォルトはtであり, 対応表示を行います. blink-matching-delayは, 対応表示のために待つ秒数を指定します. デフォルトは1秒ですが, システムによっては何分の1秒のほうが便利かもしれません. blink-matching-paren-distanceは, 対応している開き区切りをみつけるために, 何文字分まで戻って探索するか指定します. その範囲内で対応するものがみつからなければ, 走査をやめて何も表示しません. これは, 存在しもしない対応する区切りを探すことに 時間を浪費するのを防ぐためです. デフォルトは12,000です.

Xウィンドウシステムを使用している場合, 対応括弧表示(show-paren)モードにすれば, より強力な括弧の対応表示を利用できます. このモードは, 通常の対応表示をオフにするかわりに, 対応する括弧同士を示すために強調表示を行います. ポイントが閉じ括弧の直後にあるときには, 閉じ括弧とそれに対応する開き括弧の両方を強調表示します. ポイントが開き括弧の直前にあるときには, 対応する閉じ括弧を強調表示します. (ポイントの直後に開き括弧があるときには, カーソルが開き括弧に重ねて表示されるので, 開き括弧を強調表示する必要はない. ) このモードをオン/オフするには, コマンドM-x show-paren-modeを使います.


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

20.7 コメントの操作

コメントはプログラミングの重要な部分なので, Emacsにはコメントの編集や挿入を行うための特別なコマンドがあります.


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

20.7.1 コメント用コマンド

コメント用コマンドはコメントの挿入, 削除, および位置揃えを行います.

M-;

コメントの挿入/位置揃えを行う(indent-for-comment).

C-x ;

コメントの桁位置を設定する(set-comment-column).

C-u - C-x ;

現在行のコメントをキルする(kill-comment).

C-M-j

<RET>に続けて, コメントの挿入/位置揃えを行う (indent-new-comment-line).

M-x comment-region

リージョン内の各行に対して, コメント区切りを追加/削除する.

コメントを挿入するコマンドはM-;indent-for-comment)です. 行にコメントがなければ, 新規にコメントを作成して, コメント桁位置と呼ばれる特定の桁に置きます. コメントを作成する際には, Emacsが正しいと信じるコメント開始文字列 (comment-startの値. 下記参照)を挿入します. ポイントはその文字列の直後に置かれます. コードのテキストがコメント桁位置を越えているときには, 適当な境界に字下げします(通常は少なくとも空白1文字). メジャーモードでコメント終了文字列が指定されていれば, 構文を正しく保つために, ポイントの直後にその文字列を挿入します.

M-;は, 既存のコメントを位置揃えするためにも使えます. 行にコメント開始文字列がすでに含まれていれば, その文字列の直後にポイントを移動してから, 適切な位置に字下げします. 例外として, 0桁目から始まるコメントは動かしません.

特定の文脈における, ある種のコメントの字下げには特殊な規則を持つ メジャーモードもあります. たとえば, Lispのコードでは, セミコロン2つで始まるコメントは, コメント桁位置に揃えるのでなく, コードであるかのように字下げされます. また, セミコロン3つで始まるコメントは左端に置くと仮定されます. Emacsはこれらの慣習を理解していて, セミコロン2つのコメントは<TAB>で字下げし, セミコロン3つのコメントは字下げをまったく変更しません.

 
;; This function is just an example
;;; Here either two or three semicolons are appropriate.
(defun foo (x)
;;; And now, the first part of the function:
  ;; The following line adds one.
  (1+ x))           ; This line adds one.

Cのコードでは, コメントのまえに白文字しかない場合には, そのコメントをコードのように字下げします.

既存のコメントの位置が適切に揃えられている場合でも, コメント開始直後の位置にすぐに移動するにはM-;が便利です.

C-u - C-x ;kill-comment)は, 現在行にコメントがあれば, それをキルします. コメント開始文字列のまえにある字下げもキルします. コメントと思われるものが何もなければ, 何もしません. 他の行にコメントを再挿入するには, その行の末尾に移動してからC-yと打って, さらに, 位置を再調整するためにM-;と打ちます. C-u - C-x ;はひとまとまりのキーではなく, 負の引数を指定したC-x ;set-comment-column)で あることに注意しましょう. このコマンドは, 負の引数を受け取ると, kill-commentを呼ぶようにプログラムされています. kill-commentは, 望むならばキーに直接バインドできる通常のコマンドです.


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

20.7.2 複数行にわたるコメント

コメントを入力していて別の行に継続したければ, コマンド C-M-jindent-new-comment-line)を利用できます. このコマンドは, 入力中のコメントを終了して, そのつぎに空行を作り, 直前のコメントの直下にくるように字下げして新たなコメントを始めます. 自動詰め込み(auto-fill)モードがオンならば, コメントを入力中に詰め込み桁を越えると, 同様にコメントはつぎの行に継続されます. C-M-jを打ったときにポイントが行末になければ, ポイント位置から行末までのテキストは新たなコメントの一部になります.

既存の行をコメントにするには, コマンドM-x comment-regionを使います. このコマンドは, リージョン内で始まる各行にコメント区切り文字列を加えて コメントにします. 負の引数を指定すると逆の操作, つまり, コメント区切り文字列を削除します.

正の引数を指定すると, comment-regionは, 追加するコメント開始文字列の最後の文字を重複させます. つまり, 引数は, その文字を何回重複させるかを示します. たとえば, LispモードでC-u 2 M-x commment-regionとすると, 各行に‘;;’を付加します. コメント区切り文字を重複させるのは, コメントに注意を引き付けるためです. また, コメントの字下げにも影響します. Lispでは, 適切な字下げになるように, 関数定義(defun)のあいだでは引数として3を, 関数定義の内側では引数として2を指定すべきです.

変数comment-paddingは, comment-regionがコメント区切りと各行のもとのテキストとのあいだに 挿入する空白の個数を指定します. デフォルトは1です.


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

20.7.3 コメントを制御するオプション

コメント桁位置は, 変数comment-columnに入っています. この変数には明示的に値を設定できます. あるいは, コマンド C-x ;set-comment-column)を使って, ポイント位置の桁をコメント桁位置として設定できます. C-u C-x ;は, バッファ内で現在行よりまえにある最後のコメントの桁位置を コメント桁位置としてから, M-;を行って現在行のコメントをまえのコメントの直下にくるように 位置を揃えます. C-u - C-x ;は, 前述のように 関数kill-commentを実行することに注意してください.

変数comment-columnは, バッファごとの変数です. つまり, 通常の方法で設定すると, カレントバッファだけに影響しますが, setq-defaultでデフォルト値を変更できます. See section ローカル変数. 多くのメジャーモードでは, この変数をカレントバッファ用に初期化します.

コメント用コマンドは, 変数comment-start-skipの正規表現に基づいて コメントを認識します. この正規表現が空文字列には一致しないようにしてください. 厳密にはコメント開始文字列よりも長く一致するかもしれません. たとえば, Cモードではこの変数の値は"/\\*+ *"ですが, これは ‘/*’のうしろの余分なアスタリスクと空白に一致します. (Lispの構文では, 文字列中に‘\’を含めるために‘\\’とする必要がある. この‘\’は, 最初のアスタリスクの正規表現における特別な 意味を抑制するために必要. see section 正規表現の構文. )

コメント用コマンドで新たなコメントを作ると, コメントを始めるためにcomment-startの値を挿入します. また, ポイントの直後にはcomment-endの値が挿入されて, これから入力するテキストのあとに続くことになります. Cモードでは, comment-startの値は"/* ", comment-endの値は" */"です.

変数comment-multi-lineは, C-M-jindent-new-comment-line)が コメントの内側で使われたときの動作を制御します. comment-multi-linenil(通常の設定)ならば, 現在行のコメントを終了し, 新たなコメントをつぎの行から始めます. comment-multi-linenil以外ならば, 現在行と同じコメントが継続されます. つまり, 現在行のコメントを終えず, 新たな行にも開始文字列を挿入しません. 複数行にわたるコメントを許す言語では, この変数に設定する値は好みの問題です.

変数comment-indent-functionには, 新たに挿入したコメントの字下げや 既存のコメントに桁を揃えるための字下げを計算する関数を 設定する必要があります. この変数には, メジャーモードごとに異なった関数が設定されます. この関数は引数なしで呼ばれますが, コメントがあるときにはその開始位置にポイントを置いて, 新規コメントの挿入時には行末にポイントを置いて呼ばれます. 戻り値は, コメントを始めるべき桁位置です. たとえば, Lispモードでは, この字下げ用フック関数は, 既存のコメントのセミコロンの個数と まえの行のコードに基づいて計算を行います.


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

20.8 括弧の対応を保った編集

M-(

つぎの(1つ以上の)S式を括弧で囲む(insert-parentheses).

M-)

つぎの閉じ括弧のうしろへ移動してから字下げし直す (move-past-close-and-reindent).

コマンドM-(insert-parenthesis)と M-)move-past-close-and-reindent)は, 括弧の対応をつねに保ったまま編集するために設計されました. M-(は一対の括弧を挿入します. 引数がなければ‘()’を挿入しますが, 引数を指定すると, つぎのその個数分のS式を括弧で囲みます. ポイントは開き括弧の直後に置かれます. コマンドM-)は, 閉じ括弧のまえにある字下げを削除しながら 閉じ括弧のうしろにポイントを移動し, そのあと, C-jで字下げします.

たとえば, ( F O O )と打つかわりにM-( F O Oと打てば, カーソルが閉じ括弧のまえにくることを除けば同じ効果を得られます.

M-(は, 直前の文字の構文クラスによっては, 開き括弧のまえに空白を1個挿入することがあります. これを禁止したければ, parens-require-spacesnilを設定してください.


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

20.9 シンボル名の補完

通常, 補完はミニバッファで行われます. しかし, ある種の補完は任意のバッファで利用できます. それはシンボル名に対する補完です.

M-<TAB>は, ポイント直前の部分的なシンボルを, 意味のあるシンボル名の集合から補完するコマンドを実行します. 部分的な名前から補完された追加文字はポイント位置に挿入されます.

バッファ内の部分的な名前に対して, 複数個の補完候補があり, しかも, 追加できる共通部分がない場合には, 補完候補一覧を別のウィンドウに表示します.

ほとんどのプログラム言語向けメジャーモードでは, M-<TAB>はコマンドcomplete-symbolを実行します. この関数には, 2種類の補完機能があります. 通常, このコマンドはタグテーブル(see section タグテーブル)に基づいて補完を行います. 数引数(値は無関係)を指定すると, 当該言語のinfoファイルの索引に 並べられた名前を対象として補完を行います. すなわち, プログラム中で定義されたシンボル名を補完するには 引数なしでM-<TAB>を使い, 標準ライブラリ関数の名前を補完するにはC-u M-<TAB>を使います. もちろん, infoに基づいた補完は, 使用言語の標準ライブラリ関数に対する infoファイルがあり, かつ, それがインストールされている場合にだけ動作します.

Emacs Lispモードでは, 補完対象の名前空間は, 関数定義, 値や属性を持つEmacs中の特殊なシンボルから成ります. しかし, 部分的なシンボルの直前に開き括弧があれば, 関数定義を持つシンボルだけを補完対象とします. これを実現するコマンドはlisp-complete-symbolです.

テキスト(text)モードとその関連モードでは, M-<TAB>はスペルチェッカの辞書に基づいた補完を行います. See section 綴りの検査と訂正.


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

20.10 関数名表示モード(which-functionモード)

関数名表示(which-function)モードは, バッファ内を動き廻るに従って現在の関数名をモード行に表示する マイナモードです.

関数名表示(which-function)モードをオン(あるいはオフ)にするには, コマンドM-x which-function-modeを使います. このコマンドはグローバルです. つまり, 既存のバッファでもこれから作るバッファでも, すべてのバッファに通用します. しかし, which-func-modesの値で指定された 特定のメジャーモードでのみ効果があります. (which-func-modesのデフォルト値はtであり, 関数名表示(which-function)モードの支援方法を知っている すべてのメジャーモードに適用されることを意味する. 具体的には, imenuを使えるメジャーモード. )


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

20.11 説明文書用コマンド

Emacsで実行するLispコードを編集するときには, 関数や変数の説明文字列を表示するコマンド, C-h fdescribe-function)や C-h vdescribe-variable)を利用できます. これらのコマンドは, 説明文字列を表示したい関数や変数の名前を ミニバッファから読み取り, ウィンドウに説明文字列を表示します.

たいへん便利なことに, これらのコマンドはポイント近傍のコードから, デフォルトの引数を選択します. C-h fは, ポイントを含むもっとも内側のリストで呼ばれる関数をデフォルト とします. C-h vは, ポイントの周辺にあるか隣接するシンボル名を デフォルトとします.

Emacs Lispコードに対しては, eldocモードも使えます. このマイナモードは, ポイント位置で呼び出されている関数の引数リストを, たえずエコー領域に表示します. (いいかえれば, ポイントを含む関数呼び出しを探し, その関数の引数リストを表示する. ) eldocマイナモードは, Emacs Lispモードと Lisp対話(lisp-interaction)モードだけに適用できます. この機能をオン/オフするには, コマンドM-x eldoc-modeを使います.

C, Lisp, その他言語のシンボルのinfo文書を見るには C-h C-iinfo-lookup-symbol)を使います. ミニバッファでシンボルを指定します. デフォルトは, バッファ中のポイント位置にあるシンボルです. シンボルに対する説明文書を探す場所, つまり, どのinfoファイルのどの索引を探せばよいかは, メジャーモードが決定します. また, ファイル名に対する説明文書を探すには M-x info-lookup-fileを使います.

M-x manual-entryコマンドを使って, オペレーティングシステムのコマンド, ライブラリ関数, システムコールの 『マニュアルページ』を読むことができます. このコマンドは, マニュアルページを清書するために manプログラムを実行します. システムが許せば非同期に実行するので, マニュアルページが清書されるまで, 編集を継続できます (MS-DOSやMS-Windows 3.xでは, 非同期的なサブプロセスを実行できない. このため, これらのシステムではmanの終了をEmacsが待つあいだは 編集できない). 結果は, ‘*Man topic*’という名前のバッファに入ります. これらのバッファではマン(man)モードと呼ばれる特別な メジャーモードが使われ, スクロールや他のマニュアルページの調査を容易に行えます. より詳しくは, マニュアルページ用のバッファで, C-h mと打ってください.

長いマニュアルページでは, 適切なフェイスを設定するにはとても時間がかかります. さまざまなフォントや表示色を表示できる環境であれば, デフォルトでマニュアルページにフェイスを用いるようになっています. 変数Man-fontify-manpage-flagnilを設定すれば, マニュアルページにおけるフェイスの使用をオフにできます.

他の方法でマニュアルページのテキストをEmacsバッファに挿入した場合, M-x manual-entryと同じ変換を施すには, そこでM-x Man-fontify-manpageコマンドを実行します.

GNUプロジェクトでは最終的に, ほとんどのマニュアルページを infoで閲覧可能なよりよく構成されたマニュアルに置き換えることを望んでいます. See section その他のヘルプコマンド. この作業は, ほんの一部が完了しただけなので, まだマニュアルページを読めることは有益です.


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

20.12 変更記録

コマンドC-x 4 aは, 編集中のファイルに対する 新たな項目を変更記録ファイルに追加します (add-change-log-entry-other-window).

変更記録ファイルは, プログラムを変更した日付やその理由を 時間順に記録したもので, 個々の変更を記述した項目の並びから成ります. 通常は, 編集しているファイルと同じディレクトリ, あるいは, その親ディレクトリに置いた‘ChangeLog’と呼ばれる ファイルに保存されています. 1つの‘ChangeLog’ファイルで, このファイルを置いたディレクトリや そのサブディレクトリに置いた全ファイルの変更を記録できます.

変更記録項目は, 名前, (user-mail-addressから得られた) 電子メイルアドレス, 現在の日付と時刻から成るヘッダ行で始まります. 変更記録内の各行はヘッダ行を除いて, つねに空白かタブで始まります. 1つの項目は小項目から構成され, 各小項目は空白と星印で始まる行で始まります. 以下は, 1993年5月付けの2つの項目で, それぞれに2つの小項目があります.

 
1993-05-25  Richard Stallman  <rms@gnu.org>

        * man.el: Rename symbols `man-*' to `Man-*'.
        (manual-entry): Make prompt string clearer.

        * simple.el (blink-matching-paren-distance):
        Change default to 12,000.

1993-05-24  Richard Stallman  <rms@gnu.org>

        * vc.el (minor-mode-map-alist): Don't use it if it's void.
        (vc-cancel-version): Doc fix.

(Emacsの以前の版では, 日付の形式が異なる. )

1つの項目で複数の変更を記述できます. 各変更について, それぞれの小項目を用意しなくてはいけません. 通常, 小項目のあいだには空行がなくてはいけません. 小項目が関連している(場所は異なるが同じ変更の一部分の)場合には, それらのあいだには空行を入れずに一塊にしておきます. 上記の2番目の項目には, このようにしてまとめた2つの小項目が含まれています.

C-x 4 aは, 変更記録ファイルを訪問して, 最新の項目が今日の日付で当人の名前のものでなければ, 新たに項目を作成します. また, 現在のファイルに対する新たな小項目も作成します. 多くの言語に対して, 変更された関数名やその他のオブジェクトを 推測することもできます.

変更記録ファイルは, 変更記録(change-log)モードで訪問します. このメジャーモードでは, (空行で区切らない)ひとまとまりの小項目群を 段落として扱い, 各項目をページとして扱います. これにより項目の編集が容易になります. C-jや自動詰め込みにより, 新たな行は直前の行と同様に字下げされます. これは項目内容を入力するのに便利です.

プログラムの変更を掌握し, 変更記録を維持する他の手段としては, 版管理(バージョンコントロール)システムがあります. See section 記録項目用バッファの機能.


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

20.13 タグテーブル

タグテーブルとは, 複数のファイルで構成されるプログラムが, どのように各ファイルに分割されているのか記述したものです. これは, プログラムを構成するファイル名, そのファイルに入っている関数の名前(または, 名前の付いた別の単位)や ファイル内の位置の一覧です. こうして関連するファイルをまとめておけば, 全ファイルを対象とした探索や置換をコマンド1つで行えます. また, 関数名とその位置を記録してあるので, 関数がどのファイルに入っているか調べて関数定義をみつけだす M-.のようなコマンドを実現できます.

タグテーブルは, タグテーブルファイルと呼ばれるファイルに格納されます. このファイルの慣習的な名前は‘TAGS’です.

タグテーブルの各項目は, タグ名, タグが(暗黙に)定義されているファイルの名前, そして, ファイル中でタグが定義されている位置を記録しています.

もとのプログラムファイルから, どんな名前がタグテーブルに記録されるかは, プログラム言語によって異なります. 一般的には, すべての関数やサブルーチンを含み, 大域変数, データ型, あると便利なその他の情報などを含むこともあります. 記録された個々の名前をタグと呼びます.


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

20.13.1 ソースファイルのタグ構文

ここでは, 広く一般に使われている言語に対するタグ構文の定義を紹介します.

他にも以下の言語で使えます.

正規表現に基づいてタグを生成する方法 (see section タグテーブルの作成)もあるので, 上記以外の形式や言語を扱うこともできます.


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

20.13.2 タグテーブルの作成

タグテーブルファイルを作成するには, etagsプログラムを使います. etagsは, 数種類の言語について, 構文を解析しタグを取り出すことができます. つぎのように実行します.

 
etags inputfiles

etagsは指定されたファイルを読み, カレント作業ディレクトリの‘TAGS’という名前のファイルに タグテーブルを書き出します. etagsは, ファイル名とその内容から自動的に使用言語を識別します. 後述の‘--language=name’オプションで, 言語を明示することもできます.

ファイルを変更するなどしてタグテーブルの内容が古くなった場合, テーブルを更新するには, 最初にタグテーブルを作成した手順を 繰り返します. 頻繁に更新する必要はありません.

タグテーブルに記録できなかったり, 誤ったファイルを記録してしまった場合, Emacsはタグの定義をみつけることはできません. しかし, (タグの定義を含んだファイルを多少編集するなどしたために) タグテーブルに記録された位置が多少ズレている程度ならば, タグをみつけるのに通常より少し時間がかかるだけです. 記録された位置が大幅に狂っていたとしても, Emacsはタグをみつけることができますが, そのためにファイル全体を調べなくてはなりません.

ですから, 新しいタグを定義したとき, タグの定義を別のファイルに移動したとき, ファイルを相当変更したときには, タグテーブルの更新が必要です. しかし, ファイルを編集するつどタグテーブルを更新する必要はありませんし, 毎日更新する必要すらないでしょう.

タグテーブルに別のタグテーブルを取り込むこともできます. 取り込むタグファイル名をオプション‘--include=file’で 指定してタグファイルを作成します. このように作成したタグファイルには, 指定したソースファイルに加えて, 取り込んだタグファイルに記録されていたファイルも含まれます.

etagsを実行するときに相対ファイル名でソースファイルを指定すると, タグファイルには, タグファイルを書き出したときのディレクトリを 基準にしたファイル名が記録されます. こうした場合, タグファイルとソースファイルを含んだディレクトリ木構造全体を 移動することができ, しかも, タグファイルはソースファイルを正しく指し続けます.

etagsの引数として絶対ファイル名を指定すると, タグファイルには絶対ファイル名が記録されます. こうした場合, ソースファイルが同じ場所にある限り, タグファイルを移動してもタグファイルは同じファイルを指し続けます. 絶対ファイル名は, ‘/’, あるいは, MS-DOSとMS-Windowsでは‘device:/’で始まります.

非常に多数のファイルからタグテーブルを作成する場合, コマンド行の長さを制限しているシステムもあるので, ファイル名をコマンドラインで指定するときに問題が起こる可能性があります. この制限を回避するもっとも単純な方法は, つぎのように, ファイル名を指定する位置にダッシュを打って, etagsに標準入力からファイル名を読み込ませることです.

 
find . -name "*.[chCH]" -print | etags -

オプション‘--language=name’を使えば, 言語を明示的に指定できます. このオプションはファイル名と混ぜていくつでも使用できます. それぞれ, あとに続くファイル名に適用されます. ‘--language=auto’を指定すると, etagsはファイル名とその内容からふたたび使用言語を推測します. ‘--language=none’を指定すれば, 言語に依存した処理をいっさい行わないようになります. すると, etagsは正規表現による一致だけに 基づいてタグを認識します. etagsが知っている言語と, 言語を推測するファイル名規則を表示するには, ‘etags --help’を指定します.

--regex’オプションは, 正規表現による一致に基づいてタグを認識させる一般的な方法です. このオプションとファイル名を自由に混ぜて使用できます. 各‘--regex’オプションは, それ以前に指定した正規表現に追加され, オプションのあとにあるファイルに適用されます. オプションの構文はつぎのとおりです.

 
--regex=/tagregexp[/nameregexp]/

ここで, tagregexpは, 行に一致させてタグを取り出すために使われます. これはつねに位置が固定されています. つまり, ‘^’が前置されているかのように扱われます. 字下げ分を考慮したければ, 正規表現を‘[ \t]*’で始めて, 行頭の任意個の空白に一致するようにします. 正規表現においては, ‘\’は直後の文字をクォートし, ‘\t’はタブ文字を表します. etagsでは, これら以外にはCで使われるエスケープシーケンスを 扱えないことに注意してください.

etagsの正規表現の構文は, Emacsのものと同じで, 反復回数演算子(interval operator)が拡張されています. この演算子は, grepedで使えるものと同じ動作をします. 反復回数演算子の構文は‘\{m,n\}’であり, 直前の正規表現のm回以上n回以下の繰り返しに一致します.

tagregexpがタグとして認識したい部分よりも長く一致するようには しないでください. tagregexpに一致する部分が必要以上に長くなるのが避けられないならば, タグの範囲を狭めるためにnameregexpを追加するとよいかもしれません. 正規表現を利用した例をいくつか紹介しましょう.

-R’オプションは, それまでに‘--regex’オプションで定義した すべての正規表現を削除します. つぎの使用例からもわかるように, オプションのあとに続くファイルに適用されます.

 
etags --regex=/reg1/ voo.doo --regex=/reg2/ \
    bar.ber -R --lang=lisp los.er

この例では, etagsは, ‘voo.doo’と‘bar.ber’に対しては, その内容から使用言語を推定します. さらに, ‘voo.doo’から余分にタグを認識するためにreg1を使い, ‘bar.ber’から余分にタグを認識するためには reg1reg2の両方を使います. ‘los.er’からタグを認識するには, Lispのタグ構文規則だけを使い, 正規表現による一致はいっさい使いません.

別の例を示しましょう. ここでは, シェルが解釈しないように正規表現をクォートします.

他のオプション一覧を表示するには, etags --helpを実行してください.


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

20.13.3 タグテーブルの選択

Emacsでは, いつでも1つの選択されたタグテーブルがあり, タグテーブルを使って動作するコマンドは選択されたタグテーブルを使用します. タグテーブルを選択するには, M-x visit-tags-tableと打ちます. すると, タグテーブルファイル名を聞いてきます. デフォルトのファイル名は, デフォルトディレクトリの‘TAGS’です.

このコマンドは, ファイル名を変数tags-file-nameに格納するだけです. タグテーブルを使おうとしない限り, Emacsは実際にはタグテーブルの内容を読み込みません. visit-tags-tableを使わずに, 自分自身でこの変数にファイル名を設定してもかまいません. この変数の初期値はnilです. これは, タグテーブルを使うすべてのコマンドに, 使用するタグテーブルファイルを尋ねさせることになります.

すでにタグテーブルを読み込んであるときにvisit-tags-tableを使うと, 2つの選択肢があります. 現在のタグテーブルリストに新たにタグテーブルを追加するか, タグテーブルリストを新規に始めるかです. タグコマンドは, 現在のリストにあるすべてのタグテーブルを使用します. 新たなタグテーブルリストを始めると, 他のタグテーブルのかわりに 新たなタグテーブルが使われます. 現在のリストに新たなタグテーブルを追加すると, 他のタグテーブルとともに新たなものも使われます. タグコマンドがタグテーブルリストを走査するときには, つねにリストの先頭から始めるわけではありません. 現在のファイルを記録しているタグテーブルがあれば, まずそれから始めてリストの末尾まで進みます. そして, リストの先頭からリストに含まれる すべてのタグテーブルを調べ終るまで走査を続けます.

変数tags-table-listに文字列のリストを設定すれば, タグテーブルの正確なリストをあらかじめ指定できます. たとえば, つぎのようにします.

 
(setq tags-table-list
      '("~/emacs" "/usr/local/lib/emacs/src"))

この設定例では, タグコマンドは, 個人の‘~/emacs’ディレクトリと ‘/usr/local/lib/emacs/src’ディレクトリの (2つの)‘TAGS’ファイルを見にいきます. 上で述べたように, タグファイルを使う順番は, 対象としているファイルやそのファイルを記述しているタグテーブルに依存します.

tags-file-nametags-table-listの両方に 値を設定してはいけません.


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

20.13.4 タグの探索

タグテーブルで実現されるもっとも重要な機能は, 指定したタグの定義を探し出すことです.

M-. tag <RET>

タグtagの最初の定義を探す(find-tag).

C-u M-.

最後に指定したタグのつぎの定義を探す.

C-u - M-.

まえにみつかったタグに戻る.

C-M-. pattern <RET>

名前がpatternに一致するタグを探す(find-tag-regexp).

C-u C-M-.

最後に使用したパターンに一致するつぎのタグを探する.

C-x 4 . tag <RET>

タグtagの最初の定義を探し, 別のウィンドウに表示する(find-tag-other-window).

C-x 5 . tag <RET>

タグtagの最初の定義を探し, バッファを選択するための新たなフレームを作る. (find-tag-other-frame).

M-*

まえにM-.を起動した場所へ戻る.

M-.find-tag)は, 指定したタグの定義を探すコマンドです. まず, タグテーブルの中で文字列としてタグ名を探し, タグテーブルの情報を用いて, 定義されているファイルの名前とファイル内でのおおよその文字位置を求めます. 続いて, find-tagはそのソースファイルを訪れて, ポイントをおおよその文字位置に移動してから, 範囲を広げながらタグの定義を探します.

(単に<RET>と打って)引数を指定しないと, ポイントの直前または周辺にあるS式をtag引数として使います. S式に関しては, See section リストとS式.

コマンドM-.にタグの名前を完全に与える必要はありません. その一部分で十分です. というのは, M-.は, 部分文字列としてtagを含む タグをタグテーブルで探すからです. もちろん, 部分一致よりも全一致のほうが望ましいです. 同じ部分文字列に一致する別のタグを探すには, C-u M-.のようにfind-tagに数引数を指定します. こうするとタグ名を聞いてきませんが, 最後に使ったものと同じ部分文字列を含む別のタグを タグテーブルから探します. もし本物の<META>キーが使えるのであれば, C-u M-.のかわりにM-0 M-.と打つほうが簡単でしょう.

バッファの切り替えを伴う他のコマンドと同様に, find-tagにも新たなバッファを別のウィンドウに表示したり, 新規作成したフレームに表示する変種があります. 前者はC-x 4 .であり, コマンドfind-tag-other-windowを起動します. 後者はC-x 5 .であり, find-tag-other-frameを起動します.

最近にみつけたタグ位置に戻るには, C-u - M-.を使います. より一般的には, M-.に負の数引数を指定します. このコマンドは, 別のバッファへも移動します. C-x 4 .に負の数引数を指定すると, 別のウィンドウでまえのタグ位置に戻ります.

最近にみつけたタグ位置に戻るだけでなく, タグを探したときの場所へ戻ることもできます. それには, コマンドpop-tag-markを起動するM-*を使います. 典型的な使い方では, M-.で何かの定義を調べてから, M-*でもとの場所に戻ります.

C-u - M-.M-*のどちらも, 変数find-tag-marker-ring-lengthで指定される深さまで, 辿った経路を引き返せます.

コマンドC-M-.find-tag-regexp)は, 指定した正規表現に一致するタグを訪れます. 部分文字列ではなく正規表現に一致するものであることを除けば, M-.と同じです.


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

20.13.5 タグテーブルを用いた探索と置換

ここで紹介するコマンドは, 選択されたタグテーブルに記録されている すべてのファイルを1つ1つ訪れては探索を行います. これらのコマンドに対しては, タグテーブルは探索対象となる 一連のファイルを指定するだけです.

M-x tags-search <RET> regexp <RET>

選択されたタグテーブル内の各ファイルから 指定された正規表現を探索する.

M-x tags-query-replace <RET> regexp <RET> replacement <RET>

選択されたタグテーブル内の各ファイルに対して, query-replace-regexpを実行する.

M-,

ポイント位置から上記のコマンドのいずれかを再実行する (tags-loop-continue).

M-x tags-searchは, ミニバッファで正規表現を読み取り, 選択されたタグテーブル内のすべてのファイル1つ1つについて, 正規表現に一致する部分を探します. このコマンドは探索しているファイル名を表示するので, 進行状況がわかります. 正規表現に一致する部分がみつかると, tags-searchはすぐに戻ります.

一致する部分をみつけたあとに, 残りも探したくなるでしょう. つぎの一致を探すには, M-,tags-loop-continue)と打って, tags-searchを再開します. これは, カレントバッファの残りを探索してから, タグテーブルの残りのファイルについても探索します.

M-x tags-query-replaceは, タグテーブル内のすべてのファイルを対象に, query-replace-regexpを実行します. このコマンドは, 通常のM-x query-replace-regexp (問い合わせ型置換)と同じく, 探索すべき正規表現と置換文字列を読み取ります. そして, M-x tags-searchのように探索を行い, 利用者の入力に応じて一致部分を処理することを繰り返します. 問い合わせ型置換について詳しくは, See section 置換コマンド.

M-x tags-query-replaceを一度起動するだけで, タグテーブル内の全ファイルの置換を行うことができます. しかし, 一時的に置換作業から抜け出して, 問い合わせ型置換とは関係ないことを行えると便利です. M-,と打てば, 問い合わせ型置換を再開できます. このコマンドは, 最後に行ったタグの探索コマンドか置換コマンドを 再開します.

ここで紹介したコマンドは, find-tag系列のコマンドよりも, 幅広い探索を実行します. find-tagコマンドは, 指定した部分文字列や正規表現に一致する タグの定義だけをみつけます. コマンドtags-searchtags-query-replaceは, 通常の探索コマンドや置換コマンドがカレントバッファで行うように, 正規表現に一致するあらゆる部分を探し出します.

これらのコマンドは, (Emacsバッファにまだ訪れていないものに対しては) 探索すべきファイル用に一時的なバッファを作成します. 一致部分がみつからなければバッファはただちに消されますが, みつかれば存続します.

tags-searchは, grepプログラムにたいへんよく似ていると 思われたかもしれません. Emacsの下位プロセスとしてgrepを実行して, Emacsに一致した行を1つずつ表示させることもできます. これは, コンパイルを実行するのと同じように動作します. grepが一致を検出したソース箇所を探すことは, コンパイルエラーを探すのと同様に動作します. See section Emacs下でのコンパイラの実行.


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

20.13.6 タグテーブルの照会

M-x list-tags <RET> file <RET>

プログラムファイルfileで定義されているタグの一覧を表示する.

M-x tags-apropos <RET> regexp <RET>

regexpに一致するすべてのタグを表示する.

M-x list-tagsは, 選択されたタグテーブルに記載されている ファイルのどれか1つのファイル名を読み取り, そのファイルで定義されているすべてのタグを表示します. 引数の『ファイル名』は, タグテーブルに記録されたファイル名と 単純に文字列として比較されます. ファイル名というよりは, 文字列として読まれます. したがって, 補完やデフォルトはありませんし, タグテーブルに格納されているとおりに正確にファイル名を入力する必要があります. タグテーブル内のファイル名にディレクトリが含まれない限り, ファイル名にもディレクトリを含めてはいけません.

M-x tags-approposは, タグに対するaproposにあたります (see section アプロポス). このコマンドは, 正規表現を読み取り, 選択されたタグテーブルの中から正規表現に一致する項目のタグを すべてみつけだし, そのタグ名を表示します.

現在のタグテーブルに含まれるタグ名を名前空間として, バッファ内で補完を行うこともできます. See section シンボル名の補完.


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

20.14 emergeを用いたファイルの併合

ちょっとしたミスで, 1つのプログラムから2つの別の版を 作ってしまうこともあります. この混乱した状態を収拾するには, それらを併合する必要があります. emergeを使うと, 併合作業が容易になります. 手動で比較するコマンドについては, ファイルの比較(ediff)Emerge section ‘Emerge’ in The Ediff Manualを参照してください.


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

20.14.1 emergeの概要

以下の4つのコマンドのいずれかでemergeを実行します.

M-x emerge-files

指定した2つのファイルを併合する.

M-x emerge-files-with-ancestor

共通の祖先を参照しながら, 指定した2つのファイルを併合する.

M-x emerge-buffers

2つのバッファを併合する.

M-x emerge-buffers-with-ancestor

3番目のバッファに入っている共通の祖先を参照しながら, 2つのバッファを併合する.

emergeコマンドは, 2つのファイル, あるいは, 2つのバッファを比較して, 比較結果を3つのバッファ, つまり, 各入力テキストに1つずつ(AバッファBバッファ)と, 併合を実施するバッファ(併合バッファ)に表示します. 併合バッファには, 比較によって得られる差分だけでなく, 併合したテキスト全体が表示されます. 2つの入力テキストが相違している箇所については, どちらのテキストを併合バッファに含めるか選択できます.

既存のバッファを入力源とするemergeコマンドでは, 入力バッファがナロイングされていると, バッファの参照可能な部分だけを使います(see section ナロイング).

併合したい2つのテキストのもとである共通の祖先にあたる版を利用できるときには, emergeはそれを使ってどちらの選択肢が正しいのか推測します. 一方の入力と祖先との一致部分がどこかにあれば, もう一方の入力には併合結果に残すべき意図的な変更がなされていると推測します. 共通の祖先のテキストを指定するには, 名前に‘with-ancestor’の付いたコマンドを使ってください. これらのコマンドは, A版, B版, 共通の祖先に対応する 3つのファイル名かバッファ名を読み取ります.

入力を比較してバッファの準備を終えると, つぎは対話的な併合作業が始まります. 併合バッファで特別な併合コマンドを打って併合作業を制御します. 併合バッファには, 単なる差分ではなく併合したテキスト全体が表示されます. 入力テキストの各相違箇所に対して, どちら側を残すか選択したり, 両者をもとにして編集できます.

併合バッファでは, emergeモードと呼ばれる特別なメジャーモードが使われ, これらを選択するコマンドがあります. もちろん, 通常のEmacsコマンドでバッファを編集することもできます.

emergeの注意は, いつでも注目相違箇所と呼ばれる 相違箇所に向けられています. 3つのバッファ内では, 注目相違点はつぎのように印が付けられます.

 
vvvvvvvvvvvvvvvvvvvv
text that differs
^^^^^^^^^^^^^^^^^^^^

emergeはすべての相違箇所に順に番号をふります. さらに, モード行にはつねに注目相違箇所の番号が表示されます.

通常, 併合バッファはA版の内容で始まります. しかし, A版の内容が共通の祖先の内容と一致するときには, 併合バッファはB版の内容で始まります.

emergeを終えると, 併合バッファにはその時点の併合済みテキストが残ります. emerge終了時には, C-x C-wでファイルに保存できます. emerge-filesemerge-files-with-ancestorに 数引数を指定すると, ミニバッファで出力ファイル名を読み取ります. (どちらの場合でも, これがいちばん最後に聞かれるファイル名. ) すると, emerge終了時には, 併合済みのテキストがその出力ファイルに保存されます.

emergeを終えると, 通常, emergeコマンドが併合バッファをファイルに保存します. emergeをC-]でアボートするとemergeコマンドは併合バッファを保存しませんが, 必要ならばユーザー自身で保存できます.


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

20.14.2 emergeのサブモード

併合コマンドを指示するためのモードが2つ, つまり, 高速モード(Fast mode)と編集モード(Edit mode)があり, どちらかを選べます. 高速モードでは, 基本的な併合コマンドは1文字で表され, 通常のEmacsコマンドは禁止されています. 併合コマンドだけを使用するのであれば, 高速モードが便利です. 編集モードでは, すべての併合コマンドはプレフィックスC-c C-cで始まり, 通常のEmacsコマンドも使えます. このモードでは, 併合バッファを編集できますが, emergeの処理は遅くなります.

編集モードに切り替えるにはeを使い, 高速モードに切り替えるにはC-c C-c fを使います. モード行には, 編集モードは‘E’, 高速モードは‘F’と表示されます.

emergeには, 特定の併合コマンドの動作に影響を与えるサブモードが さらに2つあります. 自動前進(auto-advance)モードと 優先箇所スキップ(skip-prefers)モードです.

自動前進モードがオンであると, コマンドabは, 自動的につぎの相違箇所にポイントを進めます. このモードでは, どちらかの入力だけを選ぶ状況である限り, 高速に併合を行えます. モード行には‘A’と表示され, 自動前進モードであるを示します.

優先箇所スキップモードがオンであると, コマンドnpは, A優先/B優先の状態にある相違箇所をスキップします (see section 相違箇所の状態). つまり, どちらの版も『正しい』と推定されない相違箇所だけを調べことになります. モード行には‘S’と表示され, 優先箇所スキップモードであることを示します.

自動前進モードをオン/オフするには, コマンドs aemerge-auto-advance-mode)を使います. 優先箇所スキップモードをオン/オフするには, コマンドs semerge-skip-prefers-mode)を使います. どちらのコマンドも, 正の数引数を指定するとオンにし, 負あるいは0の数引数を指定するとオフにし, 引数を指定しないとトグル(切り替え)します.


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

20.14.3 相違箇所の状態

併合バッファ内では, 相違箇所は‘v’と‘^’の文字だけの行に 挟まれて示されます. 各相違箇所は, つぎの7つのいずれかの状態になっています.

状態A

この相違箇所はA版の内容である. aコマンドは必ずこの状態にする. モード行には‘A’と表示される.

状態B

この相違箇所はB版の内容である. bコマンドは必ずこの状態にする. モード行には‘B’と表示される.

デフォルトA
デフォルトB

まだ決心していないので, 『デフォルト』で, 相違箇所は状態A(A版の内容)か状態B(B版の内容)である. どちらかの選択肢が『優先される』(下記参照)場合を除いて, 相違箇所はすべてデフォルトAで始まる (つまり, 併合バッファの内容はAバッファのコピー).

相違箇所を選択すると, その状態は, デフォルトAやデフォルトBから 状態Aや状態Bに遷移する. つまり, 一度でも選択した相違箇所は, デフォルトAやデフォルトBの状態であることはなく, これらの状態はけっしてモード行には表示されない.

デフォルトの状態として, コマンドd aはデフォルトAを選び, d bデフォルトBを選ぶ. これらのコマンドで選んだデフォルトの状態は, 一度も選択してなく, かつ, どちらの版も優先されない相違箇所に適用される. 併合作業を先頭から順に行っている場合, 最後に選択した相違箇所に続く相違箇所群が一度も選択されていないものである. したがって, 先頭から順に進めるのであれば, d ad bを使い分けて, 併合バッファのある部分ではA版をデフォルトとし, 別の部分ではB版をデフォルトとすることができる.

優先A
優先B

どちらかが優先されているので, 相違箇所は状態A(A版の内容)か状態B(B版の内容)である. つまり, 明示的にはまだ選択していないが, 当該箇所では, 一方の版が共通の祖先に一致するため, 他方の版のほうが正しく思われるのである. したがって, Aバッファが共通の祖先と一致する箇所では, 実際に変更されたほうが正しいものである可能性があるので, B版が優先される.

これらの2つの状態は, モード行では‘A*’や‘B*’と表示される.

混合状態

x cx Cコマンドの結果, 相違箇所は, 状態A(A版の内容)と状態B(B版の内容)の混合状態になっている.

相違箇所がいったんこの状態になると, コマンドabに数引数を指定しない限り, 何もしない.

この状態は, モード行では‘comb’と表示される.


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

20.14.4 併合コマンド

ここでは, 高速モードの併合操作コマンドを示します. 編集モードでは, これらのコマンドのまえにC-c C-cを付けます.

p

まえの相違箇所を選択する.

n

つぎの相違箇所を選択する.

a

この相違箇所をA版にする(状態A).

b

この相違箇所をB版にする(状態B).

C-u n j

番号nの相違箇所を選択する.

.

ポイントを含む相違箇所を選択する. このコマンドは, 併合バッファ, Aバッファ, Bバッファのいずれでも使える.

q

終了する. 併合作業を完了.

C-]

アボートする. 併合作業をやめ, 併合結果も保存しない.

f

高速モードに移行する. (編集モードでは, 実際にはC-c C-c fコマンド. )

e

編集モードに移行する.

l

3つのウィンドウすべてを(C-lのように)再表示する.

-

数引数の一部を指定する.

digit

これも, 数引数の一部を指定する.

d a

併合バッファのこれ以降では, A版を選ぶ(デフォルトA).

d b

併合バッファのこれ以降では, B版を選ぶ(デフォルトB).

c a

この相違箇所のA版のテキストをキルリングにコピーする.

c b

この相違箇所のB版のテキストをキルリングにコピーする.

i a

この相違箇所のA版のテキストをポイント位置に挿入する.

i b

この相違箇所のB版のテキストをポイント位置に挿入する.

m

相違箇所の周りにポイントとマークを設定する.

^

3つのウィンドウすべてを(M-vのように)下にスクロールする.

v

3つのウィンドウすべてを(C-vのように)上にスクロールする.

<

3つのウィンドウすべてを(C-x <のように)左にスクロールする.

>

3つのウィンドウすべてを(C-x >のように)右にスクロールする.

|

3つのウィンドウすべてで, 水平方向のスクロール分をリセットする.

x 1

併合バッファを表示しているウィンドウの高さを1行に縮小する. (フルサイズに戻すにはC-u lを使う. )

x c

この相違箇所の2つの版を混合する(see section 2つの版の混合).

x f

emergeで作業しているファイル/バッファの名前を, ヘルプ用ウィンドウに表示する. (ウィンドウをもとの状態に戻すにはC-u lを使う. )

x j

この相違箇所を, つぎの相違箇所と結合する. (C-u x jでは, まえの相違箇所と結合する. )

x s

この相違箇所を2つに分割する. このコマンドを使うまえに, 3つのバッファそれぞれで, 相違箇所を分割したい位置にポイントを移動しておく.

x t

相違箇所の先頭や末尾にある同じ行を取り去る. このような行が現れるのは, A版とB版は一致しているが, 共通の祖先とは一致しない場合.


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

20.14.5 emergeの終了

qコマンド(emerge-quit)は, 併合を終了し, 出力ファイルを指定してあれば, そこに結果を保存します. AバッファとBバッファは正しい内容に復元されますが, emergeがAバッファとBバッファを作成して, かつ, 編集されていなければ, それらをキルします. さらに, 併合バッファでのemergeコマンドを使用禁止にします. というのは, これ以降に併合コマンドを実行すると さまざまなバッファが悪影響を受ける可能性があるからです.

C-]は, 併合作業をアボートします. つまり, 出力ファイルに書き出さずに終ります. 出力ファイルを指定していなければ, 併合作業をアボートしようが終了しようが, 何の違いもありません.

他のLispプログラムからemergeコマンドが呼び出された場合, 正しく終了するとt, アボートしたときはnilが返されます.


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

20.14.6 2つの版の混合

相違箇所によっては, 両方の版を残したいこともあるでしょう. そのような場合には, x cを使います. すると, 併合バッファはつぎのようになります.

 
#ifdef NEW
version from A buffer
#else /* not NEW */
version from B buffer
#endif /* not NEW */

この例では, 2つの版をCのプリプロセッサの条件節で分けていますが, 変数emerge-combine-versions-templateに好みの文字列を設定すれば, このコマンドで使用する文字列を指定できます. この文字列内では, A版のテキストを置く箇所には‘%a’を, B版のを置く箇所には‘%b’を指定します. 上に示した結果を生じるデフォルトの設定はつぎのとおりです.

 
"#ifdef NEW\n%a#else /* not NEW */\n%b#endif /* not NEW */\n"

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

20.14.7 細かな注意点

併合作業中には, AバッファやBバッファを勝手に編集してはいけません. emergeは一時的にこれらのバッファの内容を変更しますが, 最終的にはもとの状態に戻します.

複数の併合処理を同時に進めることもできますが, 別の併合処理の入力に同じバッファを使用してはいけません. というのは, 一時的にせよ, 互いに異なる複数の変更が 1つのバッファに加えられてしまうからです.

入力ファイル全体を比較する必要があるため, emergeの開始にはしばらく時間がかかる場合もあります. また, diffコマンドが完了するまで, emergeは何もできません. たぶん, そのうち誰かがemergeを変更して, 入力ファイルが大きいときにはバックグラウンドで比較を行うようにするでしょう. そうすれば, emergeがコマンドを受け付けるようになるまで, Emacsで他の作業を続けられます.

フックemerge-startup-hook(see section フック)が, 併合処理の設定の最後 に実行されます.


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

20.15 Cモードと関連するモード

本節では, C, C++, Objective-C, Java, CORBA IDL, Pike用の各モードで利用可能な特別な機能について述べます. 『Cモードと関連するモード』と書いたときには, これらのモードを意味します.


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

20.15.1 Cモードの移動コマンド

本節では, Cモードとその関連モードでポイントを移動する コマンドについて述べます.

C-c C-u

マークをポイント位置に設定し, ポイントを含むプリプロセッサの条件節の先頭に後向きにポイントを戻す. 数引数は反復回数として働く. 負の引数を指定すると, 条件節の末尾に前向きにポイントを移動する. 後向きに戻る場合, #elifは, #ifが続く#elseのように扱われる. 前向きに進む場合, #elifは無視される (33).

C-c C-p

マークをポイント位置に設定し, プリプロセッサの条件節を横断して後向きにポイントを移動する. 数引数は反復回数として働く. 負の引数を指定すると, 前向きに移動する.

C-c C-n

マークをポイント位置に設定し, プリプロセッサの条件節を横断して前向きにポイントを移動する. 数引数は反復回数として働く. 負の引数を指定すると, 後向きに移動する.

M-a

もっとも内側のCの文の先頭にポイントを移動する (c-beginning-of-statement). すでに文の先頭にポイントがある場合, 直前の文の先頭に移動する. 数引数nを指定すると, n-1だけまえの文に移動する.

ポイントが, 文字列やコメントの内側, あるいは, コメントのうしろ(コメントのあいだに白文字がある場合のみ)にある場合, Cの文ではなく自然言語の文単位で移動する.

プログラムから呼ばれるときには, この関数は, 3つの引数, つまり, 反復回数, (これよりも後向きには戻らない)移動限界, ポイントがコメントの内側にある場合に自然言語の文単位の移動をするかどうか, を取るが, これらは省略できる.

M-e

もっとも内側のCの文の末尾にポイントを移動する. M-aと同じだが, 移動方向が逆(c-end-of-statement).

M-x c-backward-into-nomenclature

C++の命名語法の部分や単語の先頭に後向きにポイントを移動する. 数引数nを指定すると, n回移動する. nが負ならば, 前向きに移動する. C++の命名語法とは, NamingSymbolsWithMixedCaseAndNoUnderlinesのような形のシンボル名のこと (つまり, 大文字で始めた単語を連結したもの). 各大文字が部分や単語の先頭となる.

GNUプロジェクトでは, CやC++の識別子は, 大文字小文字で区別するのではなく, 単語を下線で区切ることを推奨する.

M-x c-forward-into-nomenclature

C++の命名語法の部分や単語の末尾に前向きにポイントを移動する. 数引数nを指定すると, n回移動する.


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

20.15.2 エレクトリックC文字

Cモードとその関連モードでは, ある種の印字文字は『エレクトリック』です. つまり, その文字自身を挿入することに加えて, 現在行を字下げし直したり, 改行も挿入することさえあります. この機能は, 変数c-auto-newlineで制御されます. 『エレクトリック』文字は, {, }, :, #, ;, ,, <, >, /, *, (, )です.

自動改行(auto-newline)機能がオン (モード行のモード名のあとに‘/a’と表示される)の場合に限り, エレクトリック文字は改行を挿入します. この機能は, 変数c-auto-newlineで制御されます. コマンドC-c C-aでこの機能をオン/オフできます.

C-c C-a

自動改行機能をオン/オフする(c-toggle-auto-state). 数引数を指定した場合, 正ならば自動改行機能をオンにし, 負ならばオフにする.

コロン:はエレクトリックです. なぜなら, 単独のコロンの入力の解釈としてはそれが適切だからです. しかし, C++で2つの連続するコロンを挿入する場合, コロンのエレクトリックな動作は不便です. C-c :と打てば, 字下げも改行の挿入も行わずにコロンを2つ挿入できます.

C-c :

行の字下げも改行の挿入もせずに, スコープ演算子を表すコロン2つをポイント位置に挿入する (c-scope-operator).

エレクトリックキー#は, プリプロセッサ指令の始まりと思われる位置では, 行を字下げし直します. 変数c-electric-pound-behaviorの値が(alignleft)のときには, このようになります. この機能をオフにするには, c-electric-pound-behaviornilを設定します.

変数c-hanging-braces-alistは, 挿入された中括弧の前/後への改行の挿入を制御します. これは, (syntactic-symbol . nl-list)の形の要素 から成る連想リストです. c-offsets-alistに現れるほとんどの構文シンボルは, ここでも意味を持ちます.

リストnl-listは, シンボルbeforeafterのいずれか, あるいはその両方, もしくはnilを含みます. 中括弧が挿入されるときには, その中括弧が定義する構文上の文脈を c-hanging-braces-alistから探します. みつかれば, nl-listを使って 中括弧の前/後/前後のどこに改行を挿入するか決定します. みつからなければ, デフォルトとして中括弧の前後に改行を挿入します.

変数c-hanging-colons-alistは, 挿入されたコロンの前/後への改行の挿入を制御します. これは, (syntactic-symbol . nl-list)の形の要素 から成る連想リストです. リストnl-listは, シンボルbeforeafterのいずれか, あるいはその両方, もしくはnilを含みます.

コロンが挿入されるときには, そのコロンが定義する構文シンボルを この連想リストから探します. みつかれば, nl-listを使って コロンの前/後のどこに改行を挿入するか決定します. みつからなければ, 改行を挿入しません.

自動改行機能がオンのときには, エレクトリック文字は自動的に改行を削除します. この機能により, 改行が不要だと思われるもっとも一般的な場面で改行を削除するので, 自動改行機能をユーザーにより受け入れやすくしています. Emacsは改行を削除することが望ましいいくつかの場面を認識できますが, 変数c-cleanup-listを設定すれば, どの場面で行うか指定できます. この変数の値はシンボルのリストです. 各要素は, 改行を削除してよい場面を1つ指定します. 以下に指定できるシンボルとその意味を示します.

brace-catch-brace

} catch (condition) {’の構造全体を1行に再配置する. catchcondition以外に中括弧のあいだになにもないときに ‘{’を打つと再配置する.

brace-else-brace

} else {’の構造全体を1行に再配置する. elseに続けて‘{’を打ったときに再配置するが, 中括弧とelseのあいだに空白以外の文字がない場合に限る.

brace-elseif-brace

} else if (…) {’の構造全体を1行に配置する. ‘{’を打ったときに再配置するが, キーワードとifの条件式を除いて, ‘}’と‘{’のあいだに空白以外の文字がない場合に限る.

empty-defun-braces

空の関数定義の中括弧, ‘{’と‘}’を同じ行に再配置する. 閉じ中括弧‘}’を打ったときに再配置する.

defun-close-semi

structや同様の型宣言のあとのセミコロンを閉じ中括弧と同じ行に再配置する. セミコロンを打ったときに再配置する.

list-close-comma

配列/合成体の初期化式の中の閉じ中括弧とそれに続くコンマを同じ行に再配置する. コンマを打ったときに再配置する.

scope-operator

C++のスコープ演算子を表している可能性がある2つのコロンを一緒にする. 2つめのコロンを打ったときに一緒にするが, コロンのあいだに白文字以外の文字がない場合に限る.


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

20.15.3 Cの欲張りな削除機能

欲張りな削除機能をオン (モード行のモード名のあとに‘/h’か‘/ah’で表示される)にすると, 1つの<DEL>コマンドで, 直前の空白1つだけでなく, 白文字すべてを削除します. この機能をオン/オフにするには, C-c C-dを使います.

C-c C-d

欲張り削除機能(c-toggle-hungry-state)をオン/オフする. 数引数を指定した場合, 正ならば欲張り削除機能をオンにし, 負ならばオフにする.

C-c C-t

自動改行機能と欲張り削除機能を同時にオン/オフする (c-toggle-auto-hungry-state).

変数c-hungry-delete-keyは, 欲張り削除機能がオンかオフかを制御します.


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

20.15.4 Cモードのその他のコマンド

C-M-h

関数定義の末尾にマークを設定し, 先頭にポイントを置く (c-mark-function).

M-q

CやC++のコメントを考慮して, 段落を詰め込む (c-fill-paragraph). 現在行にコメントがあったり, 現在行がコメントの内側なら, コメントの字下げとコメント区切りを保存したまま, ポイント位置のコメントや段落を詰め込む.

C-c C-e

リージョン内のテキストに対してCプリプロセッサを実行し, マクロ呼び出しを展開した結果を表示する(c-macro-expand). リージョンのまえにあるテキストにマクロ定義があることもあるので, それらもプリプロセッサに渡されるが, その部分の出力は表示しない.

マクロを用いたCのコードをデバッグするとき, どのようにマクロが展開されるか正確に理解するのが難しいことがある. このコマンドを使えば, マクロ展開のことを考える必要はない. 展開結果を目にすることができる.

C-c C-\

リージョン内の行末に‘\’文字を挿入したり, 行末の‘\’の位置揃えを行う(c-backslash-region). Cのマクロ定義を書いたり編集したあとに便利なコマンド.

行末がすでに‘\’で終っているなら, そのまえに置く白文字の個数を調整する. そうでなければ, 新たに‘\’を挿入する. ただし, リージョン内の最後の行は特別扱いする. その行に‘\’を挿入することはなく, また, ‘\’がある場合には削除する.

M-x cpp-highlight-buffer

プリプロセッサ指令の条件節に従って, テキストの一部を強調表示する. このコマンドは‘*CPP Edit*’という名前のバッファを表示する. このバッファは, 特定のプリプロセッサ条件とその内容をどのように表示するかを 選択するグラフィックメニュー. さまざま設定を変更したあとで, ‘[A]pply these settings’をクリックする (あるいは, そのバッファへ移動してaと打つ)と, 設定に応じてCモードのバッファを強調表示し直す.

C-c C-s

現在のソース行に関する構文上の情報を表示する (c-show-syntactic-information). この情報は行の字下げを指示する.


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

20.15.5 Cモードのコメント

Cモードとその関連モードでは, コメントの整形にいくつかの変数を使います.

c-comment-only-line-offset

コメント開始部分だけを含んだ行に与える余分のオフセット. この変数の値は整数, あるいは (non-anchored-offset . anchored-offset)の形の コンスセルのどちらでもかまわない. ここで, non-anchored-offsetは, 1桁目以降から始まるコメントに与えるオフセット. anchored-offsetは, 0桁目から始まるコメントに与えるオフセット. 整数値だけの場合は, (val . 0)と等価.

c-comment-start-regexp

コメント開始の識別方法を指定するバッファにローカルな変数.

c-hanging-comment-ender-p

この変数がnilであると, c-fill-paragraphは, ブロックコメントのコメント終了区切りだけの行を作る. デフォルト値はtで, コメント終了区切り‘*/’をコメントの最後の行の末尾に置く.

c-hanging-comment-starter-p

この変数がnilであると, c-fill-paragraphは, ブロックコメントのコメント開始区切りだけの行を作る. デフォルト値はtで, コメント開始区切り‘/*’をコメントの最初の行の先頭に置く.


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

20.16 Fortranモード

Fortranモードには, Fortranの文と副プログラム向けの特別な移動コマンド, Fortranの入れ子, 行番号と継続文の約束事に従う字下げコマンドがあります. Fortranモードには, 長い行を適切なFortranの継続行に分ける 専用の自動詰め込み(fortran-auto-fill)モードがあります.

Fortranのコメントは他の言語のコメントとは異なっているので, コメントに対する特別なコマンドもあります. Fortranのキーワードを入力するときの打鍵量を減らせる, 組み込みの略語もあります.

Fortran用のメジャーモードに切り替えるには, M-x fortran-modeを使います. このコマンドは, フックfortran-mode-hookを実行します(see section フック).


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

20.16.1 移動コマンド

Fortran モードには, 副プログラム(関数やサブルーチン)や文を単位とて 移動するための特別なコマンドがあります. また, 副プログラムを囲むリージョンを設定するコマンドもあり, 副プログラムをキルしたり移動したりするのに便利です.

C-M-a

副プログラムの先頭に移動する(beginning-of-fortran-subprogram).

C-M-e

副プログラムの末尾に移動する(end-of-fortran-subprogram).

C-M-h

副プログラムの先頭にポイントを置き, 末尾にマークを設定する (mark-fortran-subprogram).

C-c C-n

現在の文かつぎの文の先頭に移動する(fortran-next-statement).

C-c C-p

現在の文かまえの文の先頭に移動する (fortran-previous-statement).


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

20.16.2 Fortranの字下げ

Fortranのコードでは, 構文上の各種要素(行番号, コメント行指示子, 継続マーク)は標準Fortranが要求する桁に現れるようにしなくてはいけないので, 字下げに関する特別なコマンドと機能が必要です.


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

20.16.2.1 Fortranの字下げコマンド

<TAB>

現在行を字下げする(fortran-indent-line).

C-j

現在行を字下げしてから, 字下げした新たな行を始める (fortran-indent-new-line).

C-M-j

ポイント位置で現在行を分割し, 継続行を設定する.

M-^

現在行と直前の行を繋げる.

C-M-q

ポイントを含む副プログラムの行をすべて字下げする (fortran-indent-subprogram).

Fortranモードでは, Fortranの行を字下げするように<TAB>を再定義します (fortran-indent-line). このコマンドは, 行番号と継続マークを要求される桁位置に字下げしたうえ, それとは独立にプログラム中の入れ子に基づいて文本体を字下げします.

キーC-jfortran-indent-new-lineを実行します. これは, 現在行を字下げしてから, 新たな行を作成して字下げします. 新たな行を始めるまえに, ‘do’ループやその他のブロックを 閉じる文を字下げし直すのに便利です.

キーC-M-qは, ポイントを含むFortranの副プログラム (関数やサブルーチン)の行すべてを字下げする コマンドfortran-indent-subprogramを実行します.

キーC-M-jは, 適切な方法でFortranの行を分割するコマンド fortran-split-lineを実行します. コメント行でなければ, 後半部を継続行にし, それに応じて字下げします. コメント行ならば, 前後半部分とも独立したコメント行になります.

M-^は, fortran-split-lineの逆操作を行う コマンドfortran-join-lineを実行します. 現在行と直前の行を, Fortranコードとして適切に繋げます.


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

20.16.2.2 継続行

近代的なほとんどのFortranコンパイラには, 継続行の記述方法が2つ用意されています. ある行の空白でない最初の文字が5桁目にあれば, 先行する行の継続行です. このスタイルを固定フォーマットと呼びます. (GNU Emacsでは, 桁位置はつねに0から数える. ) 変数fortran-continuation-stringは, 5桁目に置く文字を指定します. タブ文字で始まり‘0’以外の数字が続く行も継続行です. このスタイルをタブフォーマットと呼びます.

Fortranモードではどちらのスタイルの継続行も利用できますが, 希望するほうを指定する必要があります. 変数indent-tabs-modeの値で希望を指定します. nilならば固定フォーマット, nil以外ならばタブフォーマットになります. モード行に文字列‘Tab’があるかどうかで, 現在使用しているスタイルがわかります.

Fortranモードでは, テキストが慣用的なFortranの継続マーク‘$’で始まる, あるいは, 5桁目から白文字以外の文字で始まる場合には, その行を継続行として扱います. <TAB>で継続行を字下げすると, 選択されている継続行のスタイルに変換します. C-M-jでFortranの文を分割すると, 継続行のスタイルに応じて新たな行には継続マークを付けます.

継続行のスタイルは, Fortranモードでの編集に関わる その他の側面にも影響します. 固定フォーマットでは, 文本体を置く最小桁位置は6になります. Fortranのブロックの内側にある行を7桁目以降に字下げするときには, 白文字には空白文字を使います. 一方, タブフォーマットでは, 文本体を置く最小桁位置は8で, 8桁目よりまえの白文字はつねにタブ文字です.

既存のファイルに対してFortranモードに入ると, その内容から自動的に適切な継続行のスタイルを推測しようとします. タブ文字か空白6個で始まる最初の行でスタイルを判断します. 変数fortran-analyze-depthで, (ファイルの先頭から)何行分をスタイル判断に使用するか指定します. この範囲内にスタイルを示すような行がみつからなければ, 変数fortran-tab-mode-defaultがスタイルを指定します. nilなら固定フォーマット, nil以外ならタブフォーマットです.


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

20.16.2.3 行番号

ある行の白文字以外の最初の文字が数字であれば, Fortranの字下げではそれを行番号とみなして0桁目から4桁目のあいだに移動します. (GNU Emacsでは, 桁位置はつねに0から始まる. )

通常, 4桁以下の行番号は空白1個で字下げします. 変数fortran-line-number-indentでこの字下げ幅を制御します. この変数の値は, 行番号の最大字下げ幅を表します. 最大字下げ幅まで字下げできなくなると, 行番号の最後の桁が4桁目になるように右揃えで字下げします. この変数のデフォルト値は1です.

これらの規則に従って行番号を字下げするには, 行番号を挿入するだけで十分です. 行番号の各桁が挿入されるたびに, 字下げ幅を再計算します. この機能をオフにするには, 変数fortran-electric-line-numbernilを設定します. こうすると, 行番号の挿入はその他の文字の挿入と同様に行われます.


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

20.16.2.4 構文上の規約

Fortranモードでは, 適切な字下げをするためのFortranプログラムの解釈を 簡単にするために, 以下の規約に従っているものと仮定します.

以上の規約に従っていない場合には, 行を美しく字下げできないこともあります. しかしながら, たとえ規約に従っていなくても, 正しいFortranプログラムであれば字下げによって意味が変わることはありません.


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

20.16.2.5 Fortranの字下げのための変数

Fortranの字下げ動作に影響する変数がいくつかあります.

fortran-do-indent

do’文の各レベルごとに追加する字下げ幅(デフォルトは3).

fortran-if-indent

if’文の各レベルごとに追加する字下げ幅(デフォルトは3). この値は, Fortran 90の‘where’文の字下げにも使われる.

fortran-structure-indent

structure’, ‘union’, ‘map’の各文の各レベルごとに 追加する字下げ幅(デフォルトは3).

fortran-continuation-indent

継続行の文本体に追加する字下げ幅(デフォルトは5).

fortran-check-all-num-for-matching-do

この変数がnilなら, 字下げ処理では, ‘do’文は‘continue’文で終っていると仮定する. こうすると, ‘continue’以外の文の字下げを計算するときに, 当該文が‘do’文を終えるかどうか検査しなくてよいので, 時間を節約できる. この変数がnil以外であれば, 行番号が付いた文の字下げを計算するときには, 当該文が‘do’文を終えるかどうか検査する必要がある. デフォルト値はnil.

fortran-blink-matching-if

この変数がtなら, ‘endif’文の字下げを行うときに, 対応する‘if’文を示すために一時的にカーソルを移動する. デフォルト値はnil.

fortran-minimum-statement-indent-fixed

固定フォーマットの継続行スタイルを採用したときの, 文に対する最小字下げ幅. 文本体の字下げ幅がこの値より小さくなることはない. デフォルト値は6.

fortran-minimum-statement-indent-tab

タブフォーマットの継続行スタイルを採用したときの, 文に対する最小字下げ幅. 文本体の字下げ幅がこの値より小さくなることはない. デフォルト値は8.


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

20.16.3 Fortranのコメント

Emacsの通常のコメント用コマンドは, コメントをコードのあとにも置けると仮定します. Fortranでは, 標準的なコメントの構文は, 1つの行全体を必要とします. そのため, Fortranモードでは, Emacsの通常のコメント用コマンドを置き換え, 新たな変数をいくつか定義しています.

Fortranモードでは, 文字‘!’で始まり他のテキストのあとにも置ける 非標準的なコメントの構文も扱えます. しかし, この構文を受け付けるFortranコンパイラは限られるため, まえもって指定しておかない限り, Fortranモードは非標準のコメントを使いません. このスタイルのコメントを使うには, 変数comment-startに‘"!"’を設定します(see section 変数).

M-;

コメントの位置を揃えたり, 新たなコメントを挿入する (fortran-indent-comment).

C-x ;

非標準の‘!’コメントだけに作用する.

C-c ;

リージョン内のすべての行をコメントにする. あるいは, (引数を指定すると)コメントをコードに戻す (fortran-comment-region).

FortranモードのM-;は, コマンドfortran-indent-commentに再定義されています. 通常のM-;と同じく, 既存のコメントを認識して, そのテキストの桁位置を揃えます. コメントがなければ, コメントを挿入して桁位置を揃えます. しかし, Fortranモードのコメントの挿入と揃え方は, 他のモードと同じではありません.

新たにコメントを挿入する場合, 現在行が空行のときは(1行全体を占める)行コメントを挿入します. 空行でないとき, 非標準のコメントを使うように指定してあれば 非標準の‘!’コメントを挿入します. いずれでもないときには, 現在行のまえに行コメントを挿入します.

非標準の‘!’コメントは他の言語のコメントと同じように揃えられますが, 行コメントの場合はようすが異なります. 標準の行コメントでは, コメント区切りはつねに0桁目にある必要があります. コメント内部のテキストだけを揃えます. fortran-comment-indent-styleを設定して, 3種類の揃え方を選べます.

fixed

fortran-comment-line-extra-indentと文に対する最小字下げ幅を合計し た桁位置にテキストを揃える. デフォルトはこれ.

文の最小字下げ幅は, 固定フォーマットの継続行スタイルの場合には fortran-minimum-statement-indent-fixedの値, タブフォーマットの場合にはfortran-minimum-statement-indent-tabの値.

relative

コード行であるかのように揃えるが, fortran-comment-line-extra-indentだけ余計に桁をずらす.

nil

行コメントのテキストを勝手に動かさない.

また, 行コメントの字下げ文字を変更したければ, 変数fortran-comment-indent-charに好みの1文字を設定してください.

Fortranモードには, comment-line-startcomment-line-start-skipの2つの変数が新たに導入されています. これらは, コードのあとに置く通常のコメントに対するcomment-startcomment-start-skipと同様の役割を, 行コメントに対して果たします. どちらもFortranモードが適切に設定するので, 変更する必要はありません.

Emacsの通常のコメント用コマンドC-x ;は, 再定義されていません. このコマンドは‘!’コメントを扱えます. ‘!’コメントを使っていない場合には, このコマンドはFortranモードでは役に立ちません.

コマンドC-c ;fortran-comment-region)は, リージョン内のすべての行の先頭に‘C$$$’を挿入して コメントに変えます. 数引数を指定すると, 行の先頭から‘C$$$’を削除して, リージョンを生きたコードに戻します. これらのコメントに使う文字列は, 変数fortran-comment-regionの設定で制御できます. ところで, ここではコマンドと変数に同じ名前が使われています. LispやEmacsにおいては, 使用される文脈から コマンドと変数をつねに区別できるので, このような名前の使い方が問題を起こすことはありません.


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

20.16.4 Fortran専用自動詰め込み(fortran-auto-fill)モード

Fortran専用自動詰め込み(fortran-auto-fill)モードは, 挿入したFortranの文が長くなりすぎると自動的に文を分割するマイナモードです. 文を分割するには, fortran-continuation-string(see section 継続行)を用いて 継続行を作ります. <SPC>, <RET>, <TAB>を打ったときや, 字下げコマンドを使ったときに分割されます.

M-x fortran-auto-fill-modeは, Fortran専用自動詰め込み(fortran-auto-fill)モードがオンならばオフにし, オフならばオンにします. このコマンドは, 通常の自動詰め込み(auto-fill)モード (see section テキストの詰め込み)であるM-x auto-fill-modeが行うのと 同じように働きます. 正の数引数を指定すると, Fortran専用自動詰め込み(fortran-auto-fill)モードをオンにし, 負であればオフにします. このモードのオン/オフは, モード行の括弧の中に‘Fill’が あるかどうかで判断できます. Fortran専用自動詰め込み(fortran-auto-fill)モードはマイナモードなので, 各バッファごとに独立にオン/オフにできます. See section マイナモード(minor mode).

Fortran専用自動詰め込み(fortran-auto-fill)モードは, 行の長さが規定の幅(fill-columnの値)を越えると, 空白や区切りの位置で行を分割します. Fortran専用自動詰め込み(fortran-auto-fill)が分割する区切りは, ‘,’, ‘'’, ‘+’, ‘-’, ‘/’, ‘*’, ‘=’, ‘)’です. 変数fortran-break-before-delimitersnilの場合には, 区切りのうしろで分割します. それ以外(デフォルトでもある)では, 区切りのまえで分割します.

デフォルトではFortran専用自動詰め込み(fortran-auto-fill)モードはオフです. この機能を恒常的に使いたければ, (fortran-auto-fill-mode 1)を実行するフック関数を fortran-mode-hookに追加してください. See section フック.


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

20.16.5 桁位置の確認

C-c C-r

現在行の上にしばらくのあいだ『桁定規』を表示する (fortran-column-ruler).

C-c C-w

現在のウィンドウを一時的に分割して幅を72桁にする. 一部のFortranコンパイラは1行を72文字以内に制限しているので, このコマンドを使用すれば1行が長くなりすぎることを防げる (fortran-window-create-momentarily).

コマンドC-c C-rfortran-column-ruler)は, 桁定規をしばらくのあいだ, 現在行の上に表示します. 桁定規は, Fortranプログラムにおいて特別な意味をもつ桁位置を表す 2行のテキストです. 2行目の角括弧と中括弧で, それぞれ, 行番号と文の本体の範囲を表します. 桁番号は(それらの上の)1行目に表示されます.

GNU Emacsでは桁番号をつねに0から数えることに注意してください. その結果, 桁定規に示される桁番号は, 慣れ親しんだものより1だけ小さくなります. しかし, それらが表す位置はFortranの標準に従ったものです.

桁定規の表示に用いるテキストは, 変数indent-tabs-modeの値に依存します. この変数の値がnilならば, 変数fortran-column-ruler-fixedの値を桁定規の表示に使います. nil以外であれば, 変数 fortran-column-ruler-tabの内容を表示に使います. これらの変数の内容を変更すれば, 桁定規の表示を変更できます.

さらに桁合わせを支援するために, C-c C-wfortran-window-create)は, 現在のウィンドウを幅が72桁になるように横位置で分割します. このウィンドウで編集すれば, 正しいFortranのプログラムとしては長すぎる行を即座に発見できます.


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

20.16.6 Fortranのキーワードの略語

Fortranモードには, 一般的なキーワードや宣言に対する 数多くの組み込み略語があります. これらは, ユーザー自身が定義できる略語と同じ種類のものです. それらを使うには, 略語(abbrev)モードをオンにします. See section 略語の利用法.

組み込み略語は他の略語と1つの点で変わっています. すべてセミコロンで始まります. 通常は略語にはセミコロンを使えませんが, Fortranモードでは, セミコロンの構文上の意味を『単語を構成する文字』に 変更することで, これを可能にしています.

たとえば, ‘continue’に対する組み込みFortran略語は‘;c’です. 略語(abbrev)モードがオンのときに, ‘;c’を挿入してから空白や改行といった句読点文字を挿入すると, ‘;c’は自動的に‘continue’と展開されます.

組み込みFortran略語とその展開形の一覧を表示するには, ‘;?’あるいは‘;C-h’と打ちます.


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

20.16.7 Fortranモードのその他のコマンド

C-x n d

現在のFortranの副プログラムにナロイングする.

Fortranモードでは, キーC-x n dはコマンドfortran-narrow-to-subprogramを実行するように 再定義しています. このコマンドは, キーの通常の定義をFrotran風にしたものです. バッファをポイントを含む副プログラムにナロイングします.


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

20.17 asmモード

asmモードは, アセンブリコードのファイルを編集するためのメジャーモードです. つぎのコマンドが定義されています.

<TAB>

tab-to-tab-stop.

C-j

改行を挿入し, tab-to-tab-stopで字下げする.

:

コロンを挿入し, コロンに先行するラベルのまえの字下げを取り除く. そして, tab-to-tab-stopを行う.

;

コメントの挿入/位置揃えを行う.

変数asm-comment-charは, アセンブラ構文でコメントを開始する文字を指定します.


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

This document was generated by 新堂 安孝 on September 22, 2009 using texi2html 1.82.