4

I can complete functions with omnicomplete using c-x c-o but it only adds the opening parenthesis, is it possible to make it add the closing parenthesis and put my cursor between them? Seems unaffected by auto-pairs and delimitmate, which work fine when I type the opening parenthesis, but not when it's inserted during completion.

3

You could try the following code:

inoremap <C-x><C-o> <C-r>=<SID>close_paren()<CR><C-x><C-o>

function! s:close_paren() abort
    augroup close_paren
        autocmd!
        autocmd CompleteDone <buffer> if v:completed_item.word =~# '($'
                                   \|     call feedkeys(")\<Left>", 'in')
                                   \| endif
                                   \| autocmd! close_paren
                                   \| augroup! close_paren
    augroup END
    return ''
endfunction

It should remap the key sequence C-x C-o, so that the custom function s:close_paren() is evaluated before invoking omni completion.

The function installs a fire-once autocmd, watching the CompleteDone event, described in :h completedone:

CompleteDone    After Insert mode completion is done.  Either
                when something was completed or abandoning
                completion. |ins-completion|
                The |v:completed_item| variable contains
                information about the completed item.

The autocmd inserts the keys:

)<Left>

... in the typeahead buffer. That is a closing parenthesis, then the Left key to position the cursor between the 2 parentheses.

If you want to change the inserted keys, you can do so by changing them inside the first argument passed to the feedkeys() function, whose usage is explained in :h feedkeys():

feedkeys({string} [, {mode}])               *feedkeys()*

    Characters in {string} are queued for processing as if they
    come from a mapping or were typed by the user.
    By default the string is added to the end of the typeahead
    buffer, thus if a mapping is still being executed the
    characters come after them.  Use the 'i' flag to insert before
    other characters, they will be executed next, before any
    characters from a mapping.
    The function does not wait for processing of keys contained in
    {string}.
    To include special keys into {string}, use double-quotes
    and "\..." notation |expr-quote|. For example,
    feedkeys("\<CR>") simulates pressing of the <Enter> key. But
    feedkeys('\<CR>') pushes 5 characters.

The 2nd argument ('in') contains 2 flags whose meaning is explained like this:

    'n' Do not remap keys.

    'i' Insert the string instead of appending (see above).

The autocmd should be local to the buffer because of the pattern <buffer>, and delete itself once the completion has been performed, because of these commands:

autocmd! close_paren
augroup! close_paren

The first one removes the autocmd from the augroup, the 2nd one removes the augroup. You can't remove an augroup if it's not empty, as explained in :h augroup-delete:

:aug[roup]! {name}      Delete the autocmd group {name}.  Don't use
                        this if there is still an autocommand using
                        this group!  You will get a warning if doing
                        it anyway. when the group is the current group
                        you will get error E936.

The reason why the autocmd removes itself is because even though you want to close a parenthesis when invoking omni completion, you may not want this behavior for every other kind of completion.

If you use the mapping, don't like any suggestion in the popup menu, and exit the latter by hitting C-e, or if you don't complete a function name but another kind of syntax element, the autocmd shouldn't insert anything, because it checks whether the last character is an open parenthesis:

if v:completed_item.word =~# '($'

v:completed_item is an internal variable containing a dictionary with various information related to the last text you completed. Here, you only use the key word to be sure the last character is an open parenthesis, but if you wanted more info, maybe to build a more complex condition before deciding to call feedkeys(), you could use other keys.

Currently there seems to be 5 of them:

word
menu
info
kind
abbr

The meaning of their values is given in :h complete-items:

word        the text that will be inserted, mandatory

abbr        abbreviation of "word"; when not empty it is used in
            the menu instead of "word"

menu        extra text for the popup menu, displayed after "word"
            or "abbr"

info        more information about the item, can be displayed in a
            preview window

kind        single letter indicating the type of completion
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.