## C editing with VIM HOWTO

Siddharth
Heroor

s_heroor@yahoo.com

芳賀靖史
日本語訳

    yasufumi.haga@nifty.com

v1.0
2001年1月14日
sh
第2版。間違いをいくつか修正。
v0.1
2000年12月4日
sh
初版。フィードバック待ってます。

この文書は、C 言語やC++, Javaといった構文が似た他の言語で 書いたファイルを編集する際の入門編となるものです。

## はじめに

この文書の目的は C 言語で書いてあるファイルをVIMで編集する時に利用 できる、編集オプションをVIMの初心者ユーザーに紹介することです。この 文書ではコマンドやキーストロークをいくつか紹介しますが、こういった ものを使えば、VIMで C 言語のファイルを編集する際の、プログラマの生産 性を上げるのに役立つことでしょう。

この文書の内容は、VIMをどう使えば C 言語のファイルが編集できる のかを解説することです。でもその内容の大半は vi にも適用できるもの だし、さらに、ここで C 言語のファイル編集に関して触れているものは C++ や Java, そして他の似た言語にも大なり小なり適用できるものです。

## 動きまわる

### w, e, および b のキーストローク

ファイルの中を動きまわるにはw, e そして b といったキーが使えます。VIMでは C 言語 のプログラムにある様々なトークンが識別できます。

以下のような C のコードを考えてみます。

#### C プログラムの一部

    		  ...
    		  if(( NULL == x ) && y > z )
    		  ...

カーソルが if 文の先頭の位置にあるとします。 w を一回押すとカーソルが最初の (にジャンプ します。もう一度 w をタイプすると、そのカーソルは NULL に移ります。その次はカーソルが == トークンに移動するでしょう。それ以降の キーストロークでは、次のように移動します。 x... )... &&... y... >... z... そして最後に )... です。

e は w と似ていますが、現在 カーソルがある場所の言葉の最後に移るのであって、その次の言葉の最初 には移らない点だけが違います。

b はwとは正反対で、 カーソルは逆方向に動きます。だから b のキーストロークを使えば後ろ向きに移動できます。

### {, }, [[ と ]] のキーストローク

{ と } は段落から段落へと 移動するのに使います。 C 言語を編集している時には、これらの キーは意味が若干違ってきます。 C 言語では段落というのを 空行で分けられた行の塊だと見なすのです。

例

#### もう一つの C プログラムの一部

    		     ...

    		     C のプログラムステートメント

    		     /* 注釈 */
    		     ...

    		     /* 次のC プログラムステートメント */
    		     ...

上の例では段落が二つ現れています。ある段落から別の段落へは 簡単に移動できます。{ と } というキーを使えばいいのです。{ はカーソルが 段落を追って上の方に移動していき、}はカーソル が段落を追って下の方に移動していきます。

人にはそれぞれコーディングスタイルがあり、ステートメントの 論理的な集まりを、一つ以上の空行で分けて分類しています。

例

#### 別の C プログラムの一部

    		     void function1()
    		     {

    			     /* 宣言 */
    		             int x;
    		             char y;
    		             double z;

    			     /* ある種のコード */
    		             x = 1;
    		             y = 'a';
    		             z = 1.2;

    			     /* 別のコード */
    		             x++;
    		             y++;
    		             z++;
    		     }

{ と } キーはこういった状況 では非常に役立つものです。ある「段落」から別の段落へととても 簡単に移動できるのです。

役に立つもう一つ別のキーの組が[[ と ]] のキーです。これらのキーを使うと 最初の桁にある直前の { やあるいは次の { にジャンプできます。

例

#### C のコードの次の一部

    		     void foo()
    		     {

    			       /* 何行かの C のプログラム */
    		     }

    		     void bar()
    		     {

    			      /* 何行かの別の C のプログラム */
    		     }

foo() を編集していたとして、今度は bar() を編集したいとしましょう。 ここで単に ]] とタイプしてください。すると カーソルは bar() 関数の左括弧 "{" に移るはずです。逆方向は 若干違ってきます。bar() の中ほどにいたとして、[[ とタイプすると、カーソルは最初の "{" 、つまり bar() 自身の最初、 に移動するのです。 foo() の最初に移るにはもう一度 [[ とタイプしなければなりません。でも何回もキーを打つ代わりに、 2[[ とタイプすれば、最少のキーストロークで カーソルを直前の関数の最初にもっていけるのです。

同じようなキーストロークの、もう一つ別の組が ][ と [] です。][ だとカーソルは 最初の桁にある、次の } に移ります。 foo() を編集していたとして foo() の最後に行きたいとします。その場合は ][ でそこに行けます。同様に、bar() の編集中に foo() の最後に行きたい 場合は、[] がカーソルをそこにもっていきます。

キーストロークの覚え方ですが、分けて考えればいいのです。最初の キーストロークは上がるか下がるかを示しています。 [が上がりで、 ] が下がりです。 次のキーストロークは一致する括弧のタイプを示しています。直前の キーストロークと同じならカーソルは { に移動するはずでしょうし、 キーストロークが違えば、カーソルは } に移動するでしょう。

]], ][, [[ および [] のキーストロークで注意することは、 これらが最初の桁にある括弧と一致すると いうことです。もし最初の桁にあるかどうかに関係なく、上方向や 下方向にある括弧すべてを見つけたいとしても、それはできません。 でもVIMのドキュメントには回避策が書かれています。全ての括弧を 見つけるにはキーストロークをマップしなければなりません。 マッピングの時間を節約する、お奨めのマッピングは次のとおりです。

`:map [[ ?{<CTRL-VCTRL-M>w99[{`

`:map ][ /}<CTRL-VCTRL-M>b99]}`

`:map ]] j0[[%/{<CTRL-VCTRL-M>`

`:map [] k$][%?}<CTRL-VCTRL-M>`

### % キーストローク

% はカーソルのところにあるものに一致するものを 見つけるのに使います。カーソルのところにあるものは、小括弧でも、 中括弧、大括弧でもかまいません。% キーを押せば、カーソルは対応 する一致した括弧へジャンプするでしょう。

数ある中でも、% キーストロークは #if, #ifdef, #else #elif および #endif と一致するものを見つける のに使えます。

このキーストロークは他人が書いたコードを確認する際に非常に 役立つものです。

#### 次の C のコードの一部

    		     ...
    		     if((x==y)&&((z-=a)||(y>x)))
    		     ...

上記のコードをチェックする場合には括弧が正しいこともチェック します。% はある括弧から（対応する括弧まで） ジャンプするのに使えます。その逆も同じです。このように、どの 左括弧がどの右括弧に対応するのかを見つけたり、その情報を使って コードを確認するのに使うのです。

同じように、% はある { から対応する } にジャンプ するのにも使えます。

## C のファイルの中の勝手な位置にジャンプ

### ctags

タグというのは、場所の情報を保持する類のものです。これは C 言語 を理解したりそのファイルを編集したりする場合に非常に役立つもの です。またある関数が呼ばれている場所からその定義場所にジャンプ したり、そこから戻ったりする場合にもとても役立ちます。

以下を例にとります。

#### タグの例

    		     ...
    		     foo()
    		     {
    		             ...
    		             bar();
    		             ...
    		     }

    		     bar()
    		     {
    		             ...
    		     }
    		     ...

今 foo() を編集中に関数 bar() まで行くとしましょう。さて、bar() が何をしているのかを知るにはタグを利用します。この関数の定義に ジャンプして、それから後で戻ってきます。必要なら bar() の中で 呼んでいる別の関数にジャンプして、戻ってくることもできます。

タグを使うには、最初にすべてのソースファイルで ctags プログラム を実行しなければなりません。このプログラムは tags というファイル を生成します。この tags というファイルにはすべての関数定義を 指しているポインターが入っており、VIMはその関数定義の場所に 行くのにこのファイルを使います。

ジャンプして行き来するのに使う実際のキーストロークは、 CTRL-] と CTRL-Tになります。 foo() の中の bar() をコールしている場所で CTRL-] を打つと、カーソルを bar() の最初にもっていきます。 hitting CTRL-T を打てば、 bar() からfoo() へ ジャンプして戻れます。

ctags は次のようにして呼び出します。

    	    $ ctags options file(s)

現在のディレクトリにある *.c ファイル全部から tags ファイルを 作る場合、する必要があるのは以下のことだけです。

    	    $ ctags *.c

別々のサブディレクトリに C のファイルがあるようなソースツリー の場合には、そのソースツリーの一番上で -R オプションを付けて ctags を呼びます。するとそのソースツリーにあるすべての関数 のタグが入った tags ファイルができます。例えば以下のようにします。

    	    $ ctags -R *.c

ctags には他にもたくさんのオプションが使えます。これらの オプションの説明は ctags の man ファイルにあります。

### マーク

マークというのはタグと同じような、場所の情報を保持するものですが、 マークはファイル中のどの場所にでも設定できるし、関数や enum （列挙型）に限定されるものでもありません。さらに、マークは ユーザーが手動で設定しなければなりません。

マークを設定しても、同じものが目に見える形で現れるわけでは ありません。マークというのはVIMが覚えているファイルの中の 場所というだけなのです。次のコードを考えてみます。

#### マークの例

    		     foo()
    		     {
    		             int x,y;
    		             x=0;
    		             y=1;
    		             x++;
    		             y++;
    		             if( x != y )
    		                     x = y;
    		             y = x;
    		     }

今 x++; の行を編集中に他の行を編集し、そのあとまたこの行に 戻ってきたいとしましょう。この場合、m' という キーストロークでこの x++; の行にマークを設定できるし、 '' を打てば、後でこの同じ行に戻ってこれます。

VIMではマークは複数設定できます。これらのマークは a-z や A-Z それに 1-0といったレジスタに格納されます。 マークを設定して、その同じものをあるレジスタ、例えば j に 格納するには mj と打てば済みます。この マークに戻ってくるには、 'j と打てば済みます。

複数のマークを使うと、まとまったコードの中で行ったり来たり する際に本当に役立ちます。同じ上記の例を使いましょう。 x++; で 一つマークして、 y=x; でもう一つ、そしてそれらの間をジャンプ したり、あるいは他の場所にジャンプして、それからジャンプして 戻りたいことがあるかもしれません。

マークは複数のファイルにまたがってもかまいません。そういった マークを使うには大文字のレジスタ、つまり A-Z のレジスタを使わ なければなりません。小文字のレジスタはファイルの中だけで使う もので、ファイルをまたがることはありません。言い換えれば、ある foo.c というファイルの中でマークをレジスタ "a" に設定し、それ から別のファイルに移動して 'a と打っても、 カーソルは直前の場所には戻らないのです。別のファイルにカーソル をもっていくようなマークがしたければ、大文字のレジスタを使う 必要があるでしょう。例えば、 ma の代わりに mA を使うんです。複数のファイルを編集するに ついては、後のセクションで論じます。

### gd キーストローク

次のコードのひとまとまりを考えます。

#### 三番目の例

    		     struct X x;

    		     void foo()
    		     {
    		             struct Y y;
    		             struct Z z;
    		             ...

    			     /* 多くの行のあとで */
    		             x.bar();
    		             y.bar();
    		             z.bar();
    		     }

y と z がなんだったかを、なぜだか忘れてしまい、大至急 それらが定義してある場所に行きたいとします。一つの方法は y とか z を後方検索することです。でもVIMにはもっと簡単で 素早い解決方法があります。gd という キーストロークは "Goto Declaration （宣言へ行く）" の略 になってます。カーソルを "y" において gd と打つと、カーソルをその宣言、つまり struct Y y; にもって いくんです。

gDも似たようなキーストロークです。これは カーソルの位置にある変数をグローバル宣言してある場所まで、 カーソルをもっていきます。だから、 x の宣言に行きたければ、 必要なことは gD と打つだけで、これでカーソル は x の宣言に移動するでしょう。

## 単語の自動補完

次のコードを考えます。

### 自動補完の例

    		  void A_Very_Long_Function_Name()
    		  {
    		          ...
    		  }

    		  short A_Very_Long_Variable_Name;

    		  void Another_Function()
    		  {
    		          ...
    		          A_Very_Long_Function_Name();
    		          ...
    		  }

A_Very_Long_Function_Name() という関数は、何度も何度もタイプ するので、まったく癪の種になることがあります。でもまだ挿入モードに いる間でも、その前後にある単語を探して、単語を自動補完 できるのです。Another_Function() という関数の中で A_Very... とタイプ し、CTRL-P と打ってもいいでしょう。最初に一致した 単語が最初に表示されます。この場合は A_Very_Long_Variable_Name かも しれません。正しく補完するためにもう一度 CTRL-P と打ち、次に一致する単語まで検索が続きます。その単語が A_Very_Long_Function_Name です。正しい単語が見つかったら、ただちに タイプを続けられます。この過程の間はずっとVIMが挿入モードのままで います。

CTRL-P と似たものに CTRL-N と いうキーストロークがあります。これは後方検索の代わりに前方検索 を行なうものです。これらのキーストロークは両方とも、ファイルの先頭 かファイルの最後に行き当たるまで検索を続けます。

CTRL-P や CTRL-N は CTRL-X モードというモードの一部になっています。 CTRL-X モードは挿入 モードのサブモードです。だから挿入モードにいるときは、この モードに入れるわけです。 CTRL-X モードを抜けるには CTRL-X, CTRL-P および CTRL-N 以外のキーストロークを何か打てば いいです。いったんCRTL-X モードを抜けたら、挿入モードに戻ります。

CRTL-X モードを使えば、さまざまな方法で自動補完ができるように なります。ファイル名を自動補完することさえできます。ヘッダー ファイルをインクルードしなければならない時に、これは特に役立ちます。 CTRL-X モードを使えば、次のようなやり方で foo.h という ファイルがインクルードできます。

    	 #include "f CTRL-X CTRL-F"

そう、CTRL-X CTRL-Fです。わかってる、わかってるって。emacsみたい だっていうんでしょ ;-) CTRL-Xモードではできることが他にもあります。 そんなものの一つが辞書補完です。これを使うと単語の一覧が入った ファイルを指定して、それを使って補完するようにできるんです。 ディフォルトだとこの辞書オプションは設定されていません。 設定するには `:set dictionary=file` という コマンドを使います。大抵は C 言語のキーワードや typedef そして #define なんかをこの辞書ファイルに置いておけます。 同じように、 C++ や Java のプログラマなら、クラス名を加えるのに惹かれるかも しれません。

辞書ファイルのフォーマットは単純です。 1 行に一つ補完したい単語 を書いておくだけです。だから、 C 言語の辞書ファイルというのは たぶんこんなようなものになるんでしょう。

### 辞書ファイルのサンプル

    		  case
    		  continue
    		  default
    		  define
    		  do
    		  double
    		  else
    		  enum
    		  float
    		  for
    		  goto
    		  if
    		  ifdef
    		  ifndef
    		  include
    		  int
    		  pragma
    		  return
    		  struct
    		  switch
    		  typedef
    		  void
    		  while

辞書補完を使うには、 CTRL-X CTRL-K と打つ 必要があります。補完は CTRL-P や CTRL-N のキーストロークに似ています。 だから、えーっと、 "typedef" とタイプするなら、 CTRL-X CTRL-K と打つだけでよくて、すると、パッと出てきて、 名前の補完が完了です。

## 自動的な整形

### 桁数の制限

桁数を80桁とか75桁とか、何であれ、制限しなければならないことが よくあります。次のコマンドを使えば、きわめて容易にこの設定が できてしまいます。

    	    :set textwidth=80

これを自動的にするには、たんに自分の .vimrc にこのコマンドを 置いてください。

テキスト幅を制限する他に、ある桁でテキストを折り返したい こともあるでしょう。それは自分が使っている端末がそう規定して いるからそうなっていたり、あるいはたんにそういうように自 分で選んだからかもしれません。こんな場合に使うコマンドが 次のコマンドです。

    	    :set wrapwidth=60

上記のコマンドは60桁でテキストを折り返すようにします。

### コードを自動的にインデントする

C でコーディングしている間は、内側のコードの塊をインデント することがよくあります。コーディング中にこれを自動化する ために、VIMには cindent というオプションがあります。これを 設定するには、次のコマンドを使うだけです。

    	    :set cindent

cindent を設定すれば、コードは自動的にきれいになります。 このコマンドを自動的に実行する場合は、自分の .vimrc に加える だけでいいです。

### 注釈

VIMでは注釈を自動整形できるようにもなっています。注釈は三つの 部分に分けることができます。つまり最初の部分、真中の部分、 そして最後の部分です。例えば、自分のコーディングスタイルに 必要な条件だからということで、注釈を次のスタイルにする必要が あるかもしれません。

    	    /*
    	    * これは注釈です
    	    */

このような場合は次のコマンドが使えます。

    	    :set comments=sl:/*,mb:*,elx:*/

読者のために、このコマンドを解読してみましょう。このコマンド には三つの部分があります。最初は sl:/* という部分です。これは 三つにわかれた注釈が /* で始まることを VIM に教えています。 次は注釈の真中の部分が * だと VIM に告げています。注釈の最後の 部分は、二つのことを VIM に教えています。一つはこのコマンドが */ で終らねばならないこと、そしてもう一つは / を打つと自動的に 注釈を完成させねばならないことです。

もう一つ別の例をあげてみましょう。自分のコーディング指針が 次のようだとしましょう。

    	    /*
    	    ** これは注釈です
    	    */

このような状況では、注釈をつけるのに次のコマンドが使えます。

    	    :set comments=sl:/*,mb:**,elx:*

注釈を挿入するには、 /* とタイプし enter キーを打つだけです。 次の行には自動的に ** が入っているはずです。注釈を書き終ったら もう一度 enter キーを打つだけで、もう一つ別の ** が挿入されます。 でも注釈を終えるには **/ じゃなくて */ が欲しいですね。VIMは ここでもまことに賢いんです。最後の * を削除して / に置き換える 必要がないんです。代わりに / とだけ打って下さい。そうすれば VIMはそれが注釈の終りだと認識し、自動的にその行を ** から */ へ 変えるはずです。

もっと知りたいことがあれば、次のコマンドを打って下さい。 `:h comments`

## 複数のファイルを編集する

一度に二つ以上のファイルを編集する必要があるというのはよくある ことです。例えば、ヘッダーファイルを編集していて、同時にソース ファイルも編集することがあるかもしれません。一度に二つ以上の ファイルを編集するには、次のコマンドを使って VIM を起動します。

    	 $ vim file1 file2 ...

これで最初のファイルが編集でき、以下のコマンドを使えば次のファイル に移ることができます。

    	 :n

戻る場合は次のコマンドを使えばできます。

    	 :e#

二つのファイルを同時に見ることができて、さらにその二つを切替える ことができれば、コーディング中役立つかもしれません。言い換えれば、 画面を分割して上の方にヘッダーファイルが見えて下の画面ではソース ファイルが見えれば、役立つだろうということです。VIMにはそんな画面を 分割するコマンドがあるんです。これを起動するにはたんに次のように します。

`:split`

同じファイルが両方のウィンドウに表示されると思います。ここでどんな コマンドを実行しても、それが影響するのはその時に使っているウィンドウ だけです。だから、次のコマンドを使えば、別のウィンドウにある別の ファイルが編集できるんです。 `:e file2`

このコマンドを実行した後は、二つのファイルが見えるようになっている のがわかるでしょう。一つのウィンドウには最初のファイルが表示されて いて、他のウィンドウには二番目のファイルが表示されています。この 二つのファイルを切り替えて使うには、 CTRL-W CTRL-W というキーストロークを使わなければなりません。ウィンドウの分割に ついてもっと知りたければ、そこで help コマンドを実行すればいいです。

## Quickfix

C 言語でコーディングしている場合、編集 - コンパイル - 編集という サイクルがよくあります。（この文書を読んでいる）読者なら、これまでに 説明したコマンドなどを使って、C 言語のファイルを編集し、ファイルを 保存し、そのコードをコンパイルし、そしてエラーの箇所に行き、また編集 を始めるのが普通でしょう。こんなときに、Quickfixというモードを使えば、 VIMはこのサイクル時間を若干節約するのを助けてくれます。基本的には、コ ンパイラのエラーをファイルに保存しておいて、次のコマンドを使ってVIMで このファイルをオープンする必要があります。

    	 $ vim -q コンパイラのエラーを保存したファイル

VIMは自動的にエラーの情報が入っているこのファイルをオープンして、 カーソルを最初のエラーの位置にもっていきます。

このやり方には近道があります。 "make" というコマンドを使えば、 自動的にコードをコンパイルして、最初に発生したエラーの位置に 行ってくれます。 make コマンドを起動するには次のようにタイプ します。

    	 :make

実は、このコマンドはシェルで make をコールして、最初のエラー 箇所に行くんです。でもコンパイルに make ではなく cc のようなコマンド を使っている場合は、この make コマンドを使う時に実行したいコマンド を makeprg という変数に設定しなければなりません。 例えば次のようにです。 `:set makeprg=cc\ foo.c`

makeprg を設定しておけば、実際に make コマンドを呼び出せるし、 Quickfixモードが動き出すことでしょう。

最初のエラーを修正したら、次にやることはその次のエラーの箇所に 行ってそれを修正することでしょう。次のエラーの箇所に行くには 以下のコマンドを使います。 `:cn`

そこから戻るには、次のコマンドを使います。 `:cN`

例を使って実際にやってみることにしましょう。以下のコードを考えて ください。

### 即効ファイルプログラムのリスト

    		  1  #include <stdio.h>
    		  2
    		  3  int main()
    		  4  {
    		  5          printf("Hello World\n")
    		  6  }

見ればわかりますが、5行目にエラーがあります。このファイルは test.c という名前で保存されていて、makeprg は以下のコマンドを 使って設定してあります。

    	 :set makeprg=gcc\ test.c

次に、 make コマンドは `:make` というコマンドを 使って起動します。すると gcc がエラーを出し、 make コマンドの 出力が以下のようなものになります。

### :make コマンドで出たエラー

    		  :!gcc test.c  2>&1| tee /tmp/vim9821.err
    		  test.c: In function `main':
    		  test.c:6: parse error before `}'
    		  test.c:4: warning: return type of `main' is not `int'
    		  (2 of 3):  parse error before `}'
    		  Press RETURN or enter command to continue

RETURN を押すと、カーソルは6行目に移動します。

今度は `:cn` コマンドがカーソルを4行目にもって いきます。

直前のエラー箇所に戻るには、 `:cN` コマンドが 使えます。これでカーソルは6行目に戻ることでしょう。

5行目のエラーを修正して "return 1;" を追加したら、 もう一度 `:make` を実行します。するとその出力は 次のようになります。

### エラー無し

    		  :!gcc test.c  2>&1| tee /tmp/vim9822.err

    		  Press RETURN or enter command to continue

これはほんのわずかな一例です。でもこのQuickfixを使ってコンパイル 時間に関する問題が解決できるし、うまくいけば編集 - コンパイル - 編集の サイクルも削減できるのです。

## 著作権

Copyright (c) 2000,2001 Siddharth Heroor.

本文書の複製、配布、ないしは変更は、 Free Software Foundation 発行の バージョン 1.1 ないしそれ以降のすべてのバージョンの フリー文書利用許諾契約書（GNU Free Documentation License） の 条件下で許可する。ただし、変更不可能部分が無いこと、表表紙が 無いこと、および裏表紙が無いこと。フリー文書利用許諾契約書の 複製は以下のサイトで取得できる。 http://www.gnu.org/copyleft/fdl.html

## 参考文献

VIM に関するより多くの情報は以下のサイトから取得できるし、 VIM も そこからダウンロードできる。 http://www.vim.org

## 日本語版謝辞

校正をしていただいた佐野さん、高城さんには、この場を借りて御礼申し上げます。 また、初参加の私の些細な質問にも、丁寧にお答え下さった 中野さん、高橋さん、アドバイスをいただいた中谷さんにも御礼申し上げます。