vim-jp / vimdoc-ja / usr_30

usr_30 - Vimドキュメント

メインヘルプファイルに戻る
usr_30.txt    For Vim バージョン 8.2.  Last change: 2007 Nov 10

                     VIM USER MANUAL - by Bram Moolenaar

                               プログラムの編集


プログラミングに役立つ機能が Vim にはたくさんあります。プログラムをコンパイル
してエラーが出た行にジャンプしたり、言語に合わせて自動的にインデントしたり、コ
メントを整形したりできます。

30.1  コンパイル
30.2  C 言語系インデント
30.3  インデント設定の自動化
30.4  その他のインデント
30.5  タブとスペース
30.6  コメントの整形

次章: usr_31.txt  GUI を活用する
前章: usr_29.txt  プログラムの中を移動する
目次: usr_toc.txt

==============================================================================
30.1  コンパイル

Vim にはquickfix機能があります。これは、Vim の中でプログラムをコンパイルして、
エラーになった場所に移動し、エラーを修正するための機能です。そうして、正常にコ
ンパイルできるまでコンパイルとエラー修正を繰り返します。

次のコマンドは "make" を実行し、その出力を読み込みます (引数はそのまま渡されま
す):

        :make {arguments}

エラーが発生するとそれが認識され、最初のエラーにカーソルが移動します。
":make" の使い方を実際に見てみましょう。(典型的な :make セッションはもっと多く
のエラーあるいは少しのゴミを出力しますが) ":make" を実行すると次のような出力が
画面に表示されます:

        :!make | &tee /tmp/vim215953.err
        gcc -g -Wall -o prog main.c sub.c
        main.c: In function 'main':
        main.c:6: too many arguments to function 'do_sub'
        main.c: At top level:
        main.c:10: parse error before '}'
        make: *** [prog] Error 1

        2 returned
        "main.c" 11L, 111C
        (3 of 6): too many arguments to function 'do_sub'
        Hit ENTER or type command to continue

"main.c" の中でエラーが発生していることが確認できると思います。<Enter> を押す
と "main.c" ファイルが開き、6 行目 (最初のエラー) にカーソルが移動します。自分
でファイルを開く必要はありません。Vim はエラーメッセージを認識できます。

                +---------------------------------------------------+
                |int main()                                         |
                |{                                                  |
                |       int i=3;                                    |
      cursor -> |       do_sub("foo");                              |
                |       ++i;                                        |
                |       return (0);                                 |
                |}                                                  |
                |}                                                  |
                | ~                                                 |
                |(3 of 12): too many arguments to function 'do_sub' |
                +---------------------------------------------------+

このコマンドで次のエラーに移動できます:

        :cnext

カーソルが 10 行目に移動します。ファイルの最終行に余分な '}' がありますね。長
すぎるエラーメッセージは省略して表示されます。全部を表示するには次のコマンドを
使います:

        :cc

すべてのエラーメッセージを表示するには ":clist" コマンドを使います。次のような
出力が表示されます:

        :clist
        3 main.c: 6:too many arguments to function 'do_sub'
        5 main.c: 10:parse error before '}'

ファイル名と行番号が認識された行だけが表示されますが、それは、重要なのはそのよ
うな行だけで、他の行は無駄なメッセージであると判断されるからです。しかし時に
は、認識されなかった行が重要な情報を含んでいることもあります。例えばリンカが未
解決の関数をエラー表示した場合などです。すべてのメッセージを表示するにはコマン
ドに "!" を付けます:

        :clist!
        1 gcc -g -Wall -o prog main.c sub.c
        2 main.c: In function 'main':
        3 main.c:6: too many arguments to function 'do_sub'
        4 main.c: At top level:
        5 main.c:10: parse error before '}'
        6 make: *** [prog] Error 1

現在のエラーは強調表示されます。前のエラーに戻るには次のコマンドを使います:

        :cprevious

エラーリストを移動するコマンドは他にもあります:

        :cfirst         最初のエラー
        :clast          最後のエラー
        :cc 3           3つ目のエラー


他のコンパイラを使う
--------------------

":make" コマンドが実際に実行するプログラムは 'makeprg' オプションで設定しま
す。通常は "make" に設定されていますが、例えば Visual C++ を使う場合は "nmake"
に設定する必要があります:

        :set makeprg=nmake

オプションにはプログラムの引数も含めることができます。特殊文字はバックスラッ
シュでエスケープしてください。例:

        :set makeprg=nmake\ -f\ project.mak

プログラムの設定には特殊なキーワードが使えます。文字 % はカレントファイルの名
前に展開されます。例えば次のように設定すると:

        :set makeprg=make\ %:S

main.c を編集しているときに ":make" を実行すると次のコマンドが実行されます:

        make main.c

これ自体はそれほど便利ではありませんが、すこし変更して :r (root) 修飾子を使う
とどうでしょう:

        :set makeprg=make\ %:r:S.o

これで、実行されるコマンドは次のようになります:

        make main.o

修飾子については filename-modifiers を参照してください。


古いエラーリスト
----------------

例えば ":make" を実行したときに、一つのファイルで警告メッセージが出て、他の
ファイルではエラーが出たとします。エラーを修正し、本当に直ったかどうかを確認す
るためにもう一度 ":make" を実行しました。さて、ここで先程の警告メッセージを確
認しようとしても、エラーリストには警告メッセージありません。なぜなら、警告メッ
セージを出したファイルは再コンパイルされなかったからです。次のコマンドで古いエ
ラーリストに戻ることができます:

        :colder

":clist" と ":cc {nr}" を使って、警告が発生した場所にジャンプしましょう。
次のコマンドで新しいエラーリストに戻れます:

        :cnewer

全部で 10 個までのエラーリストを保持しておくことができます。


他のコンパイラを使う
--------------------

コンパイラが出力するエラーメッセージの書式を調べ、'errorformat' オプションを設
定する必要があります。このオプションの構文は非常に複雑ですが、どのようなコンパ
イラにも対応できます。詳しい説明は errorformat を参照してください。

複数のコンパイラを使うとき、コンパイラを変更するたびに 'makeprg' や
'errorformat' を設定するのは面倒ですよね。簡単な方法が用意されています。例え
ば、Microsoft Visual C++ なら次のように設定します:

        :compiler msvc

"msvc" 用のスクリプトが検索され、適切なオプションが設定されます。
自分で設定スクリプトを書くこともできます。write-compiler-plugin 参照。


出力のリダイレクト
------------------

":make" コマンドは、実行したプログラムの出力をエラーファイルにリダイレクトしま
す。その動作はいろいろな要因に依存しています (例えば 'shell' オプション)。
":make" コマンドがプログラムの出力を拾えていないようなら、'makeef' オプション
と 'shellpipe' オプションを確認してみてください。'shellquote' オプションと
'shellxquote' オプションも関係あるかもしれません。

どうしても ":make" コマンドのリダイレクトが機能しない場合は、シェルからコンパ
イルを実行して、その出力をファイルにリダイレクトしてください。そして、次のコマ
ンドでそのファイルを読み込みます:

        :cfile {filename}

":make" コマンドと同様にエラーにジャンプできます。

==============================================================================
30.2  C 言語系インデント

プログラムを適切にインデントするとコードが読みやすくなります。Vim の機能を使え
ばインデントするのは簡単です。C 言語、あるいは C++ や Java などの C スタイルの
プログラムなら 'cindent' オプションをオンに設定してください。C 言語のインデン
トは組み込みで用意されていて、複雑な構文でも適切にインデントできます。インデン
トに使うスペースの数は 'shiftwidth' オプションで設定します。スペース 4 個くら
いが適切でしょうか。次のコマンドで設定できます:

        :set cindent shiftwidth=4

このオプションを設定すると、例えば "if (x)" と入力したときに、次の行が自動的に
インデントされます。

                                    if (flag)
        インデントが増える --->         do_the_work();
        インデントが減る   <--      if (other_flag) {
        インデントが増える --->         do_file();
        インデントそのまま              do_some_more();
        インデントが減る   <--      }

波カッコ ({}) の中でテキストを入力すると、最初の行でインデントが増え、最後の行
でインデントが減ります。インデントが減るのは '}' を押したタイミングです (入力
を予測することはできないので)。

自動インデントには、コーディングのミスを早く発見できるという副作用があります。
例えば、関数の最後で } を入力したときに、インデントが本来よりも多くなったとし
たら、どこかで } を入力し忘れています。"%" コマンドを使って、最後に入力した }
と対になっている { を探しましょう。
同様に、) や ; を忘れると、次の行のインデントが増えます。もし予想よりもインデ
ントが多くなってしまった場合は直前の行を確認してください。

書式が汚いコードを編集するとき、あるいは編集によってインデントが崩れてしまった
場合、コードを再インデントする必要があります。それには "=" オペレータを使いま
す。最も単純なのは次の使い方です:

        ==

現在行がインデントされます。他のオペレータと同様、使い方は三通りあります。ビ
ジュアルモードで "=" を使うと、選択範囲の行がインデントされます。テキストオブ
ジェクトで便利なのは "a{" です。これは現在のブロックを選択します。つまり、次の
コマンドでコードのブロックをインデントできます:

        =a{

コードが根本的に汚い場合は、次のコマンドでファイル全体を再インデントできます:

        gg=G

ただし、手作業で丁寧にインデントされたファイルに対してこれを実行してはいけませ
ん。自動インデントは良い仕事をしてくれますが、場合によってはそのルールを破る必
要もあるからです。


インデントスタイルの設定
------------------------

インデントスタイルは人によってさまざまです。初期設定では 90% のプログラマが満
足するようなスタイルに設定されています。しかし、世の中にはいろいろなスタイルが
あるので、必要なら、'cinoptions' を設定することで、インデントスタイルをカスタ
マイズできます。
'cinoptions' の初期設定は空です。その場合はデフォルトのスタイルが使われます。
このオプションに値を追加していくことでスタイルを変更できます。例えば、波カッコ
の位置を次のようにしたい場合は:

        if (flag)
          {
            i = 8;
            j = 0;
          }

次のコマンドを使います:

        :set cinoptions+={2

設定できる項目はたくさんあります。cinoptions-values 参照。

==============================================================================
30.3  インデント設定の自動化

C ファイルを開くたびに 'cindent' オプションを設定するのは面倒ですよね。インデ
ントの設定は自動化できます:

        :filetype indent on

実際には、C ファイルに対して 'cindent' をオンにする以外の機能も有効になりま
す。まず最初に、ファイルタイプの認識が有効になります。認識機能は構文強調表示で
使われているものと同じです。
ファイルタイプが認識されると、そのファイルタイプ用のインデントファイルが検索さ
れます。Vim にはさまざまな言語に対応したインデントファイルが付属しています。イ
ンデントファイルが読み込まれ、自動インデントのための設定が行われます。

インデント設定の自動化は次のコマンドでオフにできます:

        :filetype indent off

特定のファイルタイプだけインデントを無効にしたい場合は、次のような一行だけの
ファイルを作成してください:

        :let b:did_indent = 1

これを、決められた名前で保存します:

        {directory}/indent/{filetype}.vim

{filetype} は "cpp" や "java" といったファイルタイプの名前です。次のコマンドで
Vim が使っている名前を確認できます:

        :set filetype

例えばこのヘルプファイルなら次のように表示されます:

        filetype=help

したがって、{filetype} には "help" が入ります。
{directory} はランタイムディレクトリです。次のコマンドの出力を調べてください:

        set runtimepath

ここでは先頭のパスを使います。つまり、出力が次のようなら:

        runtimepath=~/.vim,/usr/local/share/vim/vim60/runtime,~/.vim/after

{directory} には "~/.vim" が入ります。したがって、ファイル名は次のようになりま
す:

        ~/.vim/indent/help.vim

インデントをオフにするのではなく、自分のインデントファイルを作成したい場合は、
indent-expression を参照してください。

==============================================================================
30.4  その他のインデント

最もシンプルな自動インデントは 'autoindent' オプションを使う方法です。これは直
前の行と同じインデントを使います。'smartindent' はもう少しスマートです。これは
インデントファイルが用意されていないような場合に使います。'smartindent' は
'cindent' より低機能ですが、'autoindent' よりは高機能です。
'smartindent' をオンにすると、{ でインデントが一つ増え、} で減ります。さらに、
'cinwords' オプションに設定された単語が現れた場合もインデントが増えます。# で
始まる行は特別扱いされ、一切インデントされません。つまり、プリプロセッサーディ
レクティブの行はインデントされません。その次の行は通常通りインデントされます。


インデントの訂正
----------------

'autoindent' や 'smartindent' を設定すると、直前の行と同じインデントを使うこと
ができますが、自分でインデントを ('shiftwidth' の幅ずつ) 増やしたり減らしたり
する必要も多々あります。それには挿入モードで CTRL-D と CTRL-T を使うと簡単で
す。例えば、次のようなシェルスクリプトを入力してみましょう:

        if test -n a; then
           echo a
           echo "-------"
        fi

まず、次のオプションを設定します:

        :set autoindent shiftwidth=3

一行目を入力し、<Enter> を押して二行目を開始します:

        if test -n a; then
        echo

二行目にはインデントが必要ですね。CTRL-T を押します:

        if test -n a; then
           echo

挿入モードの CTRL-T コマンドは、'shiftwidth' の幅だけインデントを増やします。
カーソルの位置は関係ありません。
二行目を入力し、<Enter> を押して三行目を開始します。三行目のインデントは問題あ
りません。<Enter> を押して最後の行を入力します。テキストは次のようになりまし
た:

        if test -n a; then
           echo a
           echo "-------"
           fi

最後の行の余分なインデントを削除するには CTRL-D 押します。これは 'shiftwidth'
の幅だけインデントを減らします。カーソルの位置は関係ありません。
ノーマルモードでは ">>" コマンドと "<<" コマンドで同様の操作ができます。">" と
"<" はオペレータなので、他のオペレータと同様に、インデントを変更する範囲を三通
りの方法で指定できます。次の組み合わせが特に便利です:

        >i{

現在のブロックのインデントが増えます。変更されるのは {} の中だけで、{ と } 自
体の行は変更されません。">a{" なら {} も含まれます。次の例では、カーソルは
"printf" の上にあります:

        original text           after ">i{"             after ">a{"

        if (flag)               if (flag)               if (flag)
        {                       {                           {
        printf("yes");              printf("yes");          printf("yes");
        flag = 0;                   flag = 0;               flag = 0; 
        }                       }                           }

==============================================================================
30.5  タブとスペース

'tabstop' の初期設定は 8 です。変更することはできますが、それはトラブルの元に
なります。他のプログラムはあなたが使用しているタブ幅を知ることができません。そ
のようなプログラムでは、恐らくタブの幅は 8 であると仮定されているので、テキス
トが崩れて表示されてしまいます。また、ほとんどのプリンタはタブ幅を 8 で固定し
ています。したがって、'tabstop' を変更するのはお勧めしません。(他のタブ幅設定
で書かれたテキストを修正したい場合は 25.3 を参照してください。)
プログラムをインデントする場合、8 桁単位でインデントするとすぐに画面が埋まって
しまいます。しかしスペースが一つだけではインデントが目立ちません。多くのプログ
ラマは (折衷して) 4 桁を好んで使います。
<Tab> の幅は 8 桁で、インデントを 4 桁にしたいということは、<Tab> 文字を使って
インデントすることはできないということです。そのようなインデントには二つの方法
があります:

1.  <Tab> とスペースを混在させる。<Tab> は 1 つでスペース 8 個分の幅になるので
    ファイルサイズの節約になります。スペース 8 個より <Tab> の方が入力も削除も
    簡単です。

2.  スペースだけを使う。違うタブ幅を使う他のプログラムでもトラブルが起きませ
    ん。

Vim はどちらの方法もサポートしています。


タブとスペースを混在させる
--------------------------

タブとスペースを混在させる場合は特別な設定は必要ありません。初期設定でうまくい
きます。
'softtabstop' オプションを設定すると編集が少し楽になります。このオプションが設
定されると、タブ幅が 'softtabstop' の値に設定されたかのように、<Tab> キーが動
作します。しかし実際にはタブとスペースが混在して使われます。
次のコマンドを実行すると、<Tab> キーでカーソルが 4 桁ごとに進むようになります:

        :set softtabstop=4

行頭で <Tab> を押すと、スペースが 4 個挿入されます。次に <Tab> を押すと、最初
のスペース 4 個が削除されて <Tab> 文字が挿入されます (つまりカーソルは 8 列
目)。このように、スペースは可能な限り <Tab> 文字で置き換えられます。
バックスペースはその反対の動作になります。<BS> を押すと、'softtabstop' の幅だ
け削除されます。可能な限り <Tab> が使われ、余りはスペースになります。
次の図は、<Tab> をいくつか入力してから <BS> を使ったときの様子を示しています。
"." はスペースで "------->" は <Tab> です。

        入力                      結果
        <Tab>                     ....
        <Tab><Tab>                ------->
        <Tab><Tab><Tab>           ------->....
        <Tab><Tab><Tab><BS>       ------->
        <Tab><Tab><Tab><BS><BS>   ....

同様の動作は 'smarttab' オプションを使っても実現できます。このオプションを設定
した場合、インデントの入力のために <Tab> を押すと 'shiftwidth' の幅が使われ、
何かの文字より後ろでは実際の <Tab> 文字が使われます。ただし、<BS> の動作は
'softtabstop' のときと同様にはなりません。


スペースだけを使う
------------------

Tab 文字を一切使いたくない場合は 'expandtab' オプションを設定してください:

        :set expandtab

このオプションをオンにすると、<Tab> キーでスペースが入力されるようになります。
つまり、<Tab> 文字と同じ量のスペースが挿入され、<Tab> 文字は使われません。
バックスペースキーはスペースを一つずつ削除するので、<Tab> を押した後でそれを削
除するには <BS> を 8 回押さなければなりません。インデントの削除は CTRL-D を使
うと簡単です。


タブをスペースに変換する (あるいはその逆)
-----------------------------------------

'expandtab' を設定しても、それ以前に入力されたタブ文字は影響を受けません。つま
り、文章中のタブ文字はタブ文字のままです。タブ文字をスペースに変換したい場合
は、":retab" コマンドを使ってください。次のように使います:

        :set expandtab
        :%retab

すべてのインデントがスペースに変換されます。ただし、何かの文字より後ろにある
(インデント以外の) タブ文字はそのままです。それらのタブ文字も変換したい場合は
コマンドに ! を付けます:

        :%retab!

これは少し注意が必要です。なぜなら、文字列の中のタブ文字も変換されてしまうから
です。文字列の中でタブ文字が使われているかどうかは、次の検索パターンで確認でき
ます:

        /"[^"\t]*\t[^"]*"

文字列の中でタブ文字を使うのはお勧めしません。トラブルを避けるためにも "\t" を
使ってください。

同様に、スペースをタブ文字に変換できます:

        :set noexpandtab
        :%retab!

==============================================================================
30.6  コメントの整形

Vim のすばらしいところはコメントを解釈できるところです。コメントの整形を指示す
るだけで適切に処理してくれます。
例えば、次のようなコメントがあるとします:

        /*
         * This is a test
         * of the text formatting.
         */

最初の行に移動して次のコマンドを実行すると、コメントを整形できます:

        gq]/

"gq" はテキスト整形のためのオペレータです。"]/" はコメントの末尾に移動するコマ
ンドです。次のような結果になります:

        /*
         * This is a test of the text formatting.
         */

各行の行頭が適切に処理されていますね。
ビジュアルモードでテキストを選択してから "gq" を使う方法でも構いません。

新しい行を追加したい場合は、真ん中の行に移動して "o" を押します。次のような結
果になります:

        /*
         * This is a test of the text formatting.
         *
         */

行頭のスペースと * は自動的に挿入されるので、そのままコメントを入力することが
できます。テキストが 'textwidth' より長くなると自動的に改行されます。そのとき
も、行頭の * は自動的に挿入されます:

        /*
         * This is a test of the text formatting.
         * Typing a lot of text here will make Vim
         * break
         */

この機能を使うには 'formatoptions' の設定が必要です:

        r       挿入モードで <Enter> を押したときに * を挿入する
        o       ノーマルモードで "o" または "O" を使ったときに * を挿入する
        c       コメントを 'textwidth' の幅で改行する

詳しくは fo-table 参照。


コメントの定義
--------------

コメントの書式は 'comments' オプションで設定します。一行コメントと三部コメント
(開始、中間、終端からなるコメント) は分けて処理されます。
ほとんどの一行コメントは特定の文字で始まります。C++ は //、メイクファイルは #、
Vim は " です。例えば、C++ のコメントなら次のように設定します:

        :set comments=://

コロンはフラグとコメント文字の区切りです。'comments' の設定は次のような形式で
指定します:

        {flags}:{text}

この例のように、{flags} は空でも構いません。
複数のアイテムを指定するときはコンマで区切ります。アイテムを複数指定できるの
で、同じファイルの中でいろんな種類のコメントを使うことができます。例えばメール
を返信するときに、相手のメッセージに ">" や "!" を付けて引用する場合は、次のよ
うに設定します:

        :set comments=n:>,n:!

二つのアイテムが設定されました。一つは ">" で開始するコメント、もう一つは "!"
で開始するコメントです。"n" フラグが使われているので、コメントを入れ子にできま
す。つまり、">" で開始する行は、">" の後ろに他のコメントを含んでいても構いませ
ん。この設定により、次のようなメッセージを整形することができます:

        > ! Did you see that site?
        > ! It looks really great.
        > I don't like it.  The
        > colors are terrible.
        What is the URL of that
        site?

'textwidth' の設定を変更して (例えば 80 にして)、テキストを整形してみましょ
う。ビジュアルモードでテキストを選択してから "gq" を押します:

        > ! Did you see that site? It looks really great.
        > I don't like it.  The colors are terrible.
        What is the URL of that site?

違う種類のコメントテキストは混ざっていませんね。
二行目の "I" は一行目の末尾に入れることも可能ですが、しかし、一行目は "> !" で
始まり、二行目は ">" で始まっているため、それらのコメントは別のものであると判
断されます。


三部コメント (A THREE PART COMMENT)
------------

C のコメントは "/*" で始まり、中間には "*" が付き、"*/" で終わります。このよう
なコメントは次のように設定します:

        :set comments=s1:/*,mb:*,ex:*/

開始部分は "s1:/*" です。"s" は三部コメントの開始を示します。フラグとコメント
文字 "/*" をコロンで区切っています。フラグには "1" が指定されていますが、これ
により中間部分がスペース一個分、字下げされます。
中間部分は "mb:*" です。"m" は三部コメントの中間を示します。"b" フラグは、コメ
ント文字の後ろに空白が必要であることを示します。これを指定しないと、"*pointer"
などもコメントとして認識されてしまいます。
終端部分は "ex:*/" です。"e" は三部コメントの終端を示します。"x" は特殊なフラ
グです。中間の * が自動的に挿入された直後に "/" を押すと、余計なスペースが削除
されます。

詳細は format-comments を参照してください。

==============================================================================

次章: usr_31.txt  GUI を活用する

Copyright: see manual-copyright  vim:tw=78:ts=8:noet:ft=help:norl:
関連キーワード:  インデント, usr, 設定, Tab, コメント, コマンド, スペース, エラー, 文字, タブ