diff options
author | w0rp <devw0rp@gmail.com> | 2016-10-23 22:41:00 +0100 |
---|---|---|
committer | w0rp <devw0rp@gmail.com> | 2016-10-23 22:41:00 +0100 |
commit | 7481facd7373dda4667c401695e6d8000ef52362 (patch) | |
tree | 11ebf0397b14aff2c9daab798aa6a323f2bde254 /autoload | |
parent | 36461b69d7dbf0abe494cd450dd9233eed7b672f (diff) | |
download | ale-7481facd7373dda4667c401695e6d8000ef52362.zip |
#107 Stop jobs when buffers close
Diffstat (limited to 'autoload')
-rw-r--r-- | autoload/ale.vim | 5 | ||||
-rw-r--r-- | autoload/ale/cleanup.vim | 15 | ||||
-rw-r--r-- | autoload/ale/engine.vim | 60 | ||||
-rw-r--r-- | autoload/ale/sign.vim | 8 | ||||
-rw-r--r-- | autoload/ale/statusline.vim | 40 |
5 files changed, 83 insertions, 45 deletions
diff --git a/autoload/ale.vim b/autoload/ale.vim index 44cd5825..3e86c8f9 100644 --- a/autoload/ale.vim +++ b/autoload/ale.vim @@ -27,8 +27,11 @@ function! ale#Lint(...) abort let l:buffer = bufnr('%') let l:linters = ale#linter#Get(&filetype) + " Initialise the buffer information if needed. + call ale#engine#InitBufferInfo(l:buffer) + " Set a variable telling us to clear the loclist later. - let g:ale_buffer_should_reset_map[l:buffer] = 1 + let g:ale_buffer_info[l:buffer].should_reset = 1 for l:linter in l:linters " Check if a given linter has a program which can be executed. diff --git a/autoload/ale/cleanup.vim b/autoload/ale/cleanup.vim index 45eccb98..40a8a359 100644 --- a/autoload/ale/cleanup.vim +++ b/autoload/ale/cleanup.vim @@ -2,19 +2,16 @@ " Description: Utility functions related to cleaning state. function! ale#cleanup#Buffer(buffer) abort - if has_key(g:ale_buffer_count_map, a:buffer) - call remove(g:ale_buffer_count_map, a:buffer) - endif - if has_key(g:ale_buffer_loclist_map, a:buffer) call remove(g:ale_buffer_loclist_map, a:buffer) endif - if has_key(g:ale_buffer_should_reset_map, a:buffer) - call remove(g:ale_buffer_should_reset_map, a:buffer) - endif + if has_key(g:ale_buffer_info, a:buffer) + " When buffers are removed, clear all of the jobs. + for l:job in get(g:ale_buffer_info[a:buffer], 'job_list', []) + call ale#engine#ClearJob(l:job) + endfor - if has_key(g:ale_buffer_sign_dummy_map, a:buffer) - call remove(g:ale_buffer_sign_dummy_map, a:buffer) + call remove(g:ale_buffer_info, a:buffer) endif endfunction diff --git a/autoload/ale/engine.vim b/autoload/ale/engine.vim index 5cdcd7ce..3af60ab6 100644 --- a/autoload/ale/engine.vim +++ b/autoload/ale/engine.vim @@ -20,7 +20,17 @@ function! s:GetJobID(job) abort return ch_info(job_getchannel(a:job)).id endfunction -function! s:ClearJob(job) abort +function! ale#engine#InitBufferInfo(buffer) abort + if !has_key(g:ale_buffer_info, a:buffer) + let g:ale_buffer_info[a:buffer] = { + \ 'job_list': [], + \ 'should_reset': 1, + \ 'dummy_sign_set': 0, + \} + endif +endfunction + +function! ale#engine#ClearJob(job) abort let l:job_id = s:GetJobID(a:job) let l:linter = s:job_info_map[l:job_id].linter @@ -37,7 +47,26 @@ function! s:ClearJob(job) abort endif call remove(s:job_info_map, l:job_id) - call remove(l:linter, 'job') +endfunction + +function! s:StopPreviousJobs(buffer, linter) abort + let l:new_job_list = [] + + for l:job in g:ale_buffer_info[a:buffer].job_list + let l:job_id = s:GetJobID(l:job) + + if has_key(s:job_info_map, l:job_id) + \&& s:job_info_map[l:job_id].linter.name ==# a:linter.name + " Stop jobs which match the buffer and linter. + call ale#engine#ClearJob(l:job) + else + " Keep other jobs in the list. + call add(l:new_job_list, l:job) + endif + endfor + + " Update the list, removing the previously run job. + let g:ale_buffer_info[a:buffer].job_list = l:new_job_list endfunction function! s:GatherOutput(job, data) abort @@ -71,17 +100,11 @@ function! s:HandleExit(job) abort endif let l:job_info = s:job_info_map[l:job_id] - - call s:ClearJob(a:job) - let l:linter = l:job_info.linter let l:output = l:job_info.output let l:buffer = l:job_info.buffer - if !has_key(g:ale_buffer_should_reset_map, l:buffer) - " A job ended for a buffer which has been closed, so stop here. - return - endif + call s:StopPreviousJobs(l:buffer, l:linter) let l:linter_loclist = ale#util#GetFunction(l:linter.callback)(l:buffer, l:output) @@ -92,8 +115,10 @@ function! s:HandleExit(job) abort let l:item.linter_name = l:linter.name endfor - if g:ale_buffer_should_reset_map[l:buffer] - let g:ale_buffer_should_reset_map[l:buffer] = 0 + if g:ale_buffer_info[l:buffer].should_reset + " Set the flag for resetting the loclist to 0 again, so we won't + " empty the list later. + let g:ale_buffer_info[l:buffer].should_reset = 0 let g:ale_buffer_loclist_map[l:buffer] = [] endif @@ -150,10 +175,8 @@ function! s:FixLocList(buffer, loclist) abort endfunction function! ale#engine#Invoke(buffer, linter) abort - if has_key(a:linter, 'job') - " Stop previous jobs for the same linter. - call s:ClearJob(a:linter.job) - endif + " Stop previous jobs for the same linter. + call s:StopPreviousJobs(a:buffer, a:linter) if has_key(a:linter, 'command_callback') " If there is a callback for generating a command, call that instead. @@ -227,7 +250,8 @@ function! ale#engine#Invoke(buffer, linter) abort " Only proceed if the job is being run. if has('nvim') || (l:job !=# 'no process' && job_status(l:job) ==# 'run') - let a:linter.job = l:job + " Add the job to the list of jobs, so we can track them. + call add(g:ale_buffer_info[a:buffer].job_list, l:job) " Store the ID for the job in the map to read back again. let s:job_info_map[s:GetJobID(l:job)] = { @@ -270,8 +294,8 @@ function! ale#engine#WaitForJobs(deadline) abort let l:job_list = [] - for l:job_id in keys(s:job_info_map) - call add(l:job_list, s:job_info_map[l:job_id].linter.job) + for l:info in values(g:ale_buffer_info) + call extend(l:job_list, l:info.job_list) endfor let l:should_wait_more = 1 diff --git a/autoload/ale/sign.vim b/autoload/ale/sign.vim index 23666287..deec47f2 100644 --- a/autoload/ale/sign.vim +++ b/autoload/ale/sign.vim @@ -89,13 +89,13 @@ function! ale#sign#SetSigns(buffer, loclist) abort let l:signlist = ale#sign#CombineSigns(a:loclist) if len(l:signlist) > 0 || g:ale_sign_column_always - if !get(g:ale_buffer_sign_dummy_map, a:buffer, 0) + if !g:ale_buffer_info[a:buffer].dummy_sign_set " Insert a dummy sign if one is missing. execute 'sign place ' . g:ale_sign_offset \ . ' line=1 name=ALEDummySign buffer=' \ . a:buffer - let g:ale_buffer_sign_dummy_map[a:buffer] = 1 + let g:ale_buffer_info[a:buffer].dummy_sign_set = 1 endif endif @@ -121,10 +121,10 @@ function! ale#sign#SetSigns(buffer, loclist) abort endfor if !g:ale_sign_column_always && len(l:signlist) > 0 - if get(g:ale_buffer_sign_dummy_map, a:buffer, 0) + if g:ale_buffer_info[a:buffer].dummy_sign_set execute 'sign unplace ' . g:ale_sign_offset . ' buffer=' . a:buffer - let g:ale_buffer_sign_dummy_map[a:buffer] = 0 + let g:ale_buffer_info[a:buffer].dummy_sign_set = 0 endif endif endfunction diff --git a/autoload/ale/statusline.vim b/autoload/ale/statusline.vim index 8a31bc39..48b4d687 100644 --- a/autoload/ale/statusline.vim +++ b/autoload/ale/statusline.vim @@ -14,34 +14,48 @@ function! ale#statusline#Update(buffer, loclist) abort endif endfor - let g:ale_buffer_count_map[a:buffer] = [l:errors, l:warnings] + let g:ale_buffer_info[a:buffer].count = [l:errors, l:warnings] endfunction -" Returns a tuple of errors and warnings for use in third-party integrations. -function! ale#statusline#Count(buffer) abort +" Set the error and warning counts, calling for an update only if needed. +" If counts cannot be set, return 0. +function! s:SetupCount(buffer) abort + if !has_key(g:ale_buffer_info, a:buffer) + " Linters have not been run for the buffer yet, so stop here. + return 0 + endif + " Cache is cold, so manually ask for an update. - if !has_key(g:ale_buffer_count_map, a:buffer) + if !has_key(g:ale_buffer_info[a:buffer], 'count') call ale#statusline#Update(a:buffer, get(g:ale_buffer_loclist_map, a:buffer, [])) endif - return g:ale_buffer_count_map[a:buffer] + return 1 +endfunction + +" Returns a tuple of errors and warnings for use in third-party integrations. +function! ale#statusline#Count(buffer) abort + if !s:SetupCount(a:buffer) + return [0, 0] + endif + + return g:ale_buffer_info[a:buffer].count endfunction " Returns a formatted string that can be integrated in the statusline. function! ale#statusline#Status() abort + let [l:error_format, l:warning_format, l:no_errors] = g:ale_statusline_format let l:buffer = bufnr('%') - " Cache is cold, so manually ask for an update. - if !has_key(g:ale_buffer_count_map, l:buffer) - call ale#statusline#Update(l:buffer, get(g:ale_buffer_loclist_map, l:buffer, [])) + if !s:SetupCount(l:buffer) + return l:no_errors endif + let [l:error_count, l:warning_count] = g:ale_buffer_info[l:buffer].count + " Build strings based on user formatting preferences. - let l:errors = g:ale_buffer_count_map[l:buffer][0] ? - \ printf(g:ale_statusline_format[0], g:ale_buffer_count_map[l:buffer][0]) : '' - let l:warnings = g:ale_buffer_count_map[l:buffer][1] ? - \ printf(g:ale_statusline_format[1], g:ale_buffer_count_map[l:buffer][1]) : '' - let l:no_errors = g:ale_statusline_format[2] + let l:errors = l:error_count ? printf(l:error_format, l:error_count) : '' + let l:warnings = l:warning_count ? printf(l:warning_format, l:warning_count) : '' " Different formats based on the combination of errors and warnings. if empty(l:errors) && empty(l:warnings) |