diff --git a/plugin/ale/zmain.vim b/plugin/ale/zmain.vim index 2db0d028..994422f2 100644 --- a/plugin/ale/zmain.vim +++ b/plugin/ale/zmain.vim @@ -14,18 +14,20 @@ let s:job_linter_map = {} let s:job_output_map = {} function! s:ClearJob(job) - if a:job != -1 - let linter = s:job_linter_map[a:job] + let linter = s:job_linter_map[a:job] + if has('nvim') call jobstop(a:job) - call remove(s:job_output_map, a:job) - call remove(s:job_linter_map, a:job) - - let linter.job = -1 + else + call job_stop(a:job) endif + + call remove(s:job_output_map, a:job) + call remove(s:job_linter_map, a:job) + call remove(linter, 'job') endfunction -function! s:GatherOutput(job, data, event) +function! s:GatherOutput(job, data) if !has_key(s:job_output_map, a:job) return endif @@ -33,6 +35,14 @@ function! s:GatherOutput(job, data, event) call extend(s:job_output_map[a:job], a:data) endfunction +function! s:GatherOutputNeoVim(job, data, event) + call s:GatherOutput(a:job, a:data) +endfunction + +function! s:GatherOutputVim(channel, data) + call s:GatherOutput(ch_getjob(a:channel), [a:data]) +endfunction + function! s:LocItemCompare(left, right) if a:left['lnum'] < a:right['lnum'] return -1 @@ -53,7 +63,7 @@ function! s:LocItemCompare(left, right) return 0 endfunction -function! s:HandleExit(job, data, event) +function! s:HandleExit(job) if !has_key(s:job_linter_map, a:job) return endif @@ -90,23 +100,50 @@ function! s:HandleExit(job, data, event) " matchadd('ALEError', '\%200l\%17v') endfunction -function! s:ApplyLinter(linter) - " Stop previous jobs for the same linter. - call s:ClearJob(a:linter.job) +function! s:HandleExitNeoVim(job, data, event) + call s:HandleExit(a:job) +endfunction - let a:linter.job = jobstart(a:linter.command, { - \ 'on_stdout': 's:GatherOutput', - \ 'on_exit': 's:HandleExit', - \}) +function! s:HandleExitVim(channel) + call s:HandleExit(ch_getjob(a:channel)) +endfunction + +function! s:ApplyLinter(linter) + if has_key(a:linter, 'job') + " Stop previous jobs for the same linter. + call s:ClearJob(a:linter.job) + endif + + if has('nvim') + let a:linter.job = jobstart(a:linter.command, { + \ 'on_stdout': 's:GatherOutputNeoVim', + \ 'on_exit': 's:HandleExitNeoVim', + \}) + else + " Vim 8 will read the stdin from the file's buffer. + let a:linter.job = job_start(a:linter.command, { + \ 'out_mode': 'nl', + \ 'err_mode': 'nl', + \ 'out_cb': function('s:GatherOutputVim'), + \ 'close_cb': function('s:HandleExitVim'), + \ 'in_io': 'buffer', + \ 'in_buf': bufnr('%'), + \}) + + call ch_close_in(job_getchannel(a:linter.job)) + endif let s:job_linter_map[a:linter.job] = a:linter let s:job_output_map[a:linter.job] = [] - call jobsend(a:linter.job, join(getline(1, '$'), "\n") . "\n") - call jobclose(a:linter.job, 'stdin') + if has('nvim') + " For NeoVim, we have to send the text in the buffer to the command. + call jobsend(a:linter.job, join(getline(1, '$'), "\n") . "\n") + call jobclose(a:linter.job, 'stdin') + endif endfunction -function! s:TimerHandler() +function! s:TimerHandler(...) let filetype = &filetype let linters = ALEGetLinters(filetype) @@ -129,7 +166,6 @@ function! ALEAddLinter(filetype, linter) endif call add(s:linters[a:filetype], { - \ 'job': -1, \ 'command': a:linter.command, \ 'callback': a:linter.callback, \}) @@ -158,7 +194,7 @@ function! ALELint(delay) endif if a:delay > 0 - let s:lint_timer = timer_start(a:delay, 's:TimerHandler') + let s:lint_timer = timer_start(a:delay, function('s:TimerHandler')) else call s:TimerHandler() endif @@ -167,6 +203,12 @@ endfunction " Load all of the linters for each filetype. runtime ale_linters/*/*.vim +if !has('nvim') && !(has('timers') && has('job') && has('channel')) + echoerr 'ALE requires NeoVim or Vim 8 with +timers +job +channel' + echoerr 'ALE will not be run automatically' + finish +endif + if g:ale_lint_on_text_changed augroup ALERunOnTextChangedGroup autocmd!