maralla / completor.vim

Async completion framework made ease.
MIT License
1.32k stars 62 forks source link

Placeholders for function arguments - integration with CompleteParameter.vim #319

Closed rkueke closed 1 month ago

rkueke commented 2 years ago

Hi Maralla For c/c++ /python embedded development I use a lightweight toolchain based on Vim8.1, Make, Clang, Ale, UltiSnips, and Completor. The only missing link is a UltiSnips compatible generation/editing of placeholders for function args during the symbol-completion process.

I think you are aware about TenfyZhong's plugin CompleteParameter.vim which offers all the features including an integration with UltiSnips, but currently only for the completors ycm, deoplete, neocomplete, and clang_complete.

I installed tenfy's plugin - and suprise the placeholder generation was not triggered from completor's pum.

Wouldn't it be worth to think about a proper link between completor and completeparameter? I opened a similar issue at CompletorParameter.vim.

rkueke commented 2 years ago

Here is the corresponding issue at CompleteParameter.vim where you can follow our discussion regarding Support for Completor.vim #55 .

rkueke commented 2 years ago

Hi Maralla Here is a simple extention of your Tab_or_Complete function.

It inserts function completions including their signature placeholders based on UltiSnips anonymous snippets. The setup fully integrates the expansion of snippets with a minimum of configuration effort.

For my c development it works fine but I think it can easily be extended to other languages.

" ULTISNIPS

" Use of default UltiSnips key bindings for JumpForward <C-j>, JumpBackward <C-k>.
" JumpForward/Backward with <Tab>/<S-Tab> are more handy but block a completion within snippets.
" Default ExpandTrigger <Tab> is overwritten to avoid conflict with Completor's completion <Tab>.
let g:UltiSnipsExpandTrigger       = "<C-Tab>"

" COMPLETOR integrated with UltiSnips

let g:completor_auto_trigger = 0
let g:completor_clang_binary = '/usr/bin/clang'

" Use TAB to complete when typing words, else inserts TABs as usual.  Uses
" dictionary, source files, and completor to find matching words to complete.
function! Tab_Or_Complete() abort
    " If completor is already open the `tab` cycles through suggested completions.
    if pumvisible()
        return "\<C-N>"
        " If completor is not open and we are in the middle of typing a word then
        " `tab` opens completor menu.
    elseif col('.')>1 && strpart( getline('.'), col('.')-2, 3 ) =~ '^[[:keyword:][:ident:]]'
        return "\<C-R>=completor#do('complete')\<CR>"
    else
        " If we aren't typing a word and we press `tab` simply do the normal `tab`
        " action.
        return "\<Tab>"
    endif
endfunction

" Use tab to trigger auto completion.
inoremap <expr> <Tab> Tab_Or_Complete()

" Use <Tab> and <S-Tab> keys to select a completion.
" Use <CR> to complete or expand snippet
inoremap <expr> <S-Tab> pumvisible() ? "\<C-p>" : "\<S-Tab>"
inoremap <expr> <CR> pumvisible() ? "\<C-y>\<C-r>=Complete_Or_Ultisnips()\<CR>" : "\<CR>"
inoremap <expr> <BS> pumvisible() ? "\<BS>\<C-r>=completor#do('complete')\<CR>" : "\<BS>"

func! Complete_Or_Ultisnips()
    let menu = v:completed_item.menu
    " Expand selected snippet
    let snipstr = matchstr(menu, 'snip')
    if !empty (snipstr)
        let g:ulti_expand_res = 0
        let snippet = UltiSnips#ExpandSnippet()
        if g:ulti_expand_res > 0
            return snippet
        endif
    endif
    " Insert function signature if available
    let argstr =  matchstr(menu, '(\zs.*\ze)')
    if !empty (argstr)
        call GenerateSignatureSnippet(argstr)
    endif
    return ''
endfunc

func! GenerateSignatureSnippet(argsStr)
    let argsList = split(a:argsStr, ",")
    let snippet = ""
    let c = 1
    " Build an anonymous snippet of signature placeholders 
    for i in argsList
        if c > 1
            let snippet = snippet . ", "
        endif
        let arg = substitute(i, '^\s*\(.\{-}\)\s*$', '\1', '')
        let snippet = snippet . '${'.c.":".arg.'}'
        let c += 1
    endfor
    let snippet = "(" . snippet . ")$0"
    call UltiSnips#Anon(snippet)
endfunc