In coc.nvim include first entry in autocomplete navigation - vim

I have the following snippet in my config for autocomplete navigation:
function! CheckBackspace() abort
let col = col('.') - 1
return !col || getline('.')[col - 1] =~# '\s'
endfunction
inoremap <silent><expr> <Tab>
\ coc#pum#visible() ? coc#pum#next(1) :
\ CheckBackspace() ? "\<Tab>" :
\ coc#refresh()
Now, when the popup menu opens I can press <CR> to complete the first entry or <Tab> to walk through all other entries. How can I make <Tab> start at the first entry (as in accept completion, not close the window and on more presses walk through the list)?

Related

How to select first item in popup menu and close menu in a single keybind for autocomplete in nvim?

I'm using coc.nvim for autocomplete and when the popup menu appears, I'd like Tab to select the first item and close the menu. At the moment I've keybinded Tab to <C-n><CR>, but the <CR> actually puts in a line return which is not what I want.
inoremap <expr> <Tab> pumvisible() ? "\<C-n><Space>" : "<Tab>"
I found the answer the coc.nvim's example docs:
https://github.com/neoclide/coc.nvim/blob/e1a4ce4d95d1d89b6dd31019cc4387425aa09b86/doc/coc.txt#L892-L909
inoremap <silent><expr> <TAB>
\ pumvisible() ? coc#_select_confirm() :
\ coc#expandableOrJumpable() ?
\ "\<C-r>=coc#rpc#request('doKeymap', ['snippets-expand-jump',''])\<CR>" :
\ <SID>check_back_space() ? "\<TAB>" :
\ coc#refresh()
function! s:check_back_space() abort
let col = col('.') - 1
return !col || getline('.')[col - 1] =~# '\s'
endfunction
let g:coc_snippet_next = '<tab>'
Works like an absolute charm.
Try inoremap <expr> <Tab> pumvisible() ? coc#_select_confirm() : "<Tab>".
After struggling for so long and trying these things I realised it works out the box fine.
To select the first item in the dropdown list press: ctrl+y.
Press: ctrl+n select the next item in the drop down list.
Press: ctrl+p to select the previous item in the drop down list.
To use tab and shift tab as well to navigate next and previous items see the documentation.
To use tab to select first item in the drop down list below the above documentations config:
inoremap <expr> <TAB> pumvisible() ? "\<C-y>" : "\<C-g>u\<TAB>"

omnicomplete in vim with shift-tab not working?

Im trying to get vim to allow me to circle through the autocomplete popup list with the tab key. It works fine for tab but not for s-tab (shift-tab).
It seems like shift-tab somehow canceles the autocomplete menu before applying C-P
Anyone got any ideas?
function InsertTabWrapper(direction)
if pumvisible()
if "forward" == a:direction
return "\<C-N>"
else
return "\<C-P>"
endif
endif
let col = col('.') - 1
if !col || getline('.')[col - 1] !~ '\k'
return "\<tab>"
else
return "\<c-x>\<c-o>"
endif
endfunction
inoremap <tab> <c-r>=InsertTabWrapper("forward")<cr>
inoremap <s-tab> <c-r>InsertTabWrapper("backward")<cr>
You missed the equal sign "=" after <c-r> for the <s-tab> mapping.
However, I would suggest doing it like this:
function! InsertTabWrapper()
if pumvisible()
return "\<c-n>"
endif
let col = col('.') - 1
if !col || getline('.')[col - 1] !~ '\k'
return "\<tab>"
else
return "\<c-x>\<c-o>"
endif
endfunction
inoremap <expr><tab> InsertTabWrapper()
inoremap <expr><s-tab> pumvisible()?"\<c-p>":"\<c-d>"
Use <expr> mapping. It's nicer to see and clearer (many people don't know about <c-r>= things.
Mapping <s-tab> like this and you can do unindent in insertmode.

change from insert to normal mode when switching to another tab?

Say I have multiple tabs with multiple buffers in split screens.
When I am in edit mode in one buffer and switch to another tab (ctrl-pageDown), I am still in insert mode.
Is there a way to automatically switch to normal mode when changing tabs ?
Even better, is it possible to return to insert mode when coming back to the original buffer ?
You could try adding something very simple like
autocmd TabEnter * stopinsert
to your .vimrc.
In BufLeave you could call a function which would check what mode you're in and set a buffer variable and then in BufEnter check if it exists and go to that mode.
See help on mode(), b:var.
Here is some sample stuff for .vimrc. Having written it just now for this purpose, I've started using it myself and I think it'll be useful.
au BufLeave * call ModeSelectBufLeave()
au BufEnter * call ModeSelectBufEnter()
function! ModeSelectBufLeave()
let b:mode_select_mode = mode()
" A more complex addition you could make: if mode() == v, V, <C-V>, s, S, or <C-S>, store the selection and restore it in ModeSelectBufEnter
endfunction
function! ModeSelectBufEnter()
let l:mode = mode()
stopinsert " First, go into normal mode
if (l:mode == "i" || l:mode == "R" || l:mode == "Rv") &&
\ (!exists('b:mode_select_mode') ||
\ b:mode_select_mode == "n" ||
\ b:mode_select_mode == "v" ||
\ b:mode_select_mode == "V" ||
\ b:mode_select_mode == "\<C-V>" ||
\ b:mode_select_mode == "s" ||
\ b:mode_select_mode == "S" ||
\ b:mode_select_mode == "\<C-S>")
normal l
" Compensate for the left cursor shift in stopinsert if going from an
" insert mode to a normal mode
endif
if !exists('b:mode_select_mode')
return
elseif b:mode_select_mode == "i"
startinsert
elseif b:mode_select_mode == "R"
startreplace
elseif b:mode_select_mode == "Rv"
startgreplace
endif
endfunction
I have the following in my .vimrc:
nmap <C-b> :b#<CR>
imap <C-b> <ESC>:b#<CR>
This lets me hit Ctrl+b when in normal or insert mode to switch to the alternate buffer but leaving me in normal mode.
As for your question, you could do this:
imap <C-b> <ESC>:bnext<CR>i
This will let you hit Ctrl+b when in insert mode and switch to the next buffer putting you in insert mode when you get there.
If you find yourself switching back and forth between the same two buffers, my original mappings above may be more useful. Of course if you use all three, you'll need a different key combination for the last one.

how to map keys for popup menu in vim

After a completion try, omnicppcomplete will display all the possible items in the pop up menu . To select an certain item in the menu, one should use <C-N> and <C-p> to switch back and forth between different items. I feel that it is very inconvient . It should be very cool if j and k can be used to to take place of <C-N> and <C-P> . so how should I do ?
function! OmniPopup(action)
if pumvisible()
if a:action == 'j'
return "\<C-N>"
elseif a:action == 'k'
return "\<C-P>"
endif
endif
return a:action
endfunction
inoremap <silent>j <C-R>=OmniPopup('j')<CR>
inoremap <silent>k <C-R>=OmniPopup('k')<CR>
I prefer using the tab key for completion (I am not sure where I got this from):
"tab complete
function! InsertTabWrapper(direction)
let col = col('.') - 1
if !col || getline('.')[col - 1] !~ '\k'
return "\<tab>"
elseif "backward" == a:direction
return "\<c-p>"
else
return "\<c-n>"
endif
endfunction
inoremap <tab> <c-r>=InsertTabWrapper ("forward")<cr>
inoremap <s-tab> <c-r>=InsertTabWrapper ("backward")<cr>
CTRL+J and CTRL+K instead: (so you can type j and k)
inoremap <expr><C-J> pumvisible() ? "\<C-n>" : "\<C-J>"
inoremap <expr><C-K> pumvisible() ? "\<C-p>" : "\<C-K>"
Bonus: <ENTER> to select the option
inoremap <expr><Cr> pumvisible() ? "\<C-y>" : "\<Cr>"

Mapping Tab to Omicompletion in GVim

Omnicompletion works pressing <C-X><C-O> making a dropdown list appear.
I wanted to map it as <S-Tab> <C-X><C-O> but first I wanted to test it as: <C-F5> <C-X><C-O>.
It does complete the word but the dropdown list doesn't show up. (the same happens with the plugin SuperTab).
Any suggestions?
EDIT: it Works like this inoremap <S-F5> <C-X><C-O> but it doesn't work like this inoremap <Tab> <C-X><C-O> or <TAB> <C-X><C-O>
CODE:
" autocomplete using tab
imap <C-F5> <C-X><C-O>
One day, I found this (probably on vim.org):
fu! InsertTabWrapper(direction)
let char_before = col('.') - 1
if !char_before || getline('.')[char_before - 1] !~ '\k'
return "\<tab>"
elseif "backward" == a:direction
return "\<c-p>"
else
return "\<c-n>"
endif
endfu
inoremap <tab> <c-r>=InsertTabWrapper("forward")<cr>
inoremap <s-tab> <c-r>=InsertTabWrapper("backward")<cr>
And it works like a charm.

Resources