*indent.txt* For Vim version 6.1. Last change: 2001 Nov 01 VIMリファレンスマニュアル by Bram Moolenaar (訳 村岡太郎) このファイルにはCソースコードとその他のファイルのインデント(字下げ)について書 かれている。 1. Cソースコードのインデント |C-indenting| 2. スクリプトを用いたインデント |indent-expression| ============================================================================== 1. Cソースコードのインデント *C-indenting* C言語ソースコード(以下、単に「C」)用インデントの基本はユーザマニュアルの|30.2| 節で説明されている。 VimにはCを自動的にインデントするためのオプションがある。これらのオプションはイ ンデントだけに影響し、その他の整形には意味をなさない。コメントの整形については |format-comments|を参照。 コンパイル時に|+smartindent| か |+cindent|機能を無効にした時には、これが動作し ないことに注意。 実際のところインデントには4つの方法がある: 'autoindent' 一つ前の行に基づくインデント 'smartindent' 'autoindent'と同様だが幾つかのC構文を認識し、適切な箇所のイン デントを増減させる。 'cindent' 他の2つの方法よりも賢く動作し、設定することで異なるインデント スタイルにも対応できる。 'indentexpr' The most flexible of all: Evaluates an expression to compute the indent of a line. When non-empty this method overrides the other ones. See |indent-expression|. この中で一番融通が利く: ある行のインデントを計算するのにVimス クリプトを実行する。この方法が有効である(空でない)時にはその他 のインデントは抑制される。|indent-expression|参照 この節の残りはオプション'cindent'について述べる。 'cindent'はあらゆるCソースを正しくインデントできるわけではないことに注意。Vim はCコンパイラではない: だから全ての構文は認識できない。 Cのインデントはこの4つのオプションで制御されている: 'cindent' Cの自動インデントを有効化する。 'cinkeys' 再インデントの引金となる挿入モードでのキーを指定する。 'cinoptions' 好みのインデントスタイルを設定する。 'cinwords' 次の行から特別なインデントを開始するキーワードを定義する。 オプション'lisp'がオフで'equalprg'が空ならば、オペレータ"="は外部プログラムで はなくVimの内蔵アルゴリズムを使用してインデントを行なう。 Cのファイルに対して自動的に'cindent'をオンにしてそれ以外のファイルに対してはオ フにする方法は|autocommand|を参照。 (訳注: バージョン6.0以降はファイル形式プラグイン(|filetype|参照)とバッファロー カルオプション(|:setlocal|)を使うことが推奨される。VimにはデフォルトでC用の ファイル形式プラグイン($VIMRUNTIME/ftplug/c.vim)が付属しているから、これを行な いたい時は単にファイル形式プラグインを有効化するだけで良い。) *cinkeys-format* *indentkeys-format* オプション'cinkeys'はVimのインデントを制御する文字列で、どの文字がタイプされた 時に、どのような状況下でコマンドが実行されたかに応じてインデントを行なうかを定 義する。これがCインデントの唯一の引金ではないことには注意する。'indentexpr'が 空でない時には代わりに'indentkeys'が使われる。'cinkeys'と'indentkeys'の書式は 同じ。 デフォルトは "0{,0},0),:,0#,!^F,o,O,e" で、これにより次のような時にインデント が行なわれる: "0{" 行の先頭で '{' をタイプした時 "0}" 行の先頭で '}' をタイプした時 "0)" 行の先頭で ')' をタイプした時 ":" ラベルやcase文のあとで ':' をタイプした時 "0#" 行の先頭で '#' をタイプした時 "!^F" CTRL-Fをタイプした時 (CTRL-F自体は入力されない) "o" 挿入モードでをタイプした後、及びノーマルモードで "o" コマ ンドを使用した時 "O" ノーマルモードで "O" コマンドを使用した時 "e" 行の先頭で "else" の2つ目の 'e' をタイプした時 各キーの前に置くことのできる文字は次の通り: ! '!' をキーの前に置くと、Vimはそのキーを挿入するのではなく替わりに現在 の行のインデントを再調整する。これにより現在の行の再調整するためのコマ ンドキーを定義することができる。CTRL-Fはそのデフォルトキーである。 CTRL-Iはのアスキーコードだから、CTRL-Iを定義する際に気をつけるこ と。 * '*' をキーの前に置くと、Vimはインデント再調整を行なってからそのキーを 挿入する。'cinkeys' に "*"が含まれている時には、Vimは新しい行 を作成する前に現在行のインデントを再調整する。 0 '0' をキーの前 ('!' や '*'の後ということはあるが) に置くと、Vimはその キーが行の先頭で入力された時だけインデント再調整を行なう。"=" の前に使 われた時にはVimはその単語の前に空白文字しか無い時にだけ再調整が行なわ れる。 '!' と '*'のいずれもキーの前に置かれていない時は、Vimはそのキーがタイプされた 時にインデント再調整を行なう。だから ';' を含めれば ';' が入力された行のインデ ントが調整される。 特別なキーの名称: <> 折カッコは書き下されたキーの名前を意味する。例: "" や "" (|key-notation|参照)。 ^ キャレット(^)が前に置かれた文字はコントロール文字。例: "^F"はCTRL-F o "o"コマンドを使用した時もしくはVimが現在の行の下に新しい行を作成した時 にインデント再調整をする(例えば、挿入モードでをタイプした時)。 O "O"コマンドを使用した時にインデント再調整をする。 e "else"で始まる行の2つ目の'e'をタイプした時にインデント再調整をする。 : ラベルやcase文の後に':'をタイプした時にインデント再調整をする。C++の "class::method"内の":"では再調整しない。どんな":"でもインデントするに は"<:>"を使用する。 =word "word"の最後の文字をタイプした時にインデント再調整をする。"word"は実際 は別の単語の一部かもしれない。"=end"のように設定すれば"endif" や "endwhile" の "d"をタイプした時に再調整が起こる。しかし"bend"では起こ らない。補完により"word"で始まる単語が提示された時にも再調整は起こる。 "0=word"は単語の前に空白文字しかない時に再調整を行なう。 =~word は =wordに似ているが、大文字小文字の区別がされない。 キー 'o', 'O', 'e', '0', '<', '>', '*', ':' それに '!' そのものを入力した時に インデント再調整を行ないたいのならば、それぞれ "", "", "", "<0>", "<<>", "<>>", "<*>", "<:>" そして "" を使用する。 Enterを押す度ではなくemacsのようにTabキーを押した時にだけインデントを行なうよ うにするには、次の設定を提案する: > :set cinkeys=0{,0},:,0#,!,!^F その時には'autoindent'もオフにしたほうが良いかもしれない。 NOTE: 現在の行のインデントを手動で変更すれば、Vimはその行についてはcindentの設 定を無視する。これによりインデントの中で, を入力したり、 CTRL-TやCTRL-Dを使用してインデントを変更した後では、Vimはインデントの再調整を 行なわなくなる。 *cinoptions-values* オプション'cinoptions'ではVimがどのようなインデントを行なうのかを設定する。以 下のリストでは、"N" は指定したい数値を意味する(数値は負でも良い)。数値のあとに 's'がある時には、数値に'shiftwidth'の数を掛算して使用する: "1s"はshiftwidth'に 等しく、"2s"は'shiftwidth'の2倍になり、以下同様。小数を使うこともできる: "-0.5s"は'shiftwidth'の半分の負の数である。以下の例では'shiftwidth'は4と想定し ている。 >N 通常のインデントで追加される量。インデントを増やすべき行(ifで始 まる行や、開き波カッコ等)の直後で使用される。 (省略値 'shiftwidth') cino= cino=>2 cino=>2s > if (cond) if (cond) if (cond) { { { foo; foo; foo; } } } < eN 開き波カッコが行末にある(正確には行頭ではない)時に、カッコ内のイ ンデントを通常よりも N 追加する。'{'が行頭ある場合と行末にある場 合とでインデント量を変更したい時に便利。 (省略値 0) cino= cino=e2 cino=e-2 > if (cond) { if (cond) { if (cond) { foo; foo; foo; } } } else else else { { { bar; bar; bar; } } } < nN "if", "while" その他の直後、波カッコのセットに囲まれていないなら ば、その文のインデントを現行よりも N 追加する。文の前に '{' が無 い時と有る時とでインデント量を変更したい時に便利。 (省略値 0) cino= cino=n2 cino=n-2 > if (cond) if (cond) if (cond) foo; foo; foo; else else else { { { bar; bar; bar; } } } < fN 関数やその他のブロックを示す開き波カッコを N 列目に配置する。こ れは他の波カッコの内側ではなく、かつ行頭である開き波カッコだけに 適用される。波カッコの後の続くものはこの波カッコと相対的な位置に 配置される。 (省略値 0) cino= cino=f.5s cino=f1s > func() func() func() { { { int foo; int foo; int foo; < {N 開き波カッコを現行のインデントから N の位置に配置する。これは他 の波カッコの内側にある開き波カッコにのみ適用される。 (省略値 0) cino= cino={.5s cino={1s > if (cond) if (cond) if (cond) { { { foo; foo; foo; < }N 閉じ波カッコを対応する開き波カッコから N の位置に配置する。 (省略値 0) cino= cino={2,}-0.5s cino=}2 > if (cond) if (cond) if (cond) { { { foo; foo; foo; } } } < ^N 開き波カッコが 0 列目にある波カッコセットの内側のインデントを現 行よりも N 追加する。これにより関数全体には異なるインデント量を 指定することができる。 (省略値 0) cino= cino=^-2 cino=^-s > func() func() func() { { { if (cond) if (cond) if (cond) { { { a = b; a = b; a = b; } } } } } } < :N caseラベルをswitch()のインデントから N の位置に配置する。 (省略値 'shiftwidth') cino= cino=:0 > switch (x) switch(x) { { case 1: case 1: a = b; a = b; default: default: } } < =N caseラベル後に現れる文をラベルのインデントから N の位置に配置す る。 (省略値 'shiftwidth') cino= cino==10 > case 11: case 11: a = a + 1; a = a + 1; b = b + 1; < lN N が 0 でなければVimはcaseラベル後の文の替わりに、caseラベルそ のものを基本にして配置を行なう。 (省略値 0) cino= cino=l1 > switch (a) { switch (a) { case 1: { case 1: { break; break; } } < gN C++のスコープ宣言をそれが含まれるブロックのインデントから N の位 置へ配置する。"public:", "protected:", "private"がスコープ宣言に なり得る。 (省略値 'shiftwidth') cino= cino=g0 > { { public: public: a = b; a = b; private: private: } } < hN C++スコープ宣言後に現れる文をそのラベルのインデントから N の位置 に配置する。 (省略値 'shiftwidth') cino= cino=h10 > public: public: a = a + 1; a = a + 1; b = b + 1; < pN K&Rスタイルの関数宣言の引数宣言を N 文字インデントする。 (省略値 'shiftwidth') cino= cino=p0 cino=p2s > func(a, b) func(a, b) func(a, b) int a; int a; int a; char b; char b; char b; < tN 関数の戻り型の宣言を N 文字インデントする。 (省略値 'shiftwidth') cino= cino=t0 cino=t7 > int int int func() func() func() < +N 継続した行(次の行へと分割された行)を N でインデントする。 (省略値 'shiftwidth') cino= cino=+10 > a = b + 9 * a = b + 9 * c; c; < cN コメント開始子の後のコメント本文を、配置すべきその他のテキストが 無ければ、コメント開始子から N 文字でインデントする。 (省略値 3) |format-comments|も参照。 cino= cino=c5 > /* /* text. text. */ */ < CN N が0でなければ、コメント開始子の後に他のテキストがある場合で も、コメントの行に c フラグで指定した量でインデントがされる。 (省略値 0) cino=c0 cino=c0,C1 > /******** /******** text. text. ********/ ********/ < (":set comments& comments-=s1:/* comments^=s0:/*" を同時に設定) (N 閉じていない丸カッコ内では開き丸カッコのあるラインより N 文字イ ンデントする。インデント量は1つの丸カッコにつき 'shiftwidth'ずつ 増える。N が 0 であるか、閉じていない丸カッコが行頭にある時は、 インデント位置はそのカッコ後の非空白文字の位置になる。 (省略値 'shiftwidth' * 2) cino= cino=(0 > if (c1 && (c2 || if (c1 && (c2 || c3)) c3)) foo; foo; if (c1 && if (c1 && (c2 || c3)) (c2 || c3)) { { < uN Same as (N, but for one level deeper. (default 'shiftwidth'). (N と同じだが、一段階内側の丸カッコについての設定。 (省略値 'shiftwidth') cino= cino=u2 > if (c123456789 if (c123456789 && (c22345 && (c22345 || c3)) || c3)) < UN N が 0 ではない時には、閉じていない丸カッコが行頭にある場合でも ( や u で指定したインデントを無視しない。 (省略値 0) cino= or cino=(s cino=(s,U1 > c = c1 && c = c1 && ( ( c2 || c2 || c3 c3 ) && c4; ) && c4; < wN N が 0 ではなければ次に示すような場合の、閉じていない丸カッコ後 の非空白文字ではなく、カッコ直後の位置がインデントに使用される: - "(0" を使用している時の閉じていない丸カッコ - "u0" を使用している時の閉じていない丸カッコ - "U0" を使用している時の行頭の閉じていない丸カッコ (省略値 0) cino=(0 cino=(0,w1 > if ( c1 if ( c1 && ( c2 && ( c2 || c3)) || c3)) foo; foo; < mN N が 0 でない時には、閉じ丸カッコで始まる行を対応する開き丸カッ コのある行頭に並べる。 (省略値 0) cino=(s cino=(s,m1 > c = c1 && ( c = c1 && ( c2 || c2 || c3 c3 ) && c4; ) && c4; if ( if ( c1 && c2 c1 && c2 ) ) foo; foo; < *java-cinoptions* *java-indenting* jN Javaの無名クラスを正しくインデントする。値 'N' は現在のところ使 われていないが 0 以外(例 'j1')にするべきである。'j1'にすることで 例として次のようなコードが正しくインデントされる: > object.add(new ChangeListener() { public void stateChanged(ChangeEvent e) { do_something(); } }); < )N Vimは N 行まで遡って閉じていないカッコを探す。これはカッコを探す のにかかる時間を制限する。 (省略値 20) *N Vimは N 行まで遡って閉じられていないコメントを探す。これはコメン トの始まりを探すのにかかる時間を制限する。 (省略値 30行) 省略値を全て並べるとこうなる: cinoptions=>s,e0,n0,f0,{0,}0,^0,:s,=s,l0,gs,hs,ps,ts,+s,c3,C0,(2s,us, \U0,w0,m0,j0,)20,*30 次のような場合にはVimは行頭を1列目に持っていく: - 'cinkeys'が '#' を含み行が '#' (プリプロセッサ命令)で始まる場合 - ラベルで始まる場合("case" と "default" 以外のキーワードの後に ':' があった場 合) - インデントの組合わせの結果、その行のインデント量が0以下になった場合。 ============================================================================== 2. スクリプトを用いたインデント *indent-expression* 融通の利くインデントの基本はユーザマニュアルの|30.3|節で説明されている。 独自にインデントファイルを書きたいならば、オプション'indentexpr'を設定しなけれ ばならない。同時にオプション'indentkeys'を設定すると便利だろう。インデントファ イルの例は$VIMRUNTIME/indentディレクトリを参照。 インデントファイルについての覚書 ~ FORTRAN *fortran-indent* ifブロック、select case、そしてwhere構成物がインデントされる。コメント、ラベル 付き文、そして2行にまたがった行は、Fortranが自由形式のソースではインデントされ るが、一方Fortranが固定形式ソースの場合には左余白が言語仕様により決定されてい るのでインデントされない。それ故に固定形式ソースを使っている時にはラベル付き文 と2行にまたがった行については手動でインデントを修正する必要がある。ソース形式 の判定に使われている方法についてのさらなる議論は|fortran-syntax|を参照のこと。 Doループ ~ デフォルトでは全てのdoループはインデントされない。Fortranでは、ループはラベル 付けされたほとんど任意の型の実行可能な文で(場合によっては多重に)終わるので、do ループは非構造的になる。これを正しくインデントするにはコンパイラ級の構文解析が 必要になる。任意の型の実行可能文で終わるdoループを持っていたとしても、古いコー ドであればTidy (http://www.unb.ca/chem/ajit/f_tidy.htm) のように念入りに作られ たプログラムでインデントすることはできる。構造化do/continueループも、continue 文がdoループを終了する以外の目的でも使用されるので、インデントせずに残される。 Tidyのようなプログラムは構造化do/continueループをdo/enddo形式に変換することが できる。do/enddoタイプのdoループならばインデントすることができる。do/enddoの形 の構造化されたループしか使わないのならば、.vimrcで以下のようにfortran_do_enddo 変数を設定してそのことを宣言するべきである: > let fortran_do_enddo=1 このようなすればdoループはインデントされる。例えば拡張子が.f90 であるファイル の中にある全てのループがdo/enddoタイプだけならば、このようなautocommandを使っ てのバッファフラグを設定することができる: > au! BufRead,BufNewFile *.f90 let b:fortran_do_enddo=1 to get do loops indented in .f90 files and left alone in Fortran files with other extensions such as .for. こうすれば.f90のファイル内のdoループはインデントし、それ以外の拡張子、例えば で.forであるFortranのファイルのループはインデントせずに残すことができる。 VERILOG *verilog-indent* 一般的なブロック文であるif, for, case, always, initial, function, specify, そ してbegin等などはインデントされる。moduleブロック文(最初のレベルのブロック)は デフォルトではインデントされない。次のように.vimrcで以下の変数を設定するとその インデントを有効化できる: > let b:verilog_indent_modules = 1 これによりmoduleブロックがインデントされる。これをやめるには変数を削除すれば良 い: > :unlet b:verilog_indent_modules Verilogのファイルにだけこの変数を設定するには、次の設定が使える: > au BufReadPost * if exists("b:current_syntax") au BufReadPost * if b:current_syntax == "verilog" au BufReadPost * let b:verilog_indent_modules = 1 au BufReadPost * endif au BufReadPost * endif その上、インデントの幅を変更するのに変数b:verilog_indent_widthを設定できる (省略値 'shiftwidth'): > let b:verilog_indent_width = 4 let b:verilog_indent_width = &sw * 2 さらに、デバッグ目的でverboseモードを有効化できる: > let b:verilog_indent_verbose = 1 メッセージを表示できるようにするために、先に":set cmdheight=2"を実行することを 確認すること。 vim:tw=78:ts=8:ft=help:norl: