vim

My Annotated Vim CoC Config

jbranchaud

Josh Branchaud

Posted on April 12, 2021

My Annotated Vim CoC Config

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)
Enter fullscreen mode Exit fullscreen mode

I've then also installed coc-tsserver by running:

:CocInstall coc-tsserver
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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>"
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

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.

💖 💪 🙅 🚩
jbranchaud
Josh Branchaud

Posted on April 12, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related