From 5fc2b98b73b74a0d57037683f0c809eac41368f0 Mon Sep 17 00:00:00 2001 From: w0rp Date: Sat, 28 Oct 2017 19:36:16 +0100 Subject: [PATCH] #817 Add commands for toggling ALE for only the current buffer --- autoload/ale/highlight.vim | 4 +- autoload/ale/toggle.vim | 88 ++++++++++++++++++++++------ plugin/ale.vim | 4 ++ test/test_ale_toggle.vader | 91 +++++++++++++++++++++++++++-- test/test_highlight_placement.vader | 28 ++++++++- 5 files changed, 188 insertions(+), 27 deletions(-) diff --git a/autoload/ale/highlight.vim b/autoload/ale/highlight.vim index 5c01e7a9..47256f0b 100644 --- a/autoload/ale/highlight.vim +++ b/autoload/ale/highlight.vim @@ -58,7 +58,7 @@ function! ale#highlight#RemoveHighlights() abort endfunction function! ale#highlight#UpdateHighlights() abort - let l:item_list = g:ale_enabled + let l:item_list = get(b:, 'ale_enabled', 1) && g:ale_enabled \ ? get(b:, 'ale_highlight_items', []) \ : [] @@ -106,7 +106,7 @@ augroup ALEHighlightBufferGroup augroup END function! ale#highlight#SetHighlights(buffer, loclist) abort - let l:new_list = g:ale_enabled + let l:new_list = getbufvar(a:buffer, 'ale_enabled', 1) && g:ale_enabled \ ? filter(copy(a:loclist), 'v:val.bufnr == a:buffer && v:val.col > 0') \ : [] diff --git a/autoload/ale/toggle.vim b/autoload/ale/toggle.vim index acddea4b..8e54dc21 100644 --- a/autoload/ale/toggle.vim +++ b/autoload/ale/toggle.vim @@ -85,21 +85,36 @@ function! ale#toggle#InitAuGroups() abort endif endfunction +function! s:EnablePreamble() abort + " Set pattern options again, if enabled. + if g:ale_pattern_options_enabled + call ale#pattern_options#SetOptions() + endif + + " Lint immediately, including running linters against the file. + call ale#Queue(0, 'lint_file') + + if g:ale_set_balloons + call ale#balloon#Enable() + endif +endfunction + +function! s:DisablePostamble() abort + " Remove highlights for the current buffer now. + if g:ale_set_highlights + call ale#highlight#UpdateHighlights() + endif + + if g:ale_set_balloons + call ale#balloon#Disable() + endif +endfunction + function! ale#toggle#Toggle() abort let g:ale_enabled = !get(g:, 'ale_enabled') if g:ale_enabled - " Set pattern options again, if enabled. - if g:ale_pattern_options_enabled - call ale#pattern_options#SetOptions() - endif - - " Lint immediately, including running linters against the file. - call ale#Queue(0, 'lint_file') - - if g:ale_set_balloons - call ale#balloon#Enable() - endif + call s:EnablePreamble() else for l:key in keys(g:ale_buffer_info) " The key could be a filename or a buffer number, so try and @@ -114,14 +129,7 @@ function! ale#toggle#Toggle() abort endif endfor - " Remove highlights for the current buffer now. - if g:ale_set_highlights - call ale#highlight#UpdateHighlights() - endif - - if g:ale_set_balloons - call ale#balloon#Disable() - endif + call s:DisablePostamble() endif call ale#toggle#InitAuGroups() @@ -129,6 +137,11 @@ endfunction function! ale#toggle#Enable() abort if !g:ale_enabled + " Set pattern options again, if enabled. + if g:ale_pattern_options_enabled + call ale#pattern_options#SetOptions() + endif + call ale#toggle#Toggle() endif endfunction @@ -138,3 +151,40 @@ function! ale#toggle#Disable() abort call ale#toggle#Toggle() endif endfunction + +function! ale#toggle#ToggleBuffer(buffer) abort + " Get the new value for the toggle. + let l:enabled = !getbufvar(a:buffer, 'ale_enabled', 1) + + " Disabling ALE globally removes autocmd events, so we cannot enable + " linting locally when linting is disabled globally + if l:enabled && !g:ale_enabled + echom 'ALE cannot be enabled locally when disabled globally' + return + endif + + call setbufvar(a:buffer, 'ale_enabled', l:enabled) + + if l:enabled + call s:EnablePreamble() + else + " Stop all jobs and clear the results for everything, and delete + " all of the data we stored for the buffer. + call ale#engine#Cleanup(a:buffer) + + call s:DisablePostamble() + endif +endfunction + +function! ale#toggle#EnableBuffer(buffer) abort + " ALE is enabled by default for all buffers. + if !getbufvar(a:buffer, 'ale_enabled', 1) + call ale#toggle#ToggleBuffer(a:buffer) + endif +endfunction + +function! ale#toggle#DisableBuffer(buffer) abort + if getbufvar(a:buffer, 'ale_enabled', 1) + call ale#toggle#ToggleBuffer(a:buffer) + endif +endfunction diff --git a/plugin/ale.vim b/plugin/ale.vim index 83ca2dd0..3e1803e5 100644 --- a/plugin/ale.vim +++ b/plugin/ale.vim @@ -224,6 +224,10 @@ command! -bar ALEDetail :call ale#cursor#ShowCursorDetail() command! -bar ALEToggle :call ale#toggle#Toggle() command! -bar ALEEnable :call ale#toggle#Enable() command! -bar ALEDisable :call ale#toggle#Disable() +" Commands for turning ALE on or off for a buffer. +command! -bar ALEToggleBuffer :call ale#toggle#ToggleBuffer(bufnr('')) +command! -bar ALEEnableBuffer :call ale#toggle#EnableBuffer(bufnr('')) +command! -bar ALEDisableBuffer :call ale#toggle#DisableBuffer(bufnr('')) " A command for linting manually. command! -bar ALELint :call ale#Queue(0, 'lint_file') diff --git a/test/test_ale_toggle.vader b/test/test_ale_toggle.vader index 733ae35d..d8de398a 100644 --- a/test/test_ale_toggle.vader +++ b/test/test_ale_toggle.vader @@ -6,6 +6,9 @@ Before: let g:ale_set_signs = 1 let g:ale_set_lists_synchronously = 1 + let g:ale_run_synchronously = 1 + + unlet! b:ale_enabled let g:ale_buffer_info = {} let g:expected_loclist = [{ @@ -80,6 +83,8 @@ After: unlet! g:expected_loclist unlet! g:expected_groups + unlet! b:ale_enabled + unlet! g:output call ale#linter#Reset() @@ -91,12 +96,19 @@ After: delfunction ToggleTestCallback delfunction ParseAuGroups + call setloclist(0, []) + sign unplace * + call clearmatches() + Given foobar (Some imaginary filetype): foo bar baz Execute(ALEToggle should reset everything and then run again): + " Run this test asynchrously. + let g:ale_run_synchronously = 0 + AssertEqual 'foobar', &filetype call ale#Lint() @@ -134,6 +146,9 @@ Execute(ALEToggle should reset everything and then run again): AssertEqual [{'lnum': 2, 'bufnr': bufnr(''), 'col': 3, 'linter_name': 'testlinter', 'vcol': 0, 'nr': -1, 'type': 'E', 'text': 'foo bar', 'sign_id': 1000001}], g:ale_buffer_info[bufnr('')].loclist Execute(ALEToggle should skip filename keys and preserve them): + " Run this test asynchrously. + let g:ale_run_synchronously = 0 + AssertEqual 'foobar', &filetype let g:ale_buffer_info['/foo/bar/baz.txt'] = { @@ -178,9 +193,6 @@ Execute(ALEToggle should skip filename keys and preserve them): \ get(g:ale_buffer_info, '/foo/bar/baz.txt', {}) Execute(ALEDisable should reset everything and stay disabled): - " We can just lint sychronously for these tests. - let g:ale_run_synchronously = 1 - call ale#Lint() AssertEqual g:expected_loclist, getloclist(0) @@ -196,11 +208,80 @@ Execute(ALEDisable should reset everything and stay disabled): AssertEqual 0, g:ale_enabled Execute(ALEEnable should enable ALE and lint again): - " We can just lint sychronously for these tests. let g:ale_enabled = 0 - let g:ale_run_synchronously = 1 ALEEnable AssertEqual g:expected_loclist, getloclist(0) AssertEqual 1, g:ale_enabled + +Execute(ALEToggleBuffer should reset everything and then run again): + " Run this test asynchrously. + let g:ale_run_synchronously = 0 + + AssertEqual 'foobar', &filetype + + call ale#Lint() + call ale#engine#WaitForJobs(2000) + + " First check that everything is there... + AssertEqual g:expected_loclist, getloclist(0) + AssertEqual [0, [[2, 1000001, 'ALEErrorSign']]], ale#sign#FindCurrentSigns(bufnr('%')) + AssertEqual + \ [{'group': 'ALEError', 'pos1': [2, 3, 1]}], + \ map(getmatches(), '{''group'': v:val.group, ''pos1'': v:val.pos1}') + AssertEqual [{'lnum': 2, 'bufnr': bufnr(''), 'col': 3, 'linter_name': 'testlinter', 'vcol': 0, 'nr': -1, 'type': 'E', 'text': 'foo bar', 'sign_id': 1000001}], g:ale_buffer_info[bufnr('')].loclist + + " Now Toggle ALE off. + ALEToggleBuffer + + " Everything should be cleared. + Assert !has_key(g:ale_buffer_info, bufnr('')), 'The g:ale_buffer_info Dictionary was not removed' + AssertEqual [], getloclist(0), 'The loclist was not cleared' + AssertEqual [0, []], ale#sign#FindCurrentSigns(bufnr('%')), 'The signs were not cleared' + AssertEqual [], getmatches(), 'The highlights were not cleared' + + " Toggle ALE on, everything should be set up and run again. + ALEToggleBuffer + call ale#engine#WaitForJobs(2000) + + AssertEqual g:expected_loclist, getloclist(0) + AssertEqual [0, [[2, 1000001, 'ALEErrorSign']]], ale#sign#FindCurrentSigns(bufnr('%')) + AssertEqual + \ [{'group': 'ALEError', 'pos1': [2, 3, 1]}], + \ map(getmatches(), '{''group'': v:val.group, ''pos1'': v:val.pos1}') + AssertEqual g:expected_groups, ParseAuGroups() + AssertEqual [{'lnum': 2, 'bufnr': bufnr(''), 'col': 3, 'linter_name': 'testlinter', 'vcol': 0, 'nr': -1, 'type': 'E', 'text': 'foo bar', 'sign_id': 1000001}], g:ale_buffer_info[bufnr('')].loclist + +Execute(ALEDisableBuffer should reset everything and stay disabled): + call ale#Lint() + + AssertEqual g:expected_loclist, getloclist(0) + + ALEDisableBuffer + + AssertEqual [], getloclist(0) + AssertEqual 0, b:ale_enabled + +Execute(ALEEnableBuffer should enable ALE and lint again): + let b:ale_enabled = 0 + + ALEEnableBuffer + + AssertEqual g:expected_loclist, getloclist(0) + AssertEqual 1, b:ale_enabled + +Execute(ALEEnableBuffer should complain when ALE is disabled globally): + let g:ale_enabled = 0 + let b:ale_enabled = 0 + + redir => g:output + ALEEnableBuffer + redir END + + AssertEqual [], getloclist(0) + AssertEqual 0, b:ale_enabled + AssertEqual 0, g:ale_enabled + AssertEqual + \ 'ALE cannot be enabled locally when disabled globally', + \ join(split(g:output)) diff --git a/test/test_highlight_placement.vader b/test/test_highlight_placement.vader index 2d87b771..6a84e571 100644 --- a/test/test_highlight_placement.vader +++ b/test/test_highlight_placement.vader @@ -1,4 +1,6 @@ Before: + Save g:ale_enabled + function! GenerateResults(buffer, output) return [ \ { @@ -43,7 +45,10 @@ Before: highlight link SomeOtherGroup SpellBad After: + Restore + unlet! g:items + unlet! b:ale_enabled delfunction GenerateResults call ale#linter#Reset() @@ -206,7 +211,7 @@ Execute(Highlighting should support errors spanning many lines): \ }, \ ], \ GetMatchesWithoutIDs() - \ + Execute(Highlights should always be cleared when the buffer highlight list is empty): " Add our highlights and something else. call matchaddpos('ALEError', [[1, 1, 1]]) @@ -232,3 +237,24 @@ Execute(Highlights should always be cleared when the buffer highlight list is em \ {'group': 'SomeOtherGroup', 'priority': 10, 'pos1': [1, 1, 1]}, \ ], \ GetMatchesWithoutIDs() + +Execute(Highlights should be cleared when ALE is disabled): + let g:ale_enabled = 1 + call ale#highlight#SetHighlights(bufnr(''), [ + \ {'bufnr': bufnr(''), 'type': 'E', 'lnum': 1, 'col': 1, 'end_lnum': 10, 'end_col': 3}, + \]) + + let g:ale_enabled = 0 + call ale#highlight#UpdateHighlights() + + AssertEqual [], GetMatchesWithoutIDs() + + let g:ale_enabled = 1 + call ale#highlight#SetHighlights(bufnr(''), [ + \ {'bufnr': bufnr(''), 'type': 'E', 'lnum': 1, 'col': 1, 'end_lnum': 10, 'end_col': 3}, + \]) + + let b:ale_enabled = 0 + call ale#highlight#UpdateHighlights() + + AssertEqual [], GetMatchesWithoutIDs()