1 *usr_29.txt* For Vim バージョン 7.2. Last change: 2008 Jun 28
3 VIM USER MANUAL - by Bram Moolenaar
8 Vim の作者はプログラマです。当然、プログラムを書くための機能が Vim にはたくさ
9 んあります。この章では、識別子が定義された場所、あるいは使われている場所にジャ
10 ンプしたり、その定義を別のウィンドウでプレビューしたりする方法を説明します。プ
11 ログラミング関連の機能は次章でも説明します。
19 次章: |usr_30.txt| プログラムの編集
23 ==============================================================================
26 タグとは、識別子が定義された場所のことです。例えば C や C++ の関数定義がそうで
27 す。タグの一覧はタグファイルに保存されます。Vim はタグファイルに対応しており、
28 タグ、つまり識別子の定義場所に直接ジャンプできます。
29 カレントディレクトリのすべての C ファイルからタグを生成するには、次のコマンド
34 "ctags" は Vim に付属してません。ほとんどの Unix システムには最初からインス
35 トールされています。持っていない場合は Exuberant ctags を使ってください:
39 Vim のコマンドラインから次のコマンドを実行すると関数定義にジャンプできます: >
43 "startlist" 関数が検索されます。他のファイルで定義されていても検索可能です。
44 CTRL-] コマンドを使うとカーソルの下の単語をタグとみなしてジャンプできます。こ
45 れは複雑な C コードの探索を簡単にしてくれます。例えば、"write_block" 関数の中
46 で "write_line" の呼び出しを見つけたとき、その関数の動作を知りたかったら、
47 "write_line" にカーソルを合わせて CTRL-] を押せば、その関数の定義にジャンプで
49 "write_line" の中で "write_char" が呼ばれていたら、その関数の動作も調べる必要
50 があります。"write_char" にカーソルを合わせて CTRL-] を押しましょう。これ
51 で "write_char" の定義に移動できました。
53 +-------------------------------------+
54 |void write_block(char **s; int cnt) |
57 | for (i = 0; i < cnt; ++i) |
60 +-----------|-------------------------+
63 | +----------------------------+
64 +--> |void write_line(char *s) |
69 +--------|-------------------+
72 | +------------------------------------+
73 +--> |void write_char(char c) |
75 | putchar((int)(unsigned char)c); |
77 +------------------------------------+
79 ":tags" コマンドで移動経路を確認できます:
82 # TO tag FROM line in file/text ~
83 1 1 write_line 8 write_block.c ~
84 2 1 write_char 7 write_line.c ~
87 では元の場所に戻りましょう。CTRL-T で直前のタグに戻れます。上の例であれば、
88 "write_line" 関数の中の "write_char" の呼び出しに戻ることになります。
89 このコマンドはカウント指定を付けてジャンプする回数を指定できます。前方にジャン
90 プして、そして戻ってくることができましたね。もう一度前方に移動してみましょう。
91 次のコマンドでタグリストの前方に移動できます: >
95 コマンドの前にカウント指定を付けてジャンプする回数を指定できます。例えば
96 ":3tag" のように使います。CTRL-T も同様に回数指定できます。
97 このように、CTRL-] をで呼び出しをたどり、CTRL-T でさかのぼることができます。
98 ":tags" コマンドで現在地を確認できます。
104 ":tag" コマンドはカレントウィンドウを使ってジャンプ先のファイルを表示します。
105 しかし現在の関数とジャンプ先の関数を同時に表示したいこともあると思います。
106 ":split" コマンドでウィンドウを分割してから ":tag" コマンドを使うという方法も
107 ありますが、専用の短縮コマンドが用意されています: >
111 カーソルの下の単語にタグジャンプするときにウィンドウを分割したい場合は次のコマ
116 カウント指定を付けて新しいウィンドウの高さを指定できます。
120 ------------------------
122 ファイルが複数のディレクトリに分れている場合、ディレクトリ毎にタグファイルを作
123 ることもできますが、その方法だとタグファイルと同じディレクトリのファイルにしか
125 タグファイルが複数ある場合は 'tags' オプションを設定して、関連するすべてのタグ
126 ファイルが検索されるようにしてください。例: >
128 :set tags=./tags,./../tags,./*/tags
130 カレントファイルと同じディレクトリ、その一つ上のディレクトリ、すべてのサブディ
132 これでかなり多くのタグファイルが使えるようになりましたが、まだ十分ではないかも
133 しれません。例えば "~/proj/src" を編集しているときに "~/proj/sub/tags" を見つ
134 けることができません。そのような場合はディレクトリツリー全体を検索するように設
137 :set tags=~/proj/**/tags
141 --------------------------
143 たくさんの場所からタグファイルを検索しているときは、ハードディスクがガリガリと
144 音を立てるのが聞こえると思います。これは効率が良くありません。そんなときは少し
145 時間を掛けて一つの巨大なタグファイルを生成するのがベストです。寝ている間にでも
147 それには上述した Exuberant ctags が必要です。このプログラムにはディレクトリツ
148 リー全体を検索するためのオプションがあります: >
153 Exuberant ctags のいいところは、いろんなファイルタイプを認識してくれるところで
154 す。C や C++ だけでなく Effiel や Vim スクリプトも処理できます。詳しくは ctags
156 これで、巨大なタグファイルを一つだけ指定するだけでよくなりました: >
158 :set tags=~/proj/tags
164 同じ名前の関数が何度も定義されている場合、あるいは複数のクラスで同名のメソッド
165 が定義されている場合、":tag" コマンドは最初に見つかったタグにジャンプします。
166 カレントファイル内にタグがある場合はそれが優先されます。
167 タグが重複している場合は次のコマンドで別のタグにジャンプできます: >
171 もう一度実行するとさらに別のタグにジャンプできます。タグがたくさんある場合は次
178 # pri kind tag file ~
179 1 F f mch_init os_amiga.c ~
181 2 F f mch_init os_mac.c ~
183 3 F f mch_init os_msdos.c ~
185 4 F f mch_init os_riscos.c ~
187 Enter nr of choice (<CR> to abort): ~
189 (行頭の) 番号を入力してジャンプしたい場所を選択してください。他の列にはタグの
192 次のコマンドで他の重複タグに移動できます:
195 :[count]tprevious [count]個 前のタグに移動
196 :[count]tnext [count]個 次のタグに移動
199 [count] を省略すると 1 が使われます。
205 コマンドライン補完を使うと長いタグ名の入力が簡単になります。最初の数文字を入力
206 してから <Tab> キーを押してください: >
210 最初にマッチしたタグが補完されます。それが意図したタグでない場合は、目的のタグ
211 が見つかるまで <Tab> キーを押してください。
212 関数名の一部しか知らない場合や、同じ文字で始まるタグ (後半だけが違っている) が
213 たくさんある場合は、パターンを使ってタグを検索できます。
214 例えば、名前に "block" が含まれているタグにジャンプする場合は、まず次のように
219 そして、コマンドライン補完を使います。<Tab> キーを押してください。"block" を含
220 むタグが検索され、最初にマッチしたタグが使われます。
221 タグ名の前に "/" を付けると、続くタグ名はそのまま使われず、パターンとして解釈
222 されます。検索パターンと同じ機能がすべて使えます。例えば、"write_" で始まるタ
223 グを選択したい場合は次のようにします: >
227 最初の "^" はタグ名が "write_" で始まることを示しています。"^" がない場合はタ
228 グ名の途中にもマッチしてしまいます。同様に、"$" を最後に付けるとタグ名の末尾に
235 CTRL-] を使うとカーソルの下にある識別子の定義にジャンプできますが、これを利用
236 すると、識別子の一覧を目次として使うことができます。例を示します。まず識別子の
237 一覧を作ります (Exuberant ctags が必要です) >
239 ctags --c-types=f -f functions *.c
241 そして Vim をファイル指定なしで起動し、作成したファイルを縦分割ウィンドウで開
247 ウィンドウにはすべての関数の一覧が表示されています。関数以外の名前も含まれてい
248 るかもしれませんが、それは無視してください。":setlocal ts=99" を実行して表示を
250 このウィンドウで、次のマップを定義します: >
252 :nnoremap <buffer> <CR> 0ye<C-W>w:tag <C-R>"<CR>
254 表示したい関数の行に移動して <Enter> を押すと、カーソルが他のウィンドウに移動
261 タグ名の大文字と小文字を無視したい場合は 'ignorecase' をオンに設定してくださ
264 'tagbsearch' オプションにはタグファイルがソートされているかどうかを設定しま
265 す。初期設定ではソート済みに設定されています。これはタグの検索を高速に実行でき
266 ますが、ソートされていないタグファイルを扱えなくなります。
268 'taglength' オプションはタグの識別に使う文字数を指定するのに使います。
270 SNiFF+ プログラムを使う場合は |sniff| インターフェースが使えます。SNiFF+ は商
273 cscope はフリーのプログラムです。識別子の定義場所を探すだけでなく、それが使わ
274 れている場所も検索できます。|cscope| 参照。
276 ==============================================================================
279 コードの中で関数を呼び出すときには、その引数を正確に把握する必要があります。引
280 数の意味は関数の定義を見ればわかります。タグの仕組みを使えば簡単に確認できます
281 が、できれば別のウィンドウに定義を表示したいところです。それにはプレビューウィ
283 次のようにすると "write_char" 関数をプレビューウィンドウで表示できます: >
287 ウィンドウが開いて "write_char" タグにジャンプします。カーソルの位置は動かない
288 ので CTRL-W コマンドを使って戻る必要はありません。
289 テキストの中に関数名がある場合は、次のコマンドでその定義をプレビューウィンドウ
294 カーソルの下にある単語の定義場所を自動的に表示してくれるスクリプトもあります。
295 |CursorHold-example|参照。
297 プレビューウィンドウを閉じるには次のコマンドを使います: >
301 プレビューウィンドウでファイルを開きたい場合は ":pedit" を使います。例えばヘッ
302 ダファイルを表示するような場合に便利です: >
306 最後に ":psearch" コマンドを紹介します。カレントファイルおよびインクルードされ
307 ているファイルから単語を検索して、ヒットした場所をプレビューウィンドウで表示で
308 きます。これは例えば、ライブラリ関数を使っていて、それ用のタグファイルを作って
313 "stdio.h" がプレビューウィンドウで開き、popen() 関数のプロトタイプが表示されま
316 FILE *popen __P((const char *, const char *)); ~
318 プレビューウィンドウの高さは 'previewheight' オプションで設定できます (最初に
321 ==============================================================================
324 プログラムには構造があるので、構文を認識することが可能です。その情報を利用して
326 例えば C のプログラムには次のような構文がよく現れます:
329 fd = popen("ls", "r") ~
331 fd = fopen("tmp", "w") ~
334 もっと長いかもしれませんし、入れ子になっていることもあります。"#ifdef" に移動
335 して % を押すと "#else" にジャンプできます。もう一度 % を押すと "#endif" に
336 ジャンプします。さらに % を押すと "#ifdef" に戻ります。
337 構文が入れ子になっている場合は、正しく対応しているものが検索されます。これは
338 "#endif" の書き忘れがないかどうか確認するのに便利です。
339 "#if" と "#endif" の間にカーソルがあるとき、次のコマンドで開始位置にジャンプで
344 "#if" や "#ifdef" の中にいない場合は警告音が鳴ります。前方の "#else" または
345 "#endif" に移動するには次のコマンドを使います: >
349 これらのコマンドは、途中にある "#if" - "#endif" ブロックをスキップします。
352 #if defined(HAS_INC_H) ~
359 カーソルが最後の行にあるとき、"[#" で最初の行に移動できます。途中の "#ifdef" -
360 "#endif" ブロックはスキップされます。
364 ----------------------
366 C のコードブロックは {} で囲まれています。ブロックはかなり大きい場合もありま
367 す。アウターブロック (最も外側のブロック) の開始位置に移動するには "[[" コマン
368 ドを使います。"][" でブロックの末尾に移動できます。このコマンドは行頭の "{" と
369 "}" をブロックの区切りとして認識します。
370 "[{" コマンドで現在のブロックの開始位置に移動できます。同じレベルの {} ペアは
371 スキップされます。"]}" で末尾に移動できます。
380 | [{ | | foo(32); | --+
381 | | [{ | if (bar(a)) --+ | ]} |
382 +-- | +-- break; | ]} | |
388 C++ や Java では、最も外側の {} ブロックはクラスです。その次のレベルの {} はメ
389 ソッドです。クラスの中で "[m" を使うと、前のメソッドの開始位置に移動できます。
390 "]m" で次のメソッドの開始位置に移動できます。
392 "[]" で前の関数の末尾に移動、"]]" で次の関数の開始位置に移動できます。行頭が
393 "}" で始まる行が関数の末尾として認識されます。
403 start +-- +-- return flag;
412 ()、{}、[] などの対括弧に移動する場合は "%" も使えることを忘れないでください。
413 括弧の間に複数の行がはさまっていても機能します。
419 "[(" と "])" は "[{" と "]}" と機能は同じです。ただし、 {} のペアではなく ()
423 < <--------------------------------
425 if (a == b && (c == d || (e > f)) && x > y) ~
427 --------------------------------> >
433 コメントの開始位置に戻るには "[/" コマンドを使います。コメントの終了位置に移動
434 するには "]/" を使います。これは /* - */ 形式のコメントのみ対応しています。
437 | [/ | * A comment about --+
438 [/ | +-- * wonderful life. | ]/
441 +-- foo = bar * 3; --+
443 /* a short comment */ <-+
445 ==============================================================================
448 C プログラムを編集していて、変数の型が "int" なのか "unsigned" なのか分からな
449 かったら、"[I" コマンドで簡単に確認できます。
450 例えば、"column" という単語の上でコマンドを実行すると: >
454 マッチした行が一覧表示されます。カレントファイルとインクルードファイル (さらに
455 その中でインクルードされているファイル) が検索されます。検索結果は次のように表
459 1: 29 unsigned column; /* column number */ ~
461 インクルードファイルも検索されるという点が、タグやプレビューウィンドウを使った
462 検索よりも便利です。たいていは正しい定義場所が見つかります。タグファイルが更新
463 されていなくても、インクルードファイル用のタグファイルがなくても機能します。
464 ただし、"[I" が動作するためには少し条件があります。ファイルのインクルードを認
465 識するために、'include' オプションが正しく設定されていなければなりません。初期
466 設定は C と C++ 用に設定されているので、他の言語では設定を変更する必要がありま
471 --------------------------
473 インクルードファイルは 'path' オプションに設定された場所から検索されます。設定
474 に含まれていないディレクトリがあると、いくつかのインクルードファイルは検出でき
475 ないかもしれません。次のコマンドで検出できないファイルを確認できます: >
479 検出できなかったインクルードファイルの一覧が表示されます。インクルードファイル
480 の中のインクルードも検査されます。次のような結果が表示されます:
482 --- Included files not found in path --- ~
486 <clib/exec_protos.h> ~
488 カレントファイルでインクルードしている "io.h" が見つかっていません。"vim.h" は
489 見つかったので ":checkpath" はさらにそのファイルのインクルードも検査しました。
490 そして、"functions.h" と "clib/exec_protos.h" が見つかりませんでした。
493 Vim はコンパイラではないので、"#ifdef" ステートメントを認識しません。
494 つまり、"#if NEVER" で囲まれている "#include" ステートメントもすべて検
497 この問題を修正するには 'path' オプションにディレクトリを追加します。Makefileを
498 見れば必要なディレクトリがわかると思います。"-I/usr/local/X11" のように、"-I"
499 が使われている行を調べてください。次のコマンドでディレクトリを追加できます: >
501 :set path+=/usr/local/X11
503 サブディレクトリがたくさんある場合はワイルドカード "*" が使えます。例: >
505 :set path+=/usr/*/include
507 これで "/usr/local/include/" や "/usr/X11/include/" などが検索対象になります。
509 ディレクトリツリーのあちこちにインクルードファイルがあるようなプロジェクトでは
510 "**" が便利です。すべてのサブディレクトリを検索できます。例: >
512 :set path+=/projects/invent/**/include
514 例えば次のようなディレクトリからファイルが検索されます:
516 /projects/invent/include ~
517 /projects/invent/main/include ~
518 /projects/invent/main/os/include ~
521 設定方法は他にもあります。'path' オプションの説明を確認してください。
522 実際に検出されたインクルードファイルを確認したい場合は次のコマンドを使います:
526 インクルードされているファイルの (長大な) 一覧が表示されます。出力を短くするた
527 め、同じファイルを見つけた場合は "(Already listed)" とだけ表示し、その中のイン
532 ----------------------
534 "[I" はマッチした行だけを一覧表示します。その周辺を見たい場合は、次のコマンド
539 <Tab> と CTRL-I は同じなので "[ CTRL-I" でも構いません。
541 "[I" で表示される一覧には番号が付いています。最初の項目以外の場所にジャンプし
546 三番目のマッチにジャンプします。CTRL-O で元の場所に戻れることをお忘れなく。
554 ]i カーソルより後ろの最初のマッチだけ表示
560 "[I" コマンドはすべての識別子を検索します。"#define" で定義されたマクロだけを
565 このコマンドもインクルードファイルが検索対象になります。検索される行の書式は
566 'define' オプションで指定します。C と C++ 以外の言語では設定を変更する必要があ
568 次のような "[D" に関連したコマンドがあります:
572 ]d カーソルより後ろの最初のマッチだけ表示
574 ==============================================================================
577 "[I" コマンドはインクルードファイルの中も検索します。カーソルの下の単語が最初
578 に現れる場所を、カレントファイルの中だけ検索し、その場所にジャンプするには、次
583 ヒント: Goto Definition (定義に移動)。このコマンドはローカル(C 用語で"static")
584 に定義された変数や関数を検索するのに便利です。例 (カーソルは"counter" の上):
586 +-> static int counter = 0;
588 | int get_counter(void)
594 さらに検索範囲を狭めて、現在の関数の中だけ検索したい場合は次のコマンドを使いま
599 現在の関数の開始位置から最初に単語が使われている場所が検索されます。実際に、行
600 頭が "{" で始まる行を後方検索して、その上の空行まで戻り、そこから識別子を前方
601 検索しています。例 (カーソルは "idx" の上):
603 int find_entry(char *name)
607 gd | for (idx = 0; idx < table_len; ++idx)
608 | if (strcmp(table[idx].name, name) == 0)
612 ==============================================================================
614 次章: |usr_30.txt| プログラムの編集
616 Copyright: see |manual-copyright| vim:tw=78:ts=8:ft=help:norl: