複数行のerrorformatをちょっと勉強した
TokyoVim#9に行ってきた - ぼっち勉強会でちょっと勉強した記録
エラーフォーマット自体のhelpはこれ。
:help errorformat
今回頑張っていたのは、複数行の対応。
:help errorformat-multi-line
準備
確認用のスクリプトはこれ。msgやformatをアレコレ変えて挙動を確認してた。
ちなみに元ネタはPHPUnitの結果をQuickfixに出すためのこの設定から。
vim-phpunit/compiler/phpunit.vim at master · afternoon/vim-phpunit · GitHub
function! s:test() let msg = [ \ '1) SampleTest::Error', \ 'Failed asserting that two strings are equal.', \ 'expected:1', \ 'actual:2', \ '', \ '/Users/kanno/.vim_sandbox/2012-08-04-1329.vim in 5', \ ] try let errorformat = &g:errorformat let &g:errorformat = '%E%n)\ %.%#,%Z%f\ in\ %l,%C%m,%-G%.%#' cgetexpr msg cwindow finally let &g:errorformat = errorformat endtry endfunction call s:test()
これを実行してQuickfixに表示されるのはこんな感じ
/Users/kanno/.vim_sandbox/2012-08-04-1329.vim|5 error 1| Failed asserting that two strings are equal. expected:1 actual:2
formatの理解
let &g:errorformat = '%E%n)\ %.%#,%Z%f\ in\ %l,%C%m,%-G%.%#'
まず、エラーフォーマットはカンマ区切りで複数設定出来る。
なので、上記設定は以下の4つが設定されていることになる。
- %E%n)\ %.%#
- %Z%f\ in\ %l
- %C%m
- %-G%.%#
次に、エラーフォーマットは設定順に適用される。
なので疑似コードで書くならこういうことになる。
if("%E%n)\ %.%#" に一致) {
} else if("%Z%f\ in\ %l" に一致) {
} else if("%C%m" に一致) {
} else if("%-G%.%#" に一致) {
} else {
}
条件が厳しいものを先に書かないと、期待しない動作になるので設定順は大事。
そしたら各設定の意味を一つずつ見ていく。
%E%n)\ %.%#
%Eは「複数行エラーメッセージの開始」なので、
複数行からなるメッセージの最初の行パターンに付ける必要がある。
ここからエラーメッセージ始まってますよ、と教えてあげるわけだ。
で、%nはエラー番号、「\ 」で半角スペース、「%.%#」は正規表現でいう「.*」と同じ。
%Z%f\ in\ %l
%Zは「複数行エラーメッセージの終了」なので、
複数行からなるメッセージの最後の行パターンに付ける必要がある。
ここでエラーメッセージ終わってますよ、と教えてあげるわけだ。
で、%fはファイル名、「\ 」で半角スペース、%lはエラー行番号
%C%m
%Cは「エラーメッセージの継続」を表す。
さっき%Eで始まったと思うけどこれはその続きの行だからね、と教えてあげるわけだ。
で、%mはエラーメッセージを示す。文字列なら何でも入ってくるんだと思う
この場合、設定順はかならず%Eや%Zの後にすること。
%mで一致するパターンが広すぎるので、%Eや%Zとして検知したかったパターンも拾われてしまうので。
%-G%.%#
%-Gは「このメッセージを無視する」ことを表す。
quickfixに取り込む内容として不適切な場合に取り除く的なことだと思う。
「%.%#」は正規表現でいう「.*」と同じ。
設定順が最後なので、上記どれにも当てはまらない場合は無視するようにしているわけ。
流れに沿っておさらい
つまり上記例にあるこのメッセージはこんな感じで解釈される
1) SampleTest::Error
Failed asserting that two strings are equal.
expected:1
actual:2
- 「1) SampleTest::Error」に対してパターン一致
- 「%E%n)\ %.%#」に一致
- 「%E」により複数行のエラーメッセージとして認識開始
- 「%E%n)\ %.%#」に一致
- 「Failed asserting that two strings are equal.」に対してパターン一致
- 「%E%n)\ %.%#」「%Z%f\ in\ %l」と順に当てはめていくが一致しない
- 「%C%m」に一致
- 「%C」により複数行のエラーメッセージとして認識
- 「expected:1」に対してパターン一致
- 同上
- 「actual:2」に対してパターン一致
- 同上
- 「」(空行)に対してパターン一致
- 「%E%n)\ %.%#」「%Z%f\ in\ %l」「%C%m」と順に当てはめていくが一致しない(%mは空行に一致しないっぽい)
- 「%-G%.%#」に一致(%.%#が何でも引っかかるので)
- 「%-G」により無視する行だと認識
- 「/Users/kanno/.vim_sandbox/2012-08-04-1329.vim in 5」に対してパターン一致
- 「%E%n)\ %.%#」と順に当てはめていくが一致しない
- 「%Z%f\ in\ %l」に一致
- 「%Z」により複数行のエラーメッセージの終行だと認識して終わり
きっとこういうことなんだと思う。