quickrun でシンタックスチェックを行う

最近、某マンボウに背びれでペチペチ叩かれながらプラグイン化するにあたって色々と思案していたりします。
手元の環境では既に実装済みなんですが、プラグイン化するにあたって細かい仕様考えをまとめるのがむずい…。。
ぶっちゃけ、シンタックスチェックであれば既存の quickrun.vim の機能で十分なので、どの部分をプラグインにするかというのが一番の問題だったりするんですが。
適当に ghc-mod や jshint を呼び出す quickrun_config を書けばええねん。
と、いうことで現状の考えとかなどをちょっとまとめてみた。

[シンタックスチェックとは]

quickrun.vimシンタックスチェックというと『何か特別な設定がいるのか』と思われがちですが、基本的に各言語の処理系と同じように jshint や ghc-mod を呼び出す config を設定するだけです。
例えば、こんな感じ。

" g:quickrun_config に各シンタックスチェックを行うための config を追加する
" シンタックスチェックを行う場合は、
" :QuickRun syntax_checker/jshint
" のように任意の処理系を呼び出すだけ

let g:quickrun_config = {
\
\   "syntax_checker/g++" : {
\       "command"   : "g++",
\       "exec"      : "%c %o %s:p ",
\       "cmdopt"    : "-fsyntax-only -std=gnu++0x -Wall",
\   },
\
\   "syntax_checker/msvc" : {
\       "command"   : "cl",
\       "exec"      : "%c %o %s:p ",
\       "cmdopt"    : "/Zs /W3",
\   },
\
\   "syntax_checker/ruby" : {
\       "command" : "ruby",
\       "exec"    : "%c %s:p %o",
\       "cmdopt"  : "-c",
\   },
\
\   "syntax_checker/jshint" : {
\       "command" : "jshint",
\       "exec"    : "%c %s:p",
\       "quickfix/errorformat" : "%f: line %l\\,\ col %c\\, %m",
\   },
\
\   "syntax_checker/ghc-mod" : {
\       "command" : "ghc-mod",
\       "exec"    : "%c %o check %s:p",
\       "cmdopt"  : '--hlintOpt="--language=XmlSyntax"',
\   },
\
\}


ざっくりと設定してみましたがなんとなくやっていることは分かると思います。
細かい設定(outputter や runner)は必要ですが、基本的にはこれで問題ないと思います。

[もう少し突っ込んだシンタックスチェックに関して]

各処理系を呼び出すだけであれば上記のように g:quickrun_config に設定するだけでいいんですが、多分それだけでは満足しないと思います。
例えば、他に欲しい機能としては、

  • 任意のタイミング(ファイル保存時等)で自動的にシンタックスチェックを行なって欲しい
  • エラー箇所をハイライトして欲しい
  • エラーがあった場合にエラー内容を出力して欲しい
  • もちろん処理は非同期で!


などと言ったような事があげられるかと思います。
まぁ IDE に付いているような静的シンタックスチェックってやつですね。
しかし、ここら辺の機能は既に quickrun.vim実装済みです。

[バックエンドに quickrun.vim を使用]

余談ですが、わたしが quickrun.vim を選んだ理由として。

  • 標準で非同期処理(vimproc)に対応している
  • config で細かい設定が可能
  • hook を利用した幅広い拡張性


があります。
非同期処理に関しは言わずもがな。
syntastic は非同期処理に対応していないのが使用していない一番の理由になります。
quickrun.vim の config は g:quickrun_config を書いたことがある人ならわかると思いますが、かなり細かいところまで設定を行うことが出来ます。
更に 0.6.0 で追加された hook 機能を使用すれば、ユーザ側でありとあらゆる拡張を行うことが出来ます。
例えば、わたしの場合は、hook 機能を利用して

  • 出力がなかった場合 buffer を閉じる
  • エラーの場合は unite-quickfix へと出力を行う
  • 終了時に :HierUpdate のようなコマンドを呼び出す
  • 実行中にアニメーションの出力
  • コンパイルオプションにインクルードディレクトリの追加


などと言ったような事を行なっています。
やりたい放題し放題。
quickrun.vim チョーイイネサイコー!

[プラグイン化するにあたって]

ここからシンタックスチェックを行うプラグインの話。
上記を読んでもらえれば機能的には quickrun.vim で十分だということがわかってもらえると思います。
では、プラグイン側で何をするのかというと、
g:quickrun_config に上記で書いた syntax_checker の設定を追加する』
という事をやろうかと考えています。
あといくつか便利な quickrun-hook も公開する予定。
使い方としては、

" コマンド呼び出し
" QuickRun {filetype}/watchdog_checker -hook/extend_config/enable 1 -hook/extend_config/force 1

" ユーザ側で定義する g:quickrun_config
" {filetype}/watchdog_checker.type で filetype ごとに使用する watchdog_checker を設定する
" その他の細かい設定は {filetype}/watchdog_checker に直接記述する
let g:quickrun_config = {
\   "_" : {
\       "outputter/buffer/running_mark" : "バン(∩`・ω・)バンバンバンバン゙ン",
\   },
\
\   "cpp/watchdog_checker" : {
\       "type" : "watchdog_checker/msvc",
\       "hook/output_encode/encoding" : "sjis",
\   },
\
\}

" g:quickrun_config に config を追加する処理を呼ぶ
call watchdog#setup(g:quickrun_config)


" ------------- ここまでがユーザ側の処理 -------------


" プラグイン側で用意する quickrun_config
" シンタックスチェックを行うための各ツールの config を定義する
let g:watchdog_config = {
\
\   "cpp/watchdog_checker" : {
\       "type" : "watchdog_checker/g++"
\   },
\
\   "ruby/watchdog_checker" : {
\       "type" : "watchdog_checker/ruby"
\   },
\
\   "javascript/watchdog_checker" : {
\       "type" : "watchdog_checker/jshint"
\   },
\
\   "haskell/watchdog_checker" : {
\       "type" : "watchdog_checker/ghc-mod"
\   },
\
\   "watchdog_checker/_" : {
\       "runner" : "vimproc",
\       "outputter" : "quickfix",
\       "hook/hier_update/enable_exit" : 1,
\       "hook/quickfix_stateus_enable/enable_exit" : 1,
\   },
\
\   "watchdog_checker/g++" : {
\       "command"   : "g++",
\       "exec"      : "%c %o %s:p ",
\       "cmdopt"    : "-fsyntax-only -std=gnu++0x -Wall",
\   },
\
\   "watchdog_checker/msvc" : {
\       "command"   : "cl",
\       "exec"      : "%c %o %s:p ",
\       "cmdopt"    : "/Zs /W3",
\   },
\
\   "watchdog_checker/clang++" : {
\       "command"   : "clang",
\       "exec"      : "%c %o %s:p ",
\       "cmdopt"    : "-fsyntax-only -std=gnu++0x -Wall",
\   },
\
\   "watchdog_checker/ruby" : {
\       "command" : "ruby",
\       "exec"    : "%c %s:p %o",
\       "cmdopt"  : "-c",
\   },
\
\   "watchdog_checker/jshint" : {
\       "command" : "jshint",
\       "exec"    : "%c %s:p",
\       "quickfix/errorformat" : "%f: line %l\\,\ col %c\\, %m",
\   },
\
\   "watchdog_checker/ghc-mod" : {
\       "command" : "ghc-mod",
\       "exec"    : "%c %o check %s:p",
\       "cmdopt"  : '--hlintOpt="--language=XmlSyntax"',
\   },
\
\}


こんな感じになると思います。
プラグイン側で各シンタックスチェックの config を用意して、ユーザ側で filetype ごとに使用するシンタックスチェックを選んでもらう。って形になるかと。
その他、細かい設定や拡張は g:quickrun_config に直接記述してしまえばいいのでだいぶ使い勝手はいいんじゃないだろうかと。
実装もすっきりしますし。
エラーのハイライトとかも quickfix に出力して hier.vim などの外部プラグインに丸投げする予定です。
使えるものは使えばええんや!
あ、あと適当な autocmd もプラグイン側で用意する予定。

[その他]

今のところの構想とかはこんな感じです。
他にシンタックスチェックを行う上で欲しい機能とかがあれば教えてください!!