From c22e61c69bc4eabb53629f376bfeb2dfd6208732 Mon Sep 17 00:00:00 2001 From: Juho Teperi Date: Sun, 17 May 2015 00:06:35 +0300 Subject: [PATCH] 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. --- plugin/fireplace.vim | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/plugin/fireplace.vim b/plugin/fireplace.vim index be6650c..c03a47f 100644 --- a/plugin/fireplace.vim +++ b/plugin/fireplace.vim @@ -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([])