Vim script のエラーを出力する quickrun-outputter

元ネタ:関数対応版:Vim scriptをsourceしてエラーがあればquickfixに表示する - ぼっち勉強会


Vim script のエラー出力はちょっと特殊で、関数内でエラーが出た場合、その関数内の相対的な行番号を返すというすごく不親切なフォーマットだったりします。
わたしも前から欲しいと思っていたんですが、上記の理由によりパースがちとめんどくさいので放置していたんですが、 quickrun-outputter で実装してみました。


上記のブログのコードをそのまま使用すれば簡単かなー、と思っていたんですがわたしの環境だとうまくパースされなかったので結局フルスクラッチする事に…。
エラーフォーマットが違ったりするんだろうか…。
とりあえず、こんな感じ。

[ソース]

function! s:vsqf_funcname(line)
    let funcname  = matchstr(a:line, 'function.*<SNR>\d*_\zs.*\ze,')
    return empty(funcname) ? matchstr(a:line, 'function \zs.*\ze,') : funcname
endfunction


function! s:vsqf_lnum(filelines, line)
    let funcname = s:vsqf_funcname(a:line)
    let lnum = matchstr(a:line, '.*行 \zs\d*\ze')
    if empty(lnum)
        return -1
    else
        return (empty(funcname) ? 0 : match(a:filelines, 'function.*'.funcname.'\s*(') + 1) + lnum
    endif
endfunction

function! s:make_vim_script_qflist(filename, errors)
    let filelines = readfile(a:filename)
    let errors    = a:errors
    let bufnr     = bufnr(a:filename)
    return map(a:errors, '{
\       "bufnr" : bufnr,
\       "lnum" : s:vsqf_lnum(filelines, v:val),
\       "text" : v:val,
\}')
endfunction


let s:outputter = quickrun#outputter#buffered#new()
let s:outputter.name = "quickfix_vim_script"
let s:outputter.kind = "outputter"

function! s:outputter.finish(session)
    let messages = self._result
    let file     = a:session.config.srcfile

    let qflist= s:make_vim_script_qflist(file, split(messages, "\n"))
    call setqflist(qflist, 'r')

    copen
    for winnr in range(1, winnr('$'))
        if getwinvar(winnr, '&buftype') ==# 'quickfix'
            call setwinvar(winnr, 'quickfix_title', 'quickrun: ' .
            \    join(a:session.commands, ' && '))
            break
        endif
    endfor
endfunction
call quickrun#module#register(s:outputter, 1)
unlet s:outputter


" example
" :QuickRun -outputter quickfix_vim_script


あんまり動作テストしていないけどだいたい動いている感じ。
上記の場合は、実行したバッファ上の Vim script のみパースしているのでバッファ外のエラーは考慮していません。