diff --git a/autoload/ale/completion.vim b/autoload/ale/completion.vim index 782a68e4..48fa3963 100644 --- a/autoload/ale/completion.vim +++ b/autoload/ale/completion.vim @@ -165,14 +165,18 @@ function! s:ReplaceCompletionOptions() abort let &l:omnifunc = 'ale#completion#OmniFunc' - if !exists('b:ale_old_completopt') - let b:ale_old_completopt = &l:completeopt - endif + let l:info = get(b:, 'ale_completion_info', {}) - if &l:completeopt =~# 'preview' - let &l:completeopt = 'menu,menuone,preview,noselect,noinsert' - else - let &l:completeopt = 'menu,menuone,noselect,noinsert' + if !get(l:info, 'manual') + if !exists('b:ale_old_completeopt') + let b:ale_old_completeopt = &l:completeopt + endif + + if &l:completeopt =~# 'preview' + let &l:completeopt = 'menu,menuone,preview,noselect,noinsert' + else + let &l:completeopt = 'menu,menuone,noselect,noinsert' + endif endif endfunction @@ -186,9 +190,9 @@ function! ale#completion#RestoreCompletionOptions() abort unlet b:ale_old_omnifunc endif - if exists('b:ale_old_completopt') - let &l:completeopt = b:ale_old_completopt - unlet b:ale_old_completopt + if exists('b:ale_old_completeopt') + let &l:completeopt = b:ale_old_completeopt + unlet b:ale_old_completeopt endif endfunction @@ -503,22 +507,14 @@ function! s:OnReady(linter, lsp_details) abort endif endfunction -function! ale#completion#GetCompletions() abort - if !g:ale_completion_enabled - return - endif - - call ale#completion#AlwaysGetCompletions(1) -endfunction - " This function can be used to manually trigger autocomplete, even when " g:ale_completion_enabled is set to false -function! ale#completion#AlwaysGetCompletions(need_prefix) abort +function! ale#completion#GetCompletions(manual) abort let [l:line, l:column] = getpos('.')[1:2] let l:prefix = ale#completion#GetPrefix(&filetype, l:line, l:column) - if a:need_prefix && empty(l:prefix) + if !a:manual && empty(l:prefix) return endif @@ -531,6 +527,7 @@ function! ale#completion#AlwaysGetCompletions(need_prefix) abort \ 'prefix': l:prefix, \ 'conn_id': 0, \ 'request_id': 0, + \ 'manual': a:manual, \} let l:buffer = bufnr('') @@ -544,6 +541,10 @@ function! ale#completion#AlwaysGetCompletions(need_prefix) abort endfunction function! s:TimerHandler(...) abort + if !g:ale_completion_enabled + return + endif + let s:timer_id = -1 let [l:line, l:column] = getpos('.')[1:2] @@ -551,7 +552,7 @@ function! s:TimerHandler(...) abort " When running the timer callback, we have to be sure that the cursor " hasn't moved from where it was when we requested completions by typing. if s:timer_pos == [l:line, l:column] && ale#util#Mode() is# 'i' - call ale#completion#GetCompletions() + call ale#completion#GetCompletions(0) endif endfunction diff --git a/doc/ale.txt b/doc/ale.txt index 44ddb2e2..33d462c8 100644 --- a/doc/ale.txt +++ b/doc/ale.txt @@ -699,13 +699,13 @@ with |g:ale_completion_excluded_words| or |b:ale_completion_excluded_words|. The |ALEComplete| command can be used to show completion suggestions manually, even when |g:ale_completion_enabled| is set to `0`. - *ale-completion-completopt-bug* + *ale-completion-completeopt-bug* -ALE implements completion as you type by temporarily adjusting |completeopt| -before opening the omnicomplete menu with . In some versions of Vim, -the value set for the option will not be respected. If you experience issues -with Vim automatically inserting text while you type, set the following option -in vimrc, and your issues should go away. > +Automatic completion replaces |completeopt| before opening the omnicomplete +menu with . In some versions of Vim, the value set for the option +will not be respected. If you experience issues with Vim automatically +inserting text while you type, set the following option in vimrc, and your +issues should go away. > set completeopt=menu,menuone,preview,noselect,noinsert < diff --git a/plugin/ale.vim b/plugin/ale.vim index 1df473c5..ad3d3e56 100644 --- a/plugin/ale.vim +++ b/plugin/ale.vim @@ -216,7 +216,7 @@ command! -bar ALEDocumentation :call ale#hover#ShowDocumentationAtCursor() " Search for appearances of a symbol, such as a type name or function name. command! -nargs=1 ALESymbolSearch :call ale#symbol#Search() -command! -bar ALEComplete :call ale#completion#AlwaysGetCompletions(0) +command! -bar ALEComplete :call ale#completion#GetCompletions(1) " mappings for commands nnoremap (ale_previous) :ALEPrevious diff --git a/test/completion/test_completion_events.vader b/test/completion/test_completion_events.vader index 3f0bfa70..d04a8085 100644 --- a/test/completion/test_completion_events.vader +++ b/test/completion/test_completion_events.vader @@ -27,7 +27,7 @@ Before: let g:get_completions_called = 0 " We just want to check if the function is called. - function! ale#completion#GetCompletions() + function! ale#completion#GetCompletions(manual) let g:get_completions_called = 1 endfunction @@ -53,7 +53,7 @@ After: unlet! g:fake_mode unlet! g:get_completions_called unlet! b:ale_old_omnifunc - unlet! b:ale_old_completopt + unlet! b:ale_old_completeopt unlet! b:ale_completion_info unlet! b:ale_completion_response unlet! b:ale_completion_parser @@ -86,7 +86,7 @@ Execute(ale#completion#GetCompletions should not be called when the cursor posit call setpos('.', [bufnr(''), 1, 2, 0]) " We just want to check if the function is called. - function! ale#completion#GetCompletions() + function! ale#completion#GetCompletions(manual) let g:get_completions_called = 1 endfunction @@ -105,7 +105,7 @@ Execute(ale#completion#GetCompletions should not be called if you switch to norm let g:fake_mode = 'n' " We just want to check if the function is called. - function! ale#completion#GetCompletions() + function! ale#completion#GetCompletions(manual) let g:get_completions_called = 1 endfunction @@ -138,7 +138,7 @@ Execute(ale#completion#Show() should remember the completeopt setting and replac call ale#completion#Show('Response', 'Parser') - AssertEqual 'menu', b:ale_old_completopt + AssertEqual 'menu', b:ale_old_completeopt AssertEqual 'menu,menuone,noselect,noinsert', &l:completeopt AssertEqual [], g:feedkeys_calls @@ -150,19 +150,32 @@ Execute(ale#completion#Show() should set the preview option if it's set): call ale#completion#Show('Response', 'Parser') - AssertEqual 'menu,preview', b:ale_old_completopt + AssertEqual 'menu,preview', b:ale_old_completeopt AssertEqual 'menu,menuone,preview,noselect,noinsert', &l:completeopt AssertEqual [], g:feedkeys_calls sleep 1ms AssertEqual [["\(ale_show_completion_menu)"]], g:feedkeys_calls +Execute(ale#completion#Show() should not replace the completeopt setting for manual completion): + let b:ale_completion_info = {'manual': 1} + + let &l:completeopt = 'menu,preview' + + call ale#completion#Show('Response', 'Parser') + + Assert !exists('b:ale_old_completeopt') + + AssertEqual [], g:feedkeys_calls + sleep 1ms + AssertEqual [["\(ale_show_completion_menu)"]], g:feedkeys_calls + Execute(ale#completion#OmniFunc() should also remember the completeopt setting and replace it): let &l:completeopt = 'menu' call ale#completion#OmniFunc(0, '') - AssertEqual 'menu', b:ale_old_completopt + AssertEqual 'menu', b:ale_old_completeopt AssertEqual 'menu,menuone,noselect,noinsert', &l:completeopt Execute(ale#completion#OmniFunc() should set the preview option if it's set): @@ -170,7 +183,7 @@ Execute(ale#completion#OmniFunc() should set the preview option if it's set): call ale#completion#OmniFunc(0, '') - AssertEqual 'menu,preview', b:ale_old_completopt + AssertEqual 'menu,preview', b:ale_old_completeopt AssertEqual 'menu,menuone,preview,noselect,noinsert', &l:completeopt Execute(ale#completion#Show() should make the correct feedkeys() call): @@ -188,7 +201,7 @@ Execute(ale#completion#Show() shouldn't do anything if you switch back to normal AssertEqual 'menu,preview', &l:completeopt Assert !exists('b:ale_old_omnifunc') - Assert !exists('b:ale_old_completopt') + Assert !exists('b:ale_old_completeopt') Assert !exists('b:ale_completion_response') Assert !exists('b:ale_completion_parser') AssertEqual [], g:feedkeys_calls @@ -209,12 +222,12 @@ Execute(ale#completion#Done() should restore old omnifunc values): Assert !has_key(b:, 'ale_old_omnifunc') Execute(ale#completion#Done() should restore the old completeopt setting): - let b:ale_old_completopt = 'menu' + let b:ale_old_completeopt = 'menu' call ale#completion#Done() AssertEqual 'menu', &l:completeopt - Assert !has_key(b:, 'ale_old_completopt') + Assert !has_key(b:, 'ale_old_completeopt') Execute(ale#completion#Done() should leave settings alone when none were remembered): let &l:omnifunc = 'BazBoz' @@ -236,7 +249,7 @@ Execute(The completion request_id should be reset when queuing again): Execute(b:ale_completion_info should be set up correctly when requesting completions): call setpos('.', [bufnr(''), 3, 14, 0]) - call ale#completion#GetCompletions() + call ale#completion#GetCompletions(0) AssertEqual \ { @@ -246,6 +259,23 @@ Execute(b:ale_completion_info should be set up correctly when requesting complet \ 'line_length': 14, \ 'line': 3, \ 'prefix': 'ab', + \ 'manual': 0, + \ }, + \ b:ale_completion_info + +Execute(b:ale_completion_info should be set up correctly when requesting completions): + call setpos('.', [bufnr(''), 3, 14, 0]) + ALEComplete + + AssertEqual + \ { + \ 'request_id': 0, + \ 'conn_id': 0, + \ 'column': 14, + \ 'line_length': 14, + \ 'line': 3, + \ 'prefix': 'ab', + \ 'manual': 1, \ }, \ b:ale_completion_info @@ -264,7 +294,7 @@ Execute(The correct keybinds should be configured): Execute(Running the normal mode keybind should reset the settings): let b:ale_old_omnifunc = 'FooBar' - let b:ale_old_completopt = 'menu' + let b:ale_old_completeopt = 'menu' " We can't run the keybind, but we can call the function. call ale#completion#RestoreCompletionOptions() @@ -272,4 +302,4 @@ Execute(Running the normal mode keybind should reset the settings): AssertEqual 'FooBar', &l:omnifunc AssertEqual 'menu', &l:completeopt Assert !has_key(b:, 'ale_old_omnifunc') - Assert !has_key(b:, 'ale_old_completopt') + Assert !has_key(b:, 'ale_old_completeopt') diff --git a/test/completion/test_lsp_completion_messages.vader b/test/completion/test_lsp_completion_messages.vader index c83ad8e1..dce61e36 100644 --- a/test/completion/test_lsp_completion_messages.vader +++ b/test/completion/test_lsp_completion_messages.vader @@ -67,7 +67,7 @@ After: unlet! g:conn_id unlet! g:Callback unlet! b:ale_old_omnifunc - unlet! b:ale_old_completopt + unlet! b:ale_old_completeopt unlet! b:ale_completion_info unlet! b:ale_completion_response unlet! b:ale_completion_parser @@ -102,7 +102,7 @@ Execute(The right message should be sent for the initial tsserver request): " The cursor position needs to match what was saved before. call setpos('.', [bufnr(''), 1, 3, 0]) - call ale#completion#GetCompletions() + call ale#completion#GetCompletions(0) " We shouldn't register the callback yet. AssertEqual '''''', string(g:Callback) @@ -129,6 +129,7 @@ Execute(The right message should be sent for the initial tsserver request): \ 'request_id': 1, \ 'line': 1, \ 'prefix': 'fo', + \ 'manual': 0, \ }, \ get(b:, 'ale_completion_info', {}) @@ -190,7 +191,7 @@ Execute(The right message should be sent for the initial LSP request): " The cursor position needs to match what was saved before. call setpos('.', [bufnr(''), 1, 5, 0]) - call ale#completion#GetCompletions() + call ale#completion#GetCompletions(0) " We shouldn't register the callback yet. AssertEqual '''''', string(g:Callback) @@ -233,6 +234,7 @@ Execute(The right message should be sent for the initial LSP request): \ 'request_id': 1, \ 'line': 1, \ 'prefix': 'fo', + \ 'manual': 0, \ 'completion_filter': 'ale#completion#python#CompletionItemFilter', \ }, \ get(b:, 'ale_completion_info', {}) @@ -258,7 +260,7 @@ Execute(Two completion requests shouldn't be sent in a row): " The cursor position needs to match what was saved before. call setpos('.', [bufnr(''), 1, 5, 0]) - call ale#completion#GetCompletions() + call ale#completion#GetCompletions(0) " We shouldn't register the callback yet. AssertEqual '''''', string(g:Callback) diff --git a/test/test_ale_complete_command.vader b/test/test_ale_complete_command.vader deleted file mode 100644 index 11f781c2..00000000 --- a/test/test_ale_complete_command.vader +++ /dev/null @@ -1,26 +0,0 @@ -Before: - function! MockAlwaysGetCompletions() abort - let g:get_completions_called = 0 - let g:always_get_completions_argument = -1 - - function! ale#completion#AlwaysGetCompletions(need_prefix) abort - let g:get_completions_called = 1 - let g:always_get_completions_argument = a:need_prefix - endfunction - endfunction - - call MockAlwaysGetCompletions() - -After: - unlet! g:get_completions_called - unlet! g:always_get_completions_argument - delfunction MockAlwaysGetCompletions - delfunction ale#completion#AlwaysGetCompletions - - runtime autoload/ale/completion.vim - -Execute(ale#completion#AlwaysGetCompletions should be called when ALEComplete is executed): - AssertEqual 0, g:get_completions_called - ALEComplete - AssertEqual 1, g:get_completions_called - AssertEqual 0, g:always_get_completions_argument