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:
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.
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:
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:
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.
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:
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:
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.
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:
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:
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:
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":
(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:
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.
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.
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.
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:
If you change your mind in the way of using so called preview window you mentioned above here are some tips:
set splitbelow
.set previewheight
option to change its size.autocmd CompleteDone * pclose
.For further reading do help ins-completion
and help preview-window
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>"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With