job機能を使って非同期にエラーをチェックできるサンプルコードを書きました。
ESLintでJavaScriptのコードをチェックするサンプルを2通り掲載します。
:wなどでバッファの内容をファイルに書き込む時、非同期でエラーをチェックし、エラーがあればQuickFixにエラーを表示させます。
job機能が利用できるVimが必要です。:echo has('job')
で0が返るVimでは動作しません。
テンポラリファイルにエラーを書き出すパターン
sample.js
if(){
check.vim
function!s:callback(file, channel) abort
execute 'cgetfile ' . a:filecwindowwincmdp
echo 'finish'endfunctionfunction!s:check() abort
seterrorformat=%f:\ line\ %l\\,\ col\ %c\\,\ %m,%-G%.%#
letl:file= tempname()let job = job_start(add(split('eslint -f compact'), expand('%')), {
\ 'out_io': 'file',
\ 'out_name': l:file,
\ 'close_cb': function('s:callback', [l:file]),
\ })endfunction
augroup sample
autocmd!autocmdBufWritePost *.jscall<SID>check()
augroup END
Vim起動
vim -Nu NONE -S check.vim sample.js
ここで:wでファイルに保存するとQuickFixにエラーが表示されます。
QuickFixの内容
js|1col5|Error-Parsingerror:Unexpectedtoken)
バッファにエラー内容を出力するパターン
sample.js
if(){
check2.vim
function!s:callback(channel) abort
execute 'cgetbuffer ' . s:bufnr
cwindowwincmdp
execute 'bwipeout ' . s:bufnr
unlet s:bufnr
echo 'finish'endfunctionfunction!s:check() abort
seterrorformat=%f:\ line\ %l\\,\ col\ %c\\,\ %m,%-G%.%#
newlets:bufnr = bufnr('')setlocalbufhidden=hidesetlocalbuftype=nofile
hidelet job = job_start(add(split('eslint -f compact'), expand('%')), {
\ 'out_io': 'buffer',
\ 'out_buf': s:bufnr,
\ 'close_cb': function('s:callback'),
\ })endfunction
augroup sample
autocmd!autocmdBufWritePost *.jscall<SID>check()
augroup END
ウィンドウを表示せずにバッファを開く方法が分からなかったので:newでバッファを作成した後、:hideでそのバッファのウィンドウを閉じています。
:1newで小さいウィンドウを作成したほうが良いのか迷いましたが、:newから:hideまで違和感がなかったのでサイズ指定せずに:newでウィンドウを作成しました。
Vim起動
vim -Nu NONE -S check2.vim sample.js
ここで:wでファイルに保存するとQuickFixにエラーが表示されます。
テンポラリファイルを利用したサンプルと同様のエラー内容が表示されました。
QuickFixの内容
js|1col5|Error-Parsingerror:Unexpectedtoken)
非同期ではないサンプル
おまけ。
チェックが終わるまでカーソルを動かせません。
function!s:check() abort
seterrorformat=%f:\ line\ %l\\,\ col\ %c\\,\ %m,%-G%.%#
cgetexpr system('eslint -f compact ' . fnameescape(expand('%')))cwindowendfunction
augroup sample
autocmd!autocmdBufWritePost *.jscall<SID>check()
augroup END