Add support for context aware completion

If complete operation is given context property containing the
current toplevel form Compliment library can give better completion
results in some contexts:

- Local vars for let and defn
- Resources in classpath for io/resource calls
- Vars in specific ns for :require :refer
- Better Java class name completion for :import

The context string should contain symbol __prefix__ in place of the word
being completed. To achieve this location of cursor inside the toplevel
form is calculated so that the placeholder symbol can be placed in the
proper place.
This commit is contained in:
Juho Teperi 2015-05-17 00:06:35 +03:00
parent 1646a01b0b
commit c22e61c69b

View File

@ -108,6 +108,37 @@ function! s:candidate(val) abort
\ }
endfunction
function! s:get_complete_context() abort
" Find toplevel form
" If cursor is on start parenthesis we don't want to find the form
" If cursor is on end parenthesis we want to find the form
let [line1, col1] = searchpairpos('(', '', ')', 'Wrnb', g:fireplace#skip)
let [line2, col2] = searchpairpos('(', '', ')', 'Wrnc', g:fireplace#skip)
if (line1 == 0 && col1 == 0) || (line2 == 0 && col2 == 0)
return ""
endif
if line1 == line2
let expr = getline(line1)[col1-1 : col2-1]
else
let expr = getline(line1)[col1-1 : -1] . ' '
\ . join(getline(line1+1, line2-1), ' ')
\ . getline(line2)[0 : col2-1]
endif
" Calculate the position of cursor inside the expr
if line1 == line('.')
let p = col('.') - col1
else
let p = strlen(getline(line1)[col1-1 : -1])
\ + strlen(join(getline(line1 + 1, line('.') - 1), ' '))
\ + col('.')
endif
return strpart(expr, 0, p) . '__prefix__' . strpart(expr, p)
endfunction
function! fireplace#omnicomplete(findstart, base) abort
if a:findstart
let line = getline('.')[0 : col('.')-2]
@ -116,7 +147,12 @@ function! fireplace#omnicomplete(findstart, base) abort
try
if fireplace#op_available('complete')
let response = fireplace#message({'op': 'complete', 'symbol': a:base, 'extra-metadata': ['arglists', 'doc']})
let response = fireplace#message({
\ 'op': 'complete',
\ 'symbol': a:base,
\ 'extra-metadata': ['arglists', 'doc'],
\ 'context': s:get_complete_context()
\ })
let trans = '{"word": (v:val =~# ''[./]'' ? "" : matchstr(a:base, ''^.\+/'')) . v:val}'
let value = get(response[0], 'value', get(response[0], 'completions'))
if type(value) == type([])