quickrun.vim について語る

この記事は Vim Advent Calendar 2012 101日目の記事になります。
お陰様で100日目を迎えることが出来ました。
Vim Girl ちゃんかわいいよ Vim Girl ちゃん。


参加者はまだまだ募集中なのでとっておきのネタやプラグインなんかを紹介してみるといいと思います。
また、既に参加していて2回目もやりたい!って方はこの記事へコメントして頂けばスケジュールに追加するのでぜひ!

[quickrun.vim について]

quickrun.vim とはバッファ上のソースコードを実行して、その実行結果を Vim へ出力する為のプラグインです。
quickrun.vim を使用する事で、素早くソースコードを実行することができ、また Vim との連携を高めることが出来ます。


[導入方法]

quickrun.vimgithub で公開されておりそこから取得する事が出来ます。


Vimプラグインを使用する場合、いくつか手段があります。
git が導入されていれば、neobundle.vim を使用すると比較的簡単にプラグインを管理する事が出来ます。
neobundle.vim でのプラグインの導入方法は下記を参照してみて下さい。


それ以外には pathogen を使用するのが簡単かと思います。
こちらは git が必要なく、指定したディレクトリにプラグインを展開するだけなので比較的敷居が低いです。

[使ってみる]

実際に使ってみます。
Vim を起動させて適当な無名のバッファにコード(今回は Ruby)を記述します。

# 適当な Ruby のコード
10.times { puts "ruby" }


コードを記述し終わったら

:QuickRun ruby


でバッファ上のコードが Ruby のコードとして実行されます。
実行後にコードの実行結果が Vim 上に出力されているのがわかると思います。
またこの時にコードをファイルに保存せずに実行する事が出来るのも quickrun.vim の利点の一つです。



このように :QuickRun コマンドに type (上記の場合だと ruby)を渡して、その type でコードの実行を行います。
:QuickRun コマンドに type が渡されなかった場合には実行したバッファの filetype の値が使用されます。


2013/03/11 現在 quickrun.vim では下記の言語・環境に対応しています。

awk bash c c/C c/clang c/gcc c/vc clojure clojure/clj clojure/jark coffee cpp cpp/C cpp/clang++ cpp/g++ cpp/vc cs cs/csc cs/dmcs cs/gmcs cs/mcs cs/smcs d d/gdc d/ldc d/rdmd dart dart/dart/checked dart/dart/production dosbatch erlang eruby fortran fortran/gfortran go groovy haskell haskell/ghc haskell/ghc/core haskell/runghc io java javascript javascript/cscript javascript/nodejs javascript/phantomjs javascript/rhino javascript/spidermonkey javascript/v8 jsx lisp llvm lua markdown markdown/Markdown.pl markdown/bluecloth markdown/kramdown markdown/markdown_py markdown/pandoc markdown/redcarpet ocaml perl perl6 php python r ruby rust scala scheme scheme/gauche scheme/mzscheme sed sh typescript vim wsh zsh


上記に書かれている coffee cpp/g++javascript/nodejs などといったものが :QuickRun コマンドへ渡すことが出来ます。
quickrun.vim がいかにパワフルなのかがわかるかと思います。

[quickrun.vim の動作を制御する]

type 以外にも :QuickRun コマンドにオプションを渡すことで quickrun.vim の動作を制御する事が出来ます。
例えば下記のような感じ。

" 一番下にウィンドウを分割させて出力
:QuickRun -outputter/buffer/split ":botright"

" ウィンドウの高さを指定する場合
:QuickRun -outputter/buffer/split ":botright 8sp"

" 出力がなかった場合に出力バッファを自動的に閉じる
:QuickRun -outputter/buffer/close_on_empty 1

" quickfix へと出力する
:QuickRun -outputter quickfix

" 実行時間を計測し、その結果も最後に出力する
:QuickRun ruby -hook/time/enable 1


このように :QuickRun コマンドにオプションを渡すことで quickrun.vim の動作を制御する事が出来ます。


その他のオプションについては

:help quickrun-commands

:help quickrun-options

などを参照して下さい。

[quickrun_config を設定]

:QuickRun コマンドにオプションを渡すことで quickrun.vim を制御できることが分かったと思います。
しかし、毎回 :QuickRun コマンドにオプションを渡すのは手間です。
そういう時は g:quickrun_config を使用します。
g:quickrun_config を使用することで任意の type に対してオプションのデフォルト値を設定することが出来ます。


g:quickrun_config は type 名をキーとした辞書で定義します。
例えば、cpp/g++ に対して設定したい場合は、

" g++ のコマンドラインオプションを追加する
" 実行時間を計測する
let g:quickrun_config = {
\   "cpp/g++" : {
\       "cmdopt" : "-std=c++0x",
\       "hook/time/enable" : 1
\   },
\}


というような設定になります。
これで

:QuickRun cpp/g++

とした場合に -cmdopt "-std=c++0x"-hook/time/enable 1 が自動的に設定されます。


また、キーには type ではなくて "_" を使用することで全ての type に対するデフォルト値を設定することができます。
* ではなくて _ です。
*は古い設定方法なので _ を使用しましょう


これを利用すると
全ての type で出力バッファのウィンドウを一番下に開き、出力がなかった場合に出力バッファを閉じる
という設定は下記のような定義になります。

let g:quickrun_config = {
\   "_" : {
\       "outputter/buffer/split" : ":botright",
\       "outputter/buffer/close_on_empty" : 1
\   },
\}


g:quickrun_config の設定方法に関しては quickrun.vim がデフォルトで設定しているコードを見るのがわかりやすいかと思います。
(quickrun_config のデフォルト値は g:quickrun#default_config に設定されています。


と、いう事で quickrun.vim を使用する場合、まずは g:quickrun_config を自分好み設定していくのがいいと思います。
g:quickrun_config の設定方法さえ理解してしまえば quickrun.vim の使い勝手がだいぶよくなります。


他にも b:quickrun_config にも設定することができますが、それに関しては

:help b:quickrun_config

を参照して下さい。
また b:quickrun_config は g:quickrun_config とは設定方法が微妙に違うので注意して下さい。

[:QuickRun を非同期に実行する]

デフォルトでは :QuickRun を行なっている間は Vim を操作することはできません。
しかし、いくつかの手段を用いる事で :QuickRun 中でも Vim を操作する事が出来るようになります。
今回は vimproc を使用して、quickrun.vim を非同期に処理したいと思います。
vimproc を使用するためには別途プラグインを導入する必要があります。


こちらのプラグインは予め .c ファイルをビルドしておく必要があるので注意して下さい。
neobundle.vim を使用しているのであれば下記の設定で自動的に vimproc のビルドを行なってくれます。

NeoBundle 'Shougo/vimproc', {
    \ 'build' : {
    \     'windows' : 'make -f make_mingw32.mak',
    \     'cygwin' : 'make -f make_cygwin.mak',
    \     'mac' : 'make -f make_mac.mak',
    \     'unix' : 'make -f make_unix.mak',
    \    },
    \ }

詳しくは、

:help vimproc-install

を参照して下さい。


さて、vimproc の導入が終わったのであれば -runner に vimproc を設定することで非同期に :QuickRun を実行する事が可能です。

:QuickRun -runner vimproc



非同期処理は quickrun.vim を使用する上でほぼ必須の機能だと思うので g:quickrun_config に設定しておくといいと思います。

" runner/vimproc/updatetime で出力バッファの更新間隔をミリ秒で設定できます
" updatetime が一時的に書き換えられてしまうので注意して下さい
let g:quickrun_config = {
\   "_" : {
\       "runner" : "vimproc",
\       "runner/vimproc/updatetime" : 60
\   },
\}


これで重い処理を行なっている間でも Vim を操作することが出来ますね。

[:QuickRun を終了させる]

:QuickRun を終了させたい場合は下記のマッピングを設定しておくと便利です。

" <C-c> で実行を強制終了させる
" quickrun.vim が実行していない場合には <C-c> を呼び出す
nnoremap <expr><silent> <C-c> quickrun#is_running() ? quickrun#sweep_sessions() : "\<C-c>"

[出力箇所を変更する]

quickrun.vim では -outputter に出力箇所を設定する事で Vim のバッファ以外にも様々な場所へと出力する事が出来ます。
例えば、quickfix へ出力したい場合は下記のような設定になります。

" 実行結果を quickfix へと出力する
: QuickRun -outputter quickfix



他にも指定したファイルやブラウザなんかへと出力する事が出来ます。
特に HTML を吐き出すようなコードの場合はブラウザへ出力するようにするといいと思います。
他の出力箇所に関しては、

:help quickrun-module-outputter

を参照して下さい。

[実行に失敗した時のみ quickfix へ出力する]

さて、上記の設定では常に quickfix へと出力を行います。
しかし、実行に成功した時には buffer へと出力して欲しいと思います。
そういう時に outputter/error を使用することで実行の成功時と失敗時で出力先を変更する事が出来ます。

" 実行が成功すればバッファへ、失敗すれば quickfix へ出力する
:QuickRun -outputter error -outputter/error/success buffer -outputter/error quickfix

[独自の設定を定義する]

g:quickrun_config には独自の設定を定義することも出来ます。

let g:quickrun_config = {
\   "my_cpp" : {
\       "command"   : "C:/gcc/gcc4_8/bin/g++.exe",
\       "exec" : "%c %o %s:p",
\       "cmdopt" : "-std=c++0x -Wall -pedantic",
\   },
\}


上記のような設定を g:quickrun_config へ定義すると

:QuickRun my_cpp


でその設定を使用して :QuickRun を行なってくれます。
また、g:quickrun_config[{filetype}].type に設定名を設定するとその filetype の時にその設定名が適用されます。

" filetype=cpp 時には my_cpp の設定を使用する
let g:quickrun_config = {
\   "cpp" :{
\       "type" : "my_cpp"
\   },
\   "my_cpp" : {
\       "command"   : "C:/gcc/gcc4_8/bin/g++.exe",
\       "exec" : "%c %o %s:p",
\       "cmdopt" : "-std=c++0x -Wall -pedantic",
\   },
\}

[言語に対して複数の type を定義する]

C++ のように複数のコンパイラが存在する場合など頻繁に切り換えるような設定を予め複数設定しておけば素早く設定を切り換えることが出来ます。

" unite-quickrun_config を使用する場合は {filetype}/ を prefix として使用する
let g:quickrun_config = {
\   "cpp" :{
\       "type" : "cpp/gcc4_8"
\   },
\
\   "cpp/gcc4_6_3" : {
\       "command"   : "C:/gcc/gcc4_6_3/bin/g++.exe",
\       "exec" : "%c %o %s:p",
\       "cmdopt" : "-std=c++0x -Wall -pedantic",
\   },
\
\   "cpp/gcc4_8" : {
\       "command"   : "C:/gcc/gcc4_8/bin/g++.exe",
\       "exec" : "%c %o %s:p",
\       "cmdopt" : "-std=c++0x -Wall -pedantic",
\   },
\
\   "cpp/gcc4_8_03" : {
\       "command"   : "C:/gcc/gcc4_8/bin/g++.exe",
\       "exec" : "%c %o %s:p",
\       "cmdopt" : "-Wall -pedantic",
\   },
\
\   "cpp/clang3_1" : {
\       "command"   : "C:/llvm/BUILD_3_1/bin/clang++",
\       "exec" : "%c %o %s -o %s:p:r ",
\       "cmdopt"    : "-std=gnu++0x",
\   },
\
\}

" gcc 4.8 でコンパイルする
" :QuickRun cpp/gcc4_8

" gcc 4.8 で C++03 としてコンパイルする
" :QuickRun cpp/gcc4_8_03

" clang 3.1 でコンパイルする
" :QuickRun cpp/clang3_1


設定を変更する場合は unite-quickrun_config を使用すると便利です。
コンパイラ以外にもよく使用するオプションや環境によって切り替えたい設定なども予め定義しておくと捗ります。
他にもテストを行う設定やシンタックスチェックを行う設定を追加しておくと便利だと思います。

[まとめ]

簡単にですが quickrun.vim について紹介してみました。
このように quickrun.vim はとても柔軟にできておりデフォルトで用意されている設定も豊富です。
g:quickrun_config を使用することで自分好みの設定を自由にカスタマイズする事が出来ます。


また、コードを実行させるだけではなくて『任意のコマンドの実行結果を任意の箇所へと出力する』という点を利用すると非同期に対応していることも相まって様々な用途に使用することが出来ると思います。
(例えばこんな事とか。
make を行うような設定も g:quickrun_config に定義しておけば quickrun.vim から make する事ができ、その出力結果も Vim で参照する事が出来るので便利だと思います。


今回はあまり紹介出来ませんでしたが、quickrun-module を利用することでユーザ側が自由に出力箇所を設定できたり、任意のタイミングで処理をフックしたりする事が出来ます。
デフォルトで用意されている quickrun-module で満足できなくなってきたら自分で quickrun-module を作ってみるのもいいと思います。
quickrun-module-hook だと用意されているタイミングで自由に処理をフックする事が出来るのでかなり使い勝手がよいです。


と、いう事で quickrun.vim について書いてみました。
quickrun.vim の可能性は無限大なのでみなさんもどんどん拡張してみましょう!

[さらに quickrun.vim 力を高める]

とりあえず、ここら辺を読んでみるといいと思います。
あと 1500行以上あるわたしの quickrun.vim の設定も公開しておきます。


気になる方は眺めてみると面白いかもしれません。