My Annotated Vim CoC Config
Josh Branchaud
Posted on April 12, 2021
This is extracted directly from the CoC.nvim Example Configuration. I've made some tweaks and annotated some things that work for me.
Here's the whole thing. Below this, I'll break out sections of this that I want to say a bit more about.
""""""""""""""
" CoC Config
""""""""""""""
" Use tab for trigger completion with characters ahead and navigate.
" NOTE: Use command ':verbose imap <tab>' to make sure tab is not mapped by
" other plugin before putting this into your config.
inoremap <silent><expr> <TAB>
\ pumvisible() ? "\<C-n>" :
\ <SID>check_back_space() ? "\<TAB>" :
\ coc#refresh()
inoremap <expr><S-TAB> pumvisible() ? "\<C-p>" : "\<C-h>"
function! s:check_back_space() abort
let col = col('.') - 1
return !col || getline('.')[col - 1] =~# '\s'
endfunction
" Make <CR> auto-select the first completion item and notify coc.nvim to
" format on enter, <cr> could be remapped by other vim plugin
" inoremap <silent><expr> <cr> pumvisible() ? coc#_select_confirm() : "\<C-g>u\<CR>\<c-r>=coc#on_enter()\<CR>"
" Use K to show documentation in preview window.
nnoremap <silent> K :call <SID>show_documentation()<CR>
function! s:show_documentation()
if (index(['vim','help'], &filetype) >= 0)
execute 'h '.expand('<cword>')
elseif (coc#rpc#ready())
call CocActionAsync('doHover')
else
execute '!' . &keywordprg . " " . expand('<cword>')
endif
endfunction
" Use `[g` and `]g` to navigate diagnostics
" Use `:CocDiagnostics` to get all diagnostics of current buffer in location list.
nmap <silent> [g <Plug>(coc-diagnostic-prev)
nmap <silent> ]g <Plug>(coc-diagnostic-next)
I've then also installed coc-tsserver by running:
:CocInstall coc-tsserver
This gives me a ton of useful support for both JavaScript and TypeScript.
The Breakdown
This first bit is the minimal necessary config. This allows me to tab through the list. This also means Shift-Tab
works for going backward through the list. And if you prefer, both Ctrl-n
and Ctrl-p
can be used to go the next and previous items respectively.
inoremap <silent><expr> <TAB>
\ pumvisible() ? "\<C-n>" :
\ <SID>check_back_space() ? "\<TAB>" :
\ coc#refresh()
inoremap <expr><S-TAB> pumvisible() ? "\<C-p>" : "\<C-h>"
function! s:check_back_space() abort
let col = col('.') - 1
return !col || getline('.')[col - 1] =~# '\s'
endfunction
This next bit is supposed to streamline your use of CoC. It automatically highlights the top completion item. Then as soon as you hit Enter
, it completes that item so that you can keep typing.
As you can see, I've commented it out. That is because as great as it is, it comes at an expense. First, it was often auto-completing words unexpectedly when what I was trying to do was create a new line. For instance, in Ruby files, I'd type do
for a block and then hit enter to go the first line of the block's body. Instead, it would auto-complete do
to does
. Second, this overriding of the enter
key was clashing with vim-endwise
which I depend on for Ruby development.
I say leave this out and hit tab
once or twice to get to the completion you want.
" Make <CR> auto-select the first completion item and notify coc.nvim to
" format on enter, <cr> could be remapped by other vim plugin
" inoremap <silent><expr> <cr> pumvisible() ? coc#_select_confirm() : "\<C-g>u\<CR>\<c-r>=coc#on_enter()\<CR>"
This next bit is wonderful for any language server you have running that provides documentation and type definitions. For instance, with TypeScript and coc-tsserver
, I'm able to move the cursor over a variable or function call, hit K
(Shift-k
) and it will provide a pop up with docs and type info.
" Use K to show documentation in preview window.
nnoremap <silent> K :call <SID>show_documentation()<CR>
function! s:show_documentation()
if (index(['vim','help'], &filetype) >= 0)
execute 'h '.expand('<cword>')
elseif (coc#rpc#ready())
call CocActionAsync('doHover')
else
execute '!' . &keywordprg . " " . expand('<cword>')
endif
endfunction
As an avid user of vim-unimpaired
, I love these next two lines. These two bindings allow me to jump forward and backward to the next diagnostics marker. For instance, in a TypeScript file, if I change a type definition, that causes some type errors throughout the file, I can quickly jump to those spots in the file.
" Use `[g` and `]g` to navigate diagnostics
" Use `:CocDiagnostics` to get all diagnostics of current buffer in location list.
nmap <silent> [g <Plug>(coc-diagnostic-prev)
nmap <silent> ]g <Plug>(coc-diagnostic-next)
There may be more to come, but for now this is the configuration I'm working with.
I write and record on all things Vim. If you found this writeup useful, consider joining my newsletter or telling me about it on twitter.
Posted on April 12, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.