summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--autoload/ale/completion.vim66
-rw-r--r--test/completion/test_completion_events.vader32
2 files changed, 70 insertions, 28 deletions
diff --git a/autoload/ale/completion.vim b/autoload/ale/completion.vim
index 0f9ae4e0..e7da4028 100644
--- a/autoload/ale/completion.vim
+++ b/autoload/ale/completion.vim
@@ -1,6 +1,17 @@
" Author: w0rp <devw0rp@gmail.com>
" Description: Completion support for LSP linters
+" The omnicompletion menu is shown through a special Plug mapping which is
+" only valid in Insert mode. This way, feedkeys() won't send these keys if you
+" quit Insert mode quickly enough.
+inoremap <silent> <Plug>(ale_show_completion_menu) <C-x><C-o>
+" If we hit the key sequence in normal mode, then we won't show the menu, so
+" we should restore the old settings right away.
+nnoremap <silent> <Plug>(ale_show_completion_menu) :call ale#completion#RestoreCompletionOptions()<CR>
+cnoremap <silent> <Plug>(ale_show_completion_menu) <Nop>
+vnoremap <silent> <Plug>(ale_show_completion_menu) <Nop>
+onoremap <silent> <Plug>(ale_show_completion_menu) <Nop>
+
let g:ale_completion_delay = get(g:, 'ale_completion_delay', 100)
let g:ale_completion_excluded_words = get(g:, 'ale_completion_excluded_words', [])
let g:ale_completion_max_suggestions = get(g:, 'ale_completion_max_suggestions', 50)
@@ -129,7 +140,16 @@ function! ale#completion#Filter(buffer, suggestions, prefix) abort
return l:filtered_suggestions
endfunction
-function! s:ReplaceCompleteopt() abort
+function! s:ReplaceCompletionOptions() abort
+ " Remember the old omnifunc value, if there is one.
+ " If we don't store an old one, we'll just never reset the option.
+ " This will stop some random exceptions from appearing.
+ if !exists('b:ale_old_omnifunc') && !empty(&l:omnifunc)
+ let b:ale_old_omnifunc = &l:omnifunc
+ endif
+
+ let &l:omnifunc = 'ale#completion#OmniFunc'
+
if !exists('b:ale_old_completopt')
let b:ale_old_completopt = &l:completeopt
endif
@@ -141,6 +161,22 @@ function! s:ReplaceCompleteopt() abort
endif
endfunction
+function! ale#completion#RestoreCompletionOptions() abort
+ " Reset settings when completion is done.
+ if exists('b:ale_old_omnifunc')
+ if b:ale_old_omnifunc isnot# 'pythoncomplete#Complete'
+ let &l:omnifunc = b:ale_old_omnifunc
+ endif
+
+ unlet b:ale_old_omnifunc
+ endif
+
+ if exists('b:ale_old_completopt')
+ let &l:completeopt = b:ale_old_completopt
+ unlet b:ale_old_completopt
+ endif
+endfunction
+
function! ale#completion#OmniFunc(findstart, base) abort
if a:findstart
let l:line = b:ale_completion_info.line
@@ -163,7 +199,7 @@ function! ale#completion#OmniFunc(findstart, base) abort
let b:ale_completion_result = function(l:parser)(l:response)
endif
- call s:ReplaceCompleteopt()
+ call s:ReplaceCompletionOptions()
return get(b:, 'ale_completion_result', [])
endif
@@ -174,20 +210,12 @@ function! ale#completion#Show(response, completion_parser) abort
return
endif
- " Remember the old omnifunc value, if there is one.
- " If we don't store an old one, we'll just never reset the option.
- " This will stop some random exceptions from appearing.
- if !exists('b:ale_old_omnifunc') && !empty(&l:omnifunc)
- let b:ale_old_omnifunc = &l:omnifunc
- endif
-
" Set the list in the buffer, temporarily replace omnifunc with our
" function, and then start omni-completion.
let b:ale_completion_response = a:response
let b:ale_completion_parser = a:completion_parser
- let &l:omnifunc = 'ale#completion#OmniFunc'
- call s:ReplaceCompleteopt()
- call ale#util#FeedKeys("\<C-x>\<C-o>", 'n')
+ call s:ReplaceCompletionOptions()
+ call ale#util#FeedKeys("\<Plug>(ale_show_completion_menu)")
endfunction
function! s:CompletionStillValid(request_id) abort
@@ -523,19 +551,7 @@ endfunction
function! ale#completion#Done() abort
silent! pclose
- " Reset settings when completion is done.
- if exists('b:ale_old_omnifunc')
- if b:ale_old_omnifunc isnot# 'pythoncomplete#Complete'
- let &l:omnifunc = b:ale_old_omnifunc
- endif
-
- unlet b:ale_old_omnifunc
- endif
-
- if exists('b:ale_old_completopt')
- let &l:completeopt = b:ale_old_completopt
- unlet b:ale_old_completopt
- endif
+ call ale#completion#RestoreCompletionOptions()
let s:last_done_pos = getcurpos()[1:2]
endfunction
diff --git a/test/completion/test_completion_events.vader b/test/completion/test_completion_events.vader
index 504d79c2..f8cf268c 100644
--- a/test/completion/test_completion_events.vader
+++ b/test/completion/test_completion_events.vader
@@ -14,8 +14,8 @@ Before:
runtime autoload/ale/util.vim
- function! ale#util#FeedKeys(string, mode) abort
- call add(g:feedkeys_calls, [a:string, a:mode])
+ function! ale#util#FeedKeys(string) abort
+ call add(g:feedkeys_calls, [a:string])
endfunction
" Pretend we're in insert mode for most tests.
@@ -41,6 +41,7 @@ Before:
After:
Restore
+ unlet! g:output
unlet! g:fake_mode
unlet! g:get_completions_called
unlet! b:ale_old_omnifunc
@@ -155,7 +156,7 @@ Execute(ale#completion#OmniFunc() should set the preview option if it's set):
Execute(ale#completion#Show() should make the correct feedkeys() call):
call ale#completion#Show('Response', 'Parser')
- AssertEqual [["\<C-x>\<C-o>", 'n']], g:feedkeys_calls
+ AssertEqual [["\<Plug>(ale_show_completion_menu)"]], g:feedkeys_calls
Execute(ale#completion#Show() shouldn't do anything if you switch back to normal mode):
let &l:completeopt = 'menu,preview'
@@ -225,3 +226,28 @@ Execute(b:ale_completion_info should be set up correctly when requesting complet
\ 'prefix': 'ab',
\ },
\ b:ale_completion_info
+
+Execute(The correct keybinds should be configured):
+ redir => g:output
+ silent map <Plug>(ale_show_completion_menu)
+ redir END
+
+ AssertEqual
+ \ [
+ \ 'n <Plug>(ale_show_completion_menu) * :call ale#completion#RestoreCompletionOptions()<CR>',
+ \ 'o <Plug>(ale_show_completion_menu) * <Nop>',
+ \ 'v <Plug>(ale_show_completion_menu) * <Nop>',
+ \ ],
+ \ sort(split(g:output, "\n"))
+
+Execute(Running the normal mode <Plug> keybind should reset the settings):
+ let b:ale_old_omnifunc = 'FooBar'
+ let b:ale_old_completopt = 'menu'
+
+ " We can't run the keybind, but we can call the function.
+ call ale#completion#RestoreCompletionOptions()
+
+ AssertEqual 'FooBar', &l:omnifunc
+ AssertEqual 'menu', &l:completeopt
+ Assert !has_key(b:, 'ale_old_omnifunc')
+ Assert !has_key(b:, 'ale_old_completopt')