osyo-manga / vim-marching

Async clang code completion.
123 stars 5 forks source link

query for completion results before omnifunc is called #12

Open VanLaser opened 9 years ago

VanLaser commented 9 years ago

(this is NOT a bug)

I like to use <tab> for autocompletion with multiple sources: <c-n>, omnifunc (vim-marching) and neosnippets. In my vimrc I have something like this:

"use <tab> for completion
function! TabWrap()
    if pumvisible()
        return "\<C-N>"
    endif
    if strpart( getline('.'), 0, col('.') - 1 ) =~ '^\s*$'
        return "\<tab>"
    elseif exists ('&omnifunc') && &omnifunc != ''
        return "\<C-X>\<C-O>"
    else
        return "\<C-N>"
    endif
endfunction

imap <silent><expr><tab> neosnippet#expandable_or_jumpable() ?
 \ "\<Plug>(neosnippet_expand_or_jump)"
 \: TabWrap()
smap <silent><expr><tab> neosnippet#expandable_or_jumpable() ?
 \ "\<Plug>(neosnippet_expand_or_jump)"
 \: "\<TAB>"

inoremap <expr> <silent> <cr> pumvisible() ? "<c-y>" : "<c-g>u<cr>"

The question is, is it possible to have a vim-marching query function that I can call before return "\<c-x>\<c-o>", similar with neosnippet#expandable_or_jumpable()? The idea being: if the vim-marching omnifunc call returns 0 results, to fall back to <c-n> automatically. Or, is there another, simpler way to do it?

E.g.

elseif exists ('&omnifunc') && &omnifunc != '' && marching#has_results()
        return "\<C-X>\<C-O>"

And ... thanks for the plugin!

osyo-manga commented 9 years ago

Thanks issues :)

hmmmm. It is very hard.... For example, I'll using cache data.

function! s:is_vaild_complete()
    " not has complete keyword
    let context = marching#current_context()
    if context.keyword == ""
        return 0
    endif

    " empty completion data.
    let cache = get(b:, "marching_cache", {})
    if has_key(cache, context.keyword) && empty(cache[context.keyword])
        return 0
    endif
    return 1
endfunction

"use <tab> for completion
function! TabWrap()
    if pumvisible()
"         return "\<C-N>"
    endif
    if strpart( getline('.'), 0, col('.') - 1 ) =~ '^\s*$'
        return "\<tab>"
    elseif exists ('&omnifunc') && &omnifunc != '' && s:is_vaild_complete()
        return "\<C-X>\<C-O>"
    else
        return "\<C-N>"
    endif
endfunction

imap <silent><expr><tab> neosnippet#expandable_or_jumpable() ?
 \ "\<Plug>(neosnippet_expand_or_jump)"
 \: TabWrap()
smap <silent><expr><tab> neosnippet#expandable_or_jumpable() ?
 \ "\<Plug>(neosnippet_expand_or_jump)"
 \: "\<TAB>"

inoremap <expr> <silent> <cr> pumvisible() ? "<c-y>" : "<c-g>u<cr>"

However, it is not perfect :(

And ... thanks for the plugin!

Thanks!! :))

osyo-manga commented 9 years ago

Perhaps if you would have an explicit query marching function, that actually does the completion, returns and caches the results (for the actual omnifunc call)?

It do not know, until completion is end. :( It needs to be perfectly parse C++.

But - this is only a suggestion. I'm sorry that I don't understand enough vimscript to to this myself.

Easy implement.

function! s:can_complete()
    let context = marching#current_context()
    " if has completion keyword(maybe can complete)?
    " e.g. completion keyword is
    " x.ho| => x.
    " ::pri| => ::
    " pri| => is empty keyword :(
    " ( | is cursor pos
    if context.keyword != ""
        return 1
    endif
    return 0
endfunction

"use <tab> for completion
function! TabWrap()
    if pumvisible()
        return "\<C-N>"
    endif
    if strpart( getline('.'), 0, col('.') - 1 ) =~ '^\s*$'
        return "\<tab>"
    elseif exists ('&omnifunc') && &omnifunc != '' && s:can_complete()
        return "\<C-X>\<C-O>"
    else
        return "\<C-N>"
    endif
endfunction
VanLaser commented 9 years ago

Thanks for the answer and explanation! I think I understand now your script above. I will try this solution and think about the best approach to use. After all, I can always default to explicit completion with <c-n>, <c-x><c-o> etc., when something doesn't work as expected.

It needs to be perfectly parse C++.

Indeed, I was thinking of a solution that effectively uses the clang query at this point, to obtain 2 things:

  1. answer to the question "can complete now", using text between 'context' and cursor postion; and
  2. cache results for the actual omnifunc (marching#complete) call

In a way, an explicit call similar to marching#complete outside <c-x><c-o>

osyo-manga commented 9 years ago

Indeed, I was thinking of a solution that effectively uses the clang query at this point, to obtain 2 things:

  1. answer to the question "can complete now"? and

yep, I also want to do it. However, I do not know ...