Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to trigger omnicomplete/auto-completion on keystrokes in INSERT mode?

Tags:

VIM's omnicomplete autocompletion is not really working as expected.

Is there a way to make it smarter? Like, to monitor the context of surround text? (e.g. don't trigger if within comments or quotes)

I ask because I cannot get to a happy place since switching to Vim when compared to the autocomplete/IntelliSense in IDEs such as Visual Studio, IntelliJ, Sublime and Atom (I've used all of these for development in the past).

The basic goals to this question:

  • Can Omnicomplete be triggered on A-Za-z keystrokes in INSERT mode? I already have it being triggered via "." dot symbols.
  • How to get Omnicomplete to insert the func's parameters?

I am new to Vim for a few months and desperately trying to get a smooth workflow. But without a good autocomplete option, while forcing me to be more vigilant in learning the code I am trying to use, it is greatly slowly me down over other IDEs I've used in the past.

Atom + Go-Plus

Let's examine my expectations with Atom + Go-Plus.

I have a func named func generate(entropy chan<- uint64) located elsewhere in another Go file in the same package.

When I type the letter g on line 22, I immediately get a prompt with everything that begins with g:

Atom's autocomplete with Go-Plus

As you can see, there are 3 options that immediately pop up (the first two I think are just code snippets). I can use an arrow key to scroll down to either option.

If I select the 3rd option (or if I continue to type gen the field narrows down to only 1 option), and press enter Atom/Visual Studio/Sublime all fill out the details of the method for me:

atom with go-plus autocompletion

I did not type any of the above. It was inserted and I can override the details, modify them, or just TAB off and continue typing.

Vim + Vim-Go (really Omnicomplete)

Let's compare that with my current (maybe broken?) config of omnicomplete. I have this in my .vimrc:

set completeopt=longest,menuone

Within vim, if I type gen, all I get is what seems to be my previously entered text that I typed elsewhere in this buffer (and only in this buffer, not in other buffers). If I happen to misspell something, all I get the misspelled version I previously entered for the life that I have vim open. This tells me there is no IntelliSense/autocomplete at work - just something monitoring the keystrokes I make:

vim with omnicomplete and autocomplete not working

As you can see, autocomplete isn't working as I type. Though, this does come in handy with comments and strings in other places and I kind of like how vim remembers my free-text I type.

Not really sure what Vim option is enabling this; but, it is not autocompletion.

Now, I can press CTRL-X + CTRL-O to force autocompletion and get generate() to show up:

vim with omnicomplete and autocomplete

This is better; but, I would expect it to show me autocomplete options as I type: not requiring 3 additional keystrokes to make it happen. That is a whole lot of C-x C-o happenings throughout a few hours of coding.

Is there a way to have Vim monitor my keystrokes in INSERT mode and display autocomplete if there is a matching ctag or function? That may be the answer to this functionality.

Autocomplete with Parameters

There is a 2nd problem with autocompletion with omnicomplete that I could overlook the C-x C-o requirement of the above if this worked: once I do select the method I want to autocomplete, it does not insert the parameters/fields for me.

Going back to the screenshot above, if I select that method, this is what I get:

vim with vim-go autocomplete not fully completing

Notice that it does not insert the func's paramters. It does not match the 2nd picture posted above, where the autocomplete in Atom, Sublime, and Visual Studio all complete the method with parameters showing.

I have read the vim wikia and have tried various options with set completeopt without any viable alternative.

For example, set completeopt+=preview gives me the preview window after selecting:

enter image description here

Why giving me the parameters in a preview, it still does not autocomplete my line 22 of code and is often a distraction (I often times disable it because I type far faster than having to stop and "look up" all the time).

It took a lot of tweaking of the config file to get the below working; but, I was able to get "dot" autocompletion to work. So, there is some form of autocompletion working:

vim and vim-go autocompletion with dot

But again, it does not fill in the parameters once I select a function which is pretty annoying to have to type ESC + back arrow + back arrow + : + GoDoc just to see what it was: that's 10 character strokes to see what it was.

Sure, Atom, Sublime, and VS is much prettier when "dot autocompleting":

atom and go-plus dot autocompletion

(it is also better ordered by types, though I do have vim setup to remember the last used at the top so that helps). But I don't care about pretty - I just want my parameters to show up when selecting with 'dot'.

Any advice in how to tweak my vim-go and related plugins would be very welcome as I'd prefer to stay with Vim over any IDEs. Thank you.

EDIT:

I see that the author of vim-go has worked on the parameters-completion part and got it working:

autocompletion with parameters in vim-go

Though, I can't seem to get it working on my install (still debugging it), I wanted to show others that it is indeed possible to have autocomplete with parameters being filled.

like image 827
eduncan911 Avatar asked Mar 07 '16 07:03

eduncan911


People also ask

How do I autocomplete in Vim?

to enter the *edit* mode and type any JavaScript keyword in the text editor and press *Ctrl + x* followed by *Ctrl + o*. Vim editor will show the possible auto-complete suggestions.

What is Omni complete?

Omni completion provides smart autocompletion for programs. When invoked, the text before the cursor is inspected to guess what might follow. A popup menu offers word completion choices that may include struct and class members, system functions, and more.


2 Answers

Can Omnicomplete be triggered on A-Za-z keystrokes in INSERT mode?

You can listen to InsertCharPre event and check what keys have been pressed.

function! OpenCompletion()
    if !pumvisible() && ((v:char >= 'a' && v:char <= 'z') || (v:char >= 'A' && v:char <= 'Z'))
        call feedkeys("\<C-x>\<C-o>", "n")
    endif
endfunction

autocmd InsertCharPre * call OpenCompletion()

Also you should set completeopt+=menuone,noselect,noinsert to avoid vim inserting completion text automatically. But keep in mind it is not common decision and you will probably have some issues. The one I have found is it breaks cgn command.

For further reading do help InsertCharPre, help autocmd-events, help pumvisible(), help feedkeys().

How to get Omnicomplete to insert the func's parameters?

I used sublime for a some years and it represents builtin functions (default vim omnicompletion) with snippets. So if you want parameters to be inserted into the buffer you need to:

  1. Install snippet manager like ultisnips, neosnippet, minisnip, xptemplate or others.
  2. Create a bunch of snippets or install from somewhere.
  3. Make your completion system recognize preferred snippet manager (many completion managers recognize ultisnips).

If you change your mind in the way of using so called preview window you mentioned above here are some tips:

  1. It is possible to show preview window at the bottom of the screen set splitbelow.
  2. You can set previewheight option to change its size.
  3. To automatically close window after completion is done autocmd CompleteDone * pclose.

For further reading do help ins-completion and help preview-window

like image 76
Evgeniy Avatar answered Sep 22 '22 07:09

Evgeniy


I found that the answer by @Evgeniy to be almost perfect - but I did find that when replaying macros, the cursor would sometimes drop down a line (which would break the macro). I managed to solve it with the following functions and autocmds:

set completeopt+=menuone,noselect,noinsert " don't insert text automatically
set pumheight=5 " keep the autocomplete suggestion menu small
set shortmess+=c " don't give ins-completion-menu messages

" if completion menu closed, and two non-spaces typed, call autocomplete
let s:insert_count = 0
function! OpenCompletion()
    if string(v:char) =~ ' '
        let s:insert_count = 0
    else                    
        let s:insert_count += 1
    endif
    if !pumvisible() && s:insert_count >= 2
        silent! call feedkeys("\<C-n>", "n")
    endif
endfunction

function! TurnOnAutoComplete()
    augroup autocomplete
        autocmd!
        autocmd InsertLeave let s:insert_count = 0
        autocmd InsertCharPre * silent! call OpenCompletion()
    augroup END
endfunction

function! TurnOffAutoComplete()
    augroup autocomplete
        autocmd!
    augroup END
endfunction

function! ReplayMacroWithoutAutoComplete()
    call TurnOffAutoComplete()
    let reg = getcharstr()
    execute "normal! @".reg
    call TurnOnAutoComplete()
endfunction

call TurnOnAutoComplete()

" don't let the above mess with replaying macros
nnoremap <silent> @ :call ReplayMacroWithoutAutoComplete()<CR>

" use tab for navigating the autocomplete menu
inoremap <expr> <TAB> pumvisible() ? "\<C-n>" : "\<TAB>"
inoremap <expr> <S-TAB> pumvisible() ? "\<C-p>" : "\<TAB>"
like image 45
mattb Avatar answered Sep 21 '22 07:09

mattb