summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--autoload/ale/engine.vim12
-rw-r--r--autoload/ale/job.vim68
2 files changed, 62 insertions, 18 deletions
diff --git a/autoload/ale/engine.vim b/autoload/ale/engine.vim
index 299d37df..c778f253 100644
--- a/autoload/ale/engine.vim
+++ b/autoload/ale/engine.vim
@@ -396,17 +396,7 @@ function! s:RunJob(options) abort
let l:read_buffer = 0
endif
- " The command will be executed in a subshell. This fixes a number of
- " issues, including reading the PATH variables correctly, %PATHEXT%
- " expansion on Windows, etc.
- "
- " NeoVim handles this issue automatically if the command is a String,
- " but we'll do this explicitly, so we use thes same exact command for both
- " versions.
- let l:command = has('win32')
- \ ? 'cmd /c ' . l:command
- \ : split(&shell) + split(&shellcmdflag) + [l:command]
-
+ let l:command = ale#job#PrepareCommand(l:command)
let l:job_options = {
\ 'mode': 'nl',
\ 'exit_cb': function('s:HandleExit'),
diff --git a/autoload/ale/job.vim b/autoload/ale/job.vim
index a9965444..379d3c3a 100644
--- a/autoload/ale/job.vim
+++ b/autoload/ale/job.vim
@@ -57,31 +57,72 @@ function! s:NeoVimCallback(job, data, event) abort
\ a:data,
\)
else
- call ale#util#GetFunction(l:job_info.exit_cb)(a:job, a:data)
+ try
+ call ale#util#GetFunction(l:job_info.exit_cb)(a:job, a:data)
+ finally
+ " Automatically forget about the job after it's done.
+ if has_key(s:job_map, a:job)
+ call remove(s:job_map, a:job)
+ endif
+ endtry
endif
endfunction
function! s:VimOutputCallback(channel, data) abort
let l:job = ch_getjob(a:channel)
let l:job_id = ale#job#ParseVim8ProcessID(string(l:job))
- call ale#util#GetFunction(s:job_map[l:job_id].out_cb)(l:job_id, a:data)
+
+ " Only call the callbacks for jobs which are valid.
+ if l:job_id > 0
+ call ale#util#GetFunction(s:job_map[l:job_id].out_cb)(l:job_id, a:data)
+ endif
endfunction
function! s:VimErrorCallback(channel, data) abort
let l:job = ch_getjob(a:channel)
let l:job_id = ale#job#ParseVim8ProcessID(string(l:job))
- call ale#util#GetFunction(s:job_map[l:job_id].err_cb)(l:job_id, a:data)
+
+ " Only call the callbacks for jobs which are valid.
+ if l:job_id > 0
+ call ale#util#GetFunction(s:job_map[l:job_id].err_cb)(l:job_id, a:data)
+ endif
endfunction
function! s:VimCloseCallback(channel) abort
- " Call job_status, which will trigger the exit callback below.
- " This behaviour is described in :help job-status
- call job_status(ch_getjob(a:channel))
+ let l:job = ch_getjob(a:channel)
+ let l:job_id = ale#job#ParseVim8ProcessID(string(l:job))
+ let l:info = s:job_map[l:job_id]
+
+ " job_status() can trigger the exit handler.
+ " The channel can close before the job has exited.
+ if job_status(l:job) ==# 'dead'
+ try
+ call ale#util#GetFunction(l:info.exit_cb)(l:job_id, l:info.exit_code)
+ finally
+ " Automatically forget about the job after it's done.
+ if has_key(s:job_map, l:job_id)
+ call remove(s:job_map, l:job_id)
+ endif
+ endtry
+ endif
endfunction
function! s:VimExitCallback(job, exit_code) abort
let l:job_id = ale#job#ParseVim8ProcessID(string(a:job))
- call ale#util#GetFunction(s:job_map[l:job_id].exit_cb)(l:job_id, a:exit_code)
+ let l:info = s:job_map[l:job_id]
+ let l:info.exit_code = a:exit_code
+
+ " The program can exit before the data has finished being read.
+ if ch_status(job_getchannel(a:job)) ==# 'closed'
+ try
+ call ale#util#GetFunction(l:info.exit_cb)(l:job_id, a:exit_code)
+ finally
+ " Automatically forget about the job after it's done.
+ if has_key(s:job_map, l:job_id)
+ call remove(s:job_map, l:job_id)
+ endif
+ endtry
+ endif
endfunction
function! ale#job#ParseVim8ProcessID(job_string) abort
@@ -94,6 +135,19 @@ function! ale#job#ValidateArguments(command, options) abort
endif
endfunction
+function! ale#job#PrepareCommand(command) abort
+ " The command will be executed in a subshell. This fixes a number of
+ " issues, including reading the PATH variables correctly, %PATHEXT%
+ " expansion on Windows, etc.
+ "
+ " NeoVim handles this issue automatically if the command is a String,
+ " but we'll do this explicitly, so we use thes same exact command for both
+ " versions.
+ return has('win32')
+ \ ? 'cmd /c ' . a:command
+ \ : split(&shell) + split(&shellcmdflag) + [a:command]
+endfunction
+
" Start a job with options which are agnostic to Vim and NeoVim.
"
" The following options are accepted: