Close #2285 - Add a function for use with omnifunc

This commit is contained in:
w0rp 2019-05-17 00:57:52 +01:00
parent 8cb6d043b4
commit e5ea809094
No known key found for this signature in database
GPG key ID: 0FC1ECAA8C81CD83
5 changed files with 135 additions and 9 deletions

View file

@ -168,6 +168,13 @@ other plugins, and can be enabled by changing a setting before ALE is loaded.
let g:ale_completion_enabled = 1 let g:ale_completion_enabled = 1
``` ```
ALE provides an omni-completion function you can use for triggering
completion manually with `<C-x><C-o>`.
```vim
set omnifunc=ale#completion#OmniFunc
```
See `:help ale-completion` for more information. See `:help ale-completion` for more information.
<a name="usage-go-to-definition"></a> <a name="usage-go-to-definition"></a>

View file

@ -169,7 +169,7 @@ function! s:ReplaceCompletionOptions() abort
let b:ale_old_omnifunc = &l:omnifunc let b:ale_old_omnifunc = &l:omnifunc
endif endif
let &l:omnifunc = 'ale#completion#OmniFunc' let &l:omnifunc = 'ale#completion#AutomaticOmniFunc'
endif endif
if l:source is# 'ale-automatic' if l:source is# 'ale-automatic'
@ -235,7 +235,7 @@ function! ale#completion#GetCompletionResult() abort
return v:null return v:null
endfunction endfunction
function! ale#completion#OmniFunc(findstart, base) abort function! ale#completion#AutomaticOmniFunc(findstart, base) abort
if a:findstart if a:findstart
return ale#completion#GetCompletionPosition() return ale#completion#GetCompletionPosition()
else else
@ -279,6 +279,7 @@ function! s:CompletionStillValid(request_id) abort
\&& ( \&& (
\ b:ale_completion_info.column == l:column \ b:ale_completion_info.column == l:column
\ || b:ale_completion_info.source is# 'deoplete' \ || b:ale_completion_info.source is# 'deoplete'
\ || b:ale_completion_info.source is# 'ale-omnifunc'
\) \)
endfunction endfunction
@ -570,7 +571,7 @@ function! ale#completion#GetCompletions(source) abort
let l:prefix = ale#completion#GetPrefix(&filetype, l:line, l:column) let l:prefix = ale#completion#GetPrefix(&filetype, l:line, l:column)
if a:source is# 'ale-automatic' && empty(l:prefix) if a:source is# 'ale-automatic' && empty(l:prefix)
return return 0
endif endif
let l:line_length = len(getline('.')) let l:line_length = len(getline('.'))
@ -584,16 +585,47 @@ function! ale#completion#GetCompletions(source) abort
\ 'request_id': 0, \ 'request_id': 0,
\ 'source': a:source, \ 'source': a:source,
\} \}
unlet! b:ale_completion_response
unlet! b:ale_completion_parser
unlet! b:ale_completion_result unlet! b:ale_completion_result
let l:buffer = bufnr('') let l:buffer = bufnr('')
let l:Callback = function('s:OnReady') let l:Callback = function('s:OnReady')
let l:started = 0
for l:linter in ale#linter#Get(&filetype) for l:linter in ale#linter#Get(&filetype)
if !empty(l:linter.lsp) if !empty(l:linter.lsp)
call ale#lsp_linter#StartLSP(l:buffer, l:linter, l:Callback) if ale#lsp_linter#StartLSP(l:buffer, l:linter, l:Callback)
let l:started = 1
endif
endif endif
endfor endfor
return l:started
endfunction
function! ale#completion#OmniFunc(findstart, base) abort
if a:findstart
let l:started = ale#completion#GetCompletions('ale-omnifunc')
if !l:started
" This is the special value for cancelling completions silently.
" See :help complete-functions
return -3
endif
return ale#completion#GetCompletionPosition()
else
let l:result = ale#completion#GetCompletionResult()
while l:result is v:null && !complete_check()
sleep 2ms
let l:result = ale#completion#GetCompletionResult()
endwhile
return l:result isnot v:null ? l:result : []
endif
endfunction endfunction
function! s:TimerHandler(...) abort function! s:TimerHandler(...) abort

View file

@ -342,6 +342,12 @@ is loaded. The delay for completion can be configured with
|g:ale_completion_delay|. This setting should not be enabled if you wish to |g:ale_completion_delay|. This setting should not be enabled if you wish to
use ALE as a completion source for other plugins. use ALE as a completion source for other plugins.
ALE provides an 'omnifunc' function |ale#completion#OmniFunc| for triggering
completion manually with CTRL-X CTRL-O. |i_CTRL-X_CTRL-O| >
" Use ALE's function for omnicompletion.
set omnifunc=ale#completion#OmniFunc
<
ALE will only suggest so many possible matches for completion. The maximum ALE will only suggest so many possible matches for completion. The maximum
number of items can be controlled with |g:ale_completion_max_suggestions|. number of items can be controlled with |g:ale_completion_max_suggestions|.
@ -2790,6 +2796,13 @@ ale#command#ManageFile(buffer, filename) *ale#command#ManageFile()*
manages directories separately with the |ale#command#ManageDirectory| function. manages directories separately with the |ale#command#ManageDirectory| function.
ale#completion#OmniFunc(findstart, base) *ale#completion#OmniFunc()*
A completion function to use with 'omnifunc'.
See |ale-completion|.
ale#engine#GetLoclist(buffer) *ale#engine#GetLoclist()* ale#engine#GetLoclist(buffer) *ale#engine#GetLoclist()*
Given a buffer number, this function will return the list of problems Given a buffer number, this function will return the list of problems

View file

@ -139,7 +139,7 @@ Execute(ale#completion#Show() should remember the omnifunc setting and replace i
call ale#completion#Show('Response', 'Parser') call ale#completion#Show('Response', 'Parser')
AssertEqual 'FooBar', b:ale_old_omnifunc AssertEqual 'FooBar', b:ale_old_omnifunc
AssertEqual 'ale#completion#OmniFunc', &l:omnifunc AssertEqual 'ale#completion#AutomaticOmniFunc', &l:omnifunc
AssertEqual [], g:feedkeys_calls AssertEqual [], g:feedkeys_calls
sleep 1ms sleep 1ms
@ -184,20 +184,20 @@ Execute(ale#completion#Show() should not replace the completeopt setting for man
sleep 1ms sleep 1ms
AssertEqual [["\<Plug>(ale_show_completion_menu)"]], g:feedkeys_calls AssertEqual [["\<Plug>(ale_show_completion_menu)"]], g:feedkeys_calls
Execute(ale#completion#OmniFunc() should also remember the completeopt setting and replace it): Execute(ale#completion#AutomaticOmniFunc() should also remember the completeopt setting and replace it):
let &l:completeopt = 'menu' let &l:completeopt = 'menu'
let b:ale_completion_info = {'source': 'ale-automatic'} let b:ale_completion_info = {'source': 'ale-automatic'}
call ale#completion#OmniFunc(0, '') call ale#completion#AutomaticOmniFunc(0, '')
AssertEqual 'menu', b:ale_old_completeopt AssertEqual 'menu', b:ale_old_completeopt
AssertEqual 'menu,menuone,noselect,noinsert', &l:completeopt AssertEqual 'menu,menuone,noselect,noinsert', &l:completeopt
Execute(ale#completion#OmniFunc() should set the preview option if it's set): Execute(ale#completion#AutomaticOmniFunc() should set the preview option if it's set):
let &l:completeopt = 'menu,preview' let &l:completeopt = 'menu,preview'
let b:ale_completion_info = {'source': 'ale-automatic'} let b:ale_completion_info = {'source': 'ale-automatic'}
call ale#completion#OmniFunc(0, '') call ale#completion#AutomaticOmniFunc(0, '')
AssertEqual 'menu,preview', b:ale_old_completeopt AssertEqual 'menu,preview', b:ale_old_completeopt
AssertEqual 'menu,menuone,preview,noselect,noinsert', &l:completeopt AssertEqual 'menu,menuone,preview,noselect,noinsert', &l:completeopt
@ -317,6 +317,8 @@ Execute(b:ale_completion_info should be set up correctly when requesting complet
Execute(b:ale_completion_info should be set up correctly for other sources): Execute(b:ale_completion_info should be set up correctly for other sources):
let b:ale_completion_result = [] let b:ale_completion_result = []
let b:ale_completion_response = []
let b:ale_completion_parser = 'type'
call setpos('.', [bufnr(''), 3, 14, 0]) call setpos('.', [bufnr(''), 3, 14, 0])
call ale#completion#GetCompletions('deoplete') call ale#completion#GetCompletions('deoplete')
@ -332,6 +334,8 @@ Execute(b:ale_completion_info should be set up correctly for other sources):
\ }, \ },
\ b:ale_completion_info \ b:ale_completion_info
Assert !exists('b:ale_completion_result') Assert !exists('b:ale_completion_result')
Assert !exists('b:ale_completion_response')
Assert !exists('b:ale_completion_parser')
Execute(The correct keybinds should be configured): Execute(The correct keybinds should be configured):
redir => g:output redir => g:output

View file

@ -0,0 +1,70 @@
Before:
unlet! b:ale_completion_info
unlet! b:ale_completion_response
unlet! b:ale_completion_parser
unlet! b:ale_completion_result
let b:lsp_started = 0
runtime autoload/ale/lsp_linter.vim
function! ale#lsp_linter#StartLSP(buffer, linter, Callback) abort
return b:lsp_started
endfunction
function! Identity(x) abort
return a:x
endfunction
function! SetCompletionResult(...) abort
let b:ale_completion_result = ['foo']
endfunction
function! SetCompletionResponse(...) abort
let b:ale_completion_response = ['foo']
let b:ale_completion_parser = 'Identity'
endfunction
After:
unlet! b:ale_completion_info
unlet! b:ale_completion_response
unlet! b:ale_completion_parser
unlet! b:ale_completion_result
unlet! b:lsp_started
delfunction Identity
delfunction SetCompletionResult
delfunction SetCompletionResponse
runtime autoload/ale/lsp_linter.vim
call ale#linter#Reset()
Given typescript():
let abc = y.
let foo = ab
let foo = (ab)
Execute(-3 should be returned when completion results cannot be requested):
AssertEqual -3, ale#completion#OmniFunc(1, '')
Execute(The start position should be returned when results can be requested):
let b:lsp_started = 1
call setpos('.', [bufnr(''), 3, 14, 0])
AssertEqual 11, ale#completion#OmniFunc(1, '')
Execute(The omnifunc function should return async results):
" Neovim 0.2.0 struggles at running these tests.
if !has('nvim') || has('nvim-0.3.0')
call timer_start(0, function('SetCompletionResult'))
AssertEqual ['foo'], ale#completion#OmniFunc(0, '')
endif
Execute(The omnifunc function should parse and return async responses):
if !has('nvim') || has('nvim-0.3.0')
call timer_start(0, function('SetCompletionResponse'))
AssertEqual ['foo'], ale#completion#OmniFunc(0, '')
endif