Make your Vim/Neovim as smart as VS Code
Custom popup menu with snippet support
Fast: separated NodeJS process that does not slow down Vim most of the time.
? Reliable: typed language, tested with CI.
? Featured: all LSP 3.16 features are supported, see :h coc-lsp
.
❤️ Flexible: configured like VS Code, Coc extensions function similarly to VS Code extensions
Make sure use Vim >= 9.0.0438 or Neovim >= 0.8.0.
Install nodejs >= 16.18.0:
curl -sL install-node.vercel.app/lts | bash
For vim-plug users:
" Use release branch (recommended)Plug 'neoclide/coc.nvim', {'branch': 'release'}" Or build from source code by using npmPlug 'neoclide/coc.nvim', {'branch': 'master', 'do': 'npm ci'}
in your .vimrc
or init.vim
, then restart Vim and run :PlugInstall
.
Checkout Install coc.nvim for more info.
You have to install coc extensions or configure language servers for LSP support.
Install extensions like this:
:CocInstall coc-json coc-tsserver
Or you can configure a language server in your coc-settings.json
(open it using :CocConfig
) like this:
{ "languageserver": {"go": { "command": "gopls", "rootPatterns": ["go.mod"], "trace.server": "verbose", "filetypes": ["go"] } } }
Checkout the wiki for more details:
Completion with sources
Using the configuration file
Using coc extensions
Configure language servers
F.A.Q
Checkout :h coc-nvim
for Vim interface.
Configuration is required to make coc.nvim easier to work with, since it doesn't change your key-mappings or Vim options. This is done as much as possible to avoid conflict with your other plugins.
❗️Important: Some Vim plugins can change your key mappings. Please use
command like:verbose imap <tab>
to make sure that your keymap has taken effect.
" https://raw.githubusercontent.com/neoclide/coc.nvim/master/doc/coc-example-config.vim" May need for Vim (not Neovim) since coc.nvim calculates byte offset by count" utf-8 byte sequenceset encoding=utf-8" Some servers have issues with backup files, see #649set nobackupset nowritebackup" Having longer updatetime (default is 4000 ms = 4s) leads to noticeable" delays and poor user experienceset updatetime=300" Always show the signcolumn, otherwise it would shift the text each time" diagnostics appear/become resolvedset signcolumn=yes" Use tab for trigger completion with characters ahead and navigate" NOTE: There's always complete item selected by default, you may want to enable" no select by `"suggest.noselect": true` in your configuration file" NOTE: Use command ':verbose imap <tab>' to make sure tab is not mapped by" other plugin before putting this into your configinoremap <silent><expr> <TAB> coc#pum#visible() ? coc#pum#next(1) : CheckBackspace() ? "<Tab>" : coc#refresh()inoremap <expr><S-TAB> coc#pum#visible() ? coc#pum#prev(1) : "<C-h>"" Make <CR> to accept selected completion item or notify coc.nvim to format" <C-g>u breaks current undo, please make your own choiceinoremap <silent><expr> <CR> coc#pum#visible() ? coc#pum#confirm() : "<C-g>u<CR><c-r>=coc#on_enter()<CR>"function! CheckBackspace() abort let col = col('.') - 1 return !col || getline('.')[col - 1] =~# 's'endfunction" Use <c-space> to trigger completionif has('nvim') inoremap <silent><expr> <c-space> coc#refresh()else inoremap <silent><expr> <c-@> coc#refresh()endif" Use `[g` and `]g` to navigate diagnostics" Use `:CocDiagnostics` to get all diagnostics of current buffer in location listnmap <silent> [g <Plug>(coc-diagnostic-prev)nmap <silent> ]g <Plug>(coc-diagnostic-next)" GoTo code navigationnmap <silent> gd <Plug>(coc-definition)nmap <silent> gy <Plug>(coc-type-definition)nmap <silent> gi <Plug>(coc-implementation)nmap <silent> gr <Plug>(coc-references)" Use K to show documentation in preview windownnoremap <silent> K :call ShowDocumentation()<CR>function! ShowDocumentation() if CocAction('hasProvider', 'hover')call CocActionAsync('doHover') elsecall feedkeys('K', 'in') endifendfunction" Highlight the symbol and its references when holding the cursorautocmd CursorHold * silent call CocActionAsync('highlight')" Symbol renamingnmap <leader>rn <Plug>(coc-rename)" Formatting selected codexmap <leader>f <Plug>(coc-format-selected)nmap <leader>f <Plug>(coc-format-selected)augroup mygroup autocmd! " Setup formatexpr specified filetype(s) autocmd FileType typescript,json setl formatexpr=CocAction('formatSelected') " Update signature help on jump placeholder autocmd User CocJumpPlaceholder call CocActionAsync('showSignatureHelp')augroup end" Applying code actions to the selected code block" Example: `<leader>aap` for current paragraphxmap <leader>a <Plug>(coc-codeaction-selected)nmap <leader>a <Plug>(coc-codeaction-selected)" Remap keys for applying code actions at the cursor positionnmap <leader>ac <Plug>(coc-codeaction-cursor)" Remap keys for apply code actions affect whole buffernmap <leader>as <Plug>(coc-codeaction-source)" Apply the most preferred quickfix action to fix diagnostic on the current linenmap <leader>qf <Plug>(coc-fix-current)" Remap keys for applying refactor code actionsnmap <silent> <leader>re <Plug>(coc-codeaction-refactor)xmap <silent> <leader>r <Plug>(coc-codeaction-refactor-selected)nmap <silent> <leader>r <Plug>(coc-codeaction-refactor-selected)" Run the Code Lens action on the current linenmap <leader>cl <Plug>(coc-codelens-action)" Map function and class text objects" NOTE: Requires 'textDocument.documentSymbol' support from the language serverxmap if <Plug>(coc-funcobj-i)omap if <Plug>(coc-funcobj-i)xmap af <Plug>(coc-funcobj-a)omap af <Plug>(coc-funcobj-a)xmap ic <Plug>(coc-classobj-i)omap ic <Plug>(coc-classobj-i)xmap ac <Plug>(coc-classobj-a)omap ac <Plug>(coc-classobj-a)" Remap <C-f> and <C-b> to scroll float windows/popupsif has('nvim-0.4.0') || has('patch-8.2.0750') nnoremap <silent><nowait><expr> <C-f> coc#float#has_scroll() ? coc#float#scroll(1) : "<C-f>" nnoremap <silent><nowait><expr> <C-b> coc#float#has_scroll() ? coc#float#scroll(0) : "<C-b>" inoremap <silent><nowait><expr> <C-f> coc#float#has_scroll() ? "<c-r>=coc#float#scroll(1)<cr>" : "<Right>" inoremap <silent><nowait><expr> <C-b> coc#float#has_scroll() ? "<c-r>=coc#float#scroll(0)<cr>" : "<Left>" vnoremap <silent><nowait><expr> <C-f> coc#float#has_scroll() ? coc#float#scroll(1) : "<C-f>" vnoremap <silent><nowait><expr> <C-b> coc#float#has_scroll() ? coc#float#scroll(0) : "<C-b>"endif" Use CTRL-S for selections ranges" Requires 'textDocument/selectionRange' support of language servernmap <silent> <C-s> <Plug>(coc-range-select)xmap <silent> <C-s> <Plug>(coc-range-select)" Add `:Format` command to format current buffercommand! -nargs=0 Format :call CocActionAsync('format')" Add `:Fold` command to fold current buffercommand! -nargs=? Fold :call CocAction('fold', <f-args>)" Add `:OR` command for organize imports of the current buffercommand! -nargs=0 OR :call CocActionAsync('runCommand', 'editor.action.organizeImport')" Add (Neo)Vim's native statusline support" NOTE: Please see `:h coc-status` for integrations with external plugins that" provide custom statusline: lightline.vim, vim-airlineset statusline^=%{coc#status()}%{get(b:,'coc_current_function','')}" Mappings for CoCList" Show all diagnosticsnnoremap <silent><nowait> <space>a :<C-u>CocList diagnostics<cr>" Manage extensionsnnoremap <silent><nowait> <space>e :<C-u>CocList extensions<cr>" Show commandsnnoremap <silent><nowait> <space>c :<C-u>CocList commands<cr>" Find symbol of current documentnnoremap <silent><nowait> <space>o :<C-u>CocList outline<cr>" Search workspace symbolsnnoremap <silent><nowait> <space>s :<C-u>CocList -I symbols<cr>" Do default action for next itemnnoremap <silent><nowait> <space>j :<C-u>CocNext<CR>" Do default action for previous itemnnoremap <silent><nowait> <space>k :<C-u>CocPrev<CR>" Resume latest coc listnnoremap <silent><nowait> <space>p :<C-u>CocListResume<CR>
NOTE: This only works in Neovim 0.7.0dev+.
-- https://raw.githubusercontent.com/neoclide/coc.nvim/master/doc/coc-example-config.lua-- Some servers have issues with backup files, see #649vim.opt.backup = falsevim.opt.writebackup = false-- Having longer updatetime (default is 4000 ms = 4s) leads to noticeable-- delays and poor user experiencevim.opt.updatetime = 300-- Always show the signcolumn, otherwise it would shift the text each time-- diagnostics appeared/became resolvedvim.opt.signcolumn = "yes"local keyset = vim.keymap.set-- Autocompletefunction _G.check_back_space()local col = vim.fn.col('.') - 1return col == 0 or vim.fn.getline('.'):sub(col, col):match('%s') ~= nilend-- Use Tab for trigger completion with characters ahead and navigate-- NOTE: There's always a completion item selected by default, you may want to enable-- no select by setting `"suggest.noselect": true` in your configuration file-- NOTE: Use command ':verbose imap <tab>' to make sure Tab is not mapped by-- other plugins before putting this into your configlocal opts = {silent = true, noremap = true, expr = true, replace_keycodes = false}keyset("i", "<TAB>", 'coc#pum#visible() ? coc#pum#next(1) : v:lua.check_back_space() ? "<TAB>" : coc#refresh()', opts)keyset("i", "<S-TAB>", [[coc#pum#visible() ? coc#pum#prev(1) : "<C-h>"]], opts)-- Make <CR> to accept selected completion item or notify coc.nvim to format-- <C-g>u breaks current undo, please make your own choicekeyset("i", "<cr>", [[coc#pum#visible() ? coc#pum#confirm() : "<C-g>u<CR><c-r>=coc#on_enter()<CR>"]], opts)-- Use <c-j> to trigger snippetskeyset("i", "<c-j>", "<Plug>(coc-snippets-expand-jump)")-- Use <c-space> to trigger completionkeyset("i", "<c-space>", "coc#refresh()", {silent = true, expr = true})-- Use `[g` and `]g` to navigate diagnostics-- Use `:CocDiagnostics` to get all diagnostics of current buffer in location listkeyset("n", "[g", "<Plug>(coc-diagnostic-prev)", {silent = true})keyset("n", "]g", "<Plug>(coc-diagnostic-next)", {silent = true})-- GoTo code navigationkeyset("n", "gd", "<Plug>(coc-definition)", {silent = true})keyset("n", "gy", "<Plug>(coc-type-definition)", {silent = true})keyset("n", "gi", "<Plug>(coc-implementation)", {silent = true})keyset("n", "gr", "<Plug>(coc-references)", {silent = true})-- Use K to show documentation in preview windowfunction _G.show_docs()local cw = vim.fn.expand('<cword>')if vim.fn.index({'vim', 'help'}, vim.bo.filetype) >= 0 thenvim.api.nvim_command('h ' .. cw)elseif vim.api.nvim_eval('coc#rpc#ready()') thenvim.fn.CocActionAsync('doHover')elsevim.api.nvim_command('!' .. vim.o.keywordprg .. ' ' .. cw)endendkeyset("n", "K", '<CMD>lua _G.show_docs()<CR>', {silent = true})-- Highlight the symbol and its references on a CursorHold event(cursor is idle)vim.api.nvim_create_augroup("CocGroup", {})vim.api.nvim_create_autocmd("CursorHold", {group = "CocGroup",command = "silent call CocActionAsync('highlight')",desc = "Highlight symbol under cursor on CursorHold"})-- Symbol renamingkeyset("n", "<leader>rn", "<Plug>(coc-rename)", {silent = true})-- Formatting selected codekeyset("x", "<leader>f", "<Plug>(coc-format-selected)", {silent = true})keyset("n", "<leader>f", "<Plug>(coc-format-selected)", {silent = true})-- Setup formatexpr specified filetype(s)vim.api.nvim_create_autocmd("FileType", {group = "CocGroup",pattern = "typescript,json",command = "setl formatexpr=CocAction('formatSelected')",desc = "Setup formatexpr specified filetype(s)."})-- Update signature help on jump placeholdervim.api.nvim_create_autocmd("User", {group = "CocGroup",pattern = "CocJumpPlaceholder",command = "call CocActionAsync('showSignatureHelp')",desc = "Update signature help on jump placeholder"})-- Apply codeAction to the selected region-- Example: `<leader>aap` for current paragraphlocal opts = {silent = true, nowait = true}keyset("x", "<leader>a", "<Plug>(coc-codeaction-selected)", opts)keyset("n", "<leader>a", "<Plug>(coc-codeaction-selected)", opts)-- Remap keys for apply code actions at the cursor position.keyset("n", "<leader>ac", "<Plug>(coc-codeaction-cursor)", opts)-- Remap keys for apply source code actions for current file.keyset("