Vimユーザーとしては、Vimでソースコードを編集しながら、随時コンパイルや実行ができた方がよい。いちいちターミナルに戻ってコマンドを入力するのは面倒だ。プログラムのコンパイルや実行をVimから指示させるようにする最も簡単な方法は、Makefileを使う方法だ。Vimにはmakeコマンドがあり、外部のmakeコマンドが実行できるようになっている。例えばここでは次のようなMakefileを用意する。
build: clang -o hello hello.c run: ./hello clean: rm -f hello
行頭から始まり、「:」で終わっている行がターゲット、その次からの行がターゲットの処理内容となる。ターゲットの次の行からは、行頭が「タブ」になっている点に注意しておこう。ここが空白では別の意味になってしまう。また、make(1)コマンドの引数に何も指定しないと、最初のターゲットが実行される。この場合はbuild:の次の行が実行される。通常、ビルド処理が一番上に来るように記述しておく。Makefileを作成したら、次のようにmakeコマンドを実行することで、Makefileに記載した内容を実行できる。
% make clang -o hello hello.c % make run ./hello % make clean rm -f hello %
鋭い方ならもうお気付きかもしれない。この仕組みは、Vimをプログラムのビルドのみならず、さまざまな外部コマンドと連携させることに利用できるのだ。例えばビルドに「Ctrl-b」、実行に「Ctrl-u」、デバッグウィンドウ(というかQuickfix)にF5などをショートカットキーとして割り当て、それぞれ:make、:make run、:copenなどに結び付けておけば、同じショートカットキーで、さまざまなプログラムのビルドに対応させることができる。
ビルドのみならず実行したいコマンドをMakefileに書いておけばそれが実行されるので、Makefileの内容次第でいろいろなことができる。LaTeXのビルドにしておいてもよいし、特定のコマンドの実行にしておいてもよいだろう。
Vimでhello.cファイルを開いて、ノーマルモードで「:make[Enter]」と入力すると、次のようにビルドが実行される(図7)。
「:make run[Enter]」とすれば、次のようにプログラムが実行される(図8)。
図8 Vimからプログラムを実行したところ。クリックすると拡大
次は、わざとコンパイルに失敗してみよう。まず、「return 0;」の行を次のように「printf("hello world!\n");」へ書き換える。いわゆる最初に作成するHello Worldプログラムだ。
int main(void) { printf("hello world!\n"); }
ノーマルモードで「:make[Enter]」と入力すると次のようにエラーが表示される(図9)。printfが暗黙的に使われているので、ヘッダをインクルードするか、またはprintfを定義するように、というメッセージが表示されている。Clangは、このようなメッセージが丁寧で分かりやすい。
ノーマルモードで「:copen[Enter]」と入力すると、下側に新しいウィンドウが表示される。エラーメッセージの一覧を表示するウィンドウ(Quickfix)で、統合開発環境で言うところのデバッグウィンドウなどに相当する。このウィンドウで該当するエラーメッセージまで移動し[Enter]キーを押すと、ソースコードの該当する行にジャンプする(図10)。便利な機能だ。
指示に従い、行の先頭に「#include 」を追加する。
もう一度「:make[Enter]」と実行すると、ちゃんとビルドに成功する。「:make run[Enter]」でプログラムの動作も確認できる。
ノーマルモードで実行する「:make[Enter]」や「:make run[Enter]」は、プログラムを作成する段階ではよく使うことになる。ショートカットキーを設定しておくと便利だ。例えば、ファイルを保存してビルドを「Ctrl-b」、実行を「Ctrl-u」と割り当てるには、次の設定を~/.vimrcに追加しておけばよい。次の設定であれば挿入モードからも同様のショートカットで処理を実行できる。
nmap :write:make imap :write:make nmap :make run imap :make run
エラーが表示されていたウィンドウも、ワンタッチで表示・非表示が切り替えられれば便利だ。開くコマンドは「:copen」で、閉じるコマンドが「:cclose」なので、この2つを切り替えて実行するようにVimスクリプトを書けば良い。次のような感じで良いだろう。
let s:quickfixwindow = "close" function! b:openCloseQuickfix() if "open" ==? s:quickfixwindow let s:quickfixwindow = "close" cclose else let s:quickfixwindow = "open" copen endif endfunction nmap :call b:openCloseQuickfix() imap :call b:openCloseQuickfix()
ここではファンクションキーのF5に割り当ててみた。ビルド、実行、エラー一覧表示はなにかと便利な機能なので、Makefileの扱い方と同時に覚えてしまいたい。今回紹介した内容を設定するだけで、プログラムの作成と実行作業において、いちいちVimを終了してターミナルに戻るということはなくなるはずだ。
後藤大地
オングス代表取締役。@ITへの寄稿、MYCOMジャーナルにおけるニュース執筆のほか、アプリケーション開発やシステム構築、『改訂第二版 FreeBSDビギナーズバイブル』『D言語パーフェクトガイド』『UNIX本格マスター 基礎編〜Linux&FreeBSDを使いこなすための第一歩〜』など著書多数。
Copyright © ITmedia, Inc. All Rights Reserved.