DEV Community

Cover image for Minimal (neo)vim with VSCode like setup
Cason Adams
Cason Adams

Posted on

Minimal (neo)vim with VSCode like setup

I wanted to share a quick little setup to get up and running quickly with vim as an IDE. I don't really like vim and IDE in the same sentence, but I do have to admit that having an IDE that runs in the terminal and loads fast is pretty sweet.
header image


├── _lsp.vim
├── _options.vim
├── _plugins.vim
├── _theme.vim
Enter fullscreen mode Exit fullscreen mode



create ~/.vim directory

First we need a place to store a few files. I am going to put them in ${HOME}/.vim/ so I will make that directory.

_theme.vim (optional)

Lets create a file to store theme settings. I am going to put it in ${HOME}/.vim/_theme.vim.

syntax enable
" set t_Co=16 " uncomment to force ANSI 16 colors

if has('gui_running')
    set background=light
    set background=dark

colorscheme gruvbox8

Enter fullscreen mode Exit fullscreen mode

_options.vim (optional)

Lets create a file to store vim options. I am going to put it in ${HOME}/.vim/_options.vim. I tried to document the options below. These are optional, I borrowed some of this information from LunarVims default settings. Most options can be prefixed with no to disable the behavior.

let mapleader="\ " " set leader key to space

set clipboard="" " don't use clipboard
set cmdheight=1 " more space in the neovim command line for
set colorcolumn="99999" " fixes indentline for now
set completeopt=menuone,noselect
set conceallevel=0 " so that `` is visible in markdown files
set cursorline " highlight the current line
set expandtab " convert tabs to spaces
set fileencoding="utf-8" " the encoding written to a file
set foldexpr="" " set to "nvim_treesitter#foldexpr()" for treesitter based folding
set hidden " required to keep multiple buffers and open multiple buffers
set hlsearch " highlight all matches on previous search pattern
set ignorecase " ignore case in search patterns
set laststatus=2 " hide statusline
set list " show hidden chars
set listchars=tab:│\ ,trail:·,nbsp:+
set nobackup " creates a backup file
set norelativenumber " set relative numbered lines
set nospell " disable spell checking
set noswapfile " creates a swapfile
set nowritebackup " if a file is being edited by another program (or was written to file while editing with another program) it is not allowed to be edited
set number " set numbered lines
set numberwidth=1 " set number column width to 2 {default 4}
set pumheight=10 " pop up menu height
set scrolloff=4 " is one of my fav
set shiftwidth=2 " the number of spaces inserted for each indentation
set showmode " shows " INSERT " in cmdline
set showtabline=2 " always show tabs
set sidescrolloff=4
set signcolumn="yes" " always show the sign column otherwise it would shift the text each time
set smartcase " smart case
set smartindent " make indenting smarter again
set spelllang="en" " language for spell checking
set splitbelow " force all horizontal splits to go below current window
set splitright " force all vertical splits to go to the right of current window
set tabstop=2 " insert 2 spaces for a tab
set timeoutlen=500 " timeout length
set title " set the title of window to the value of the titlestring
set titlestring="%<%F - vim" " what the title of the window will be set to
set undodir="/undo" .. "/undo"
set undofile " enable persistent undo
set updatetime=300 " faster completion
set wrap " display lines as one long line
Enter fullscreen mode Exit fullscreen mode


Lets create a file to manage vim plugins. I am going to put it in ${HOME}/.vim/_plugins.vim. For this tutorial we are using vim-plug.

  • Note fancy things are happening in the first 2 blocks of code that will auto install vim-plug and auto install missing plugins. (curl is required for this magic to happen)

  • Note 3 plugins are being installed here:

    1. coc.nvim (LSP IDE magic)
    2. vim-gruvbox8 (colorscheme)
    3. vim-commentary (nice shortcuts for code commenting)

" Install vim-plug if not found
if empty(glob('~/.vim/autoload/plug.vim'))
   silent !curl -fLo ~/.vim/autoload/plug.vim --create-dirs

" Run PlugInstall if there are missing plugins
autocmd VimEnter * if len(filter(values(g:plugs), '!isdirectory(v:val.dir)'))
 \| PlugInstall --sync | source $MYVIMRC
 \| endif

" Plugins
call plug#begin()
  Plug 'neoclide/coc.nvim', {'branch': 'release'}
  Plug 'lifepillar/vim-gruvbox8'
  Plug 'tpope/vim-commentary'
call plug#end()
Enter fullscreen mode Exit fullscreen mode

Most used shortcut key for vim-commentary

Shortcut Description
gcc comment / uncomment


Lets create a file to manage vim lsp servers. I am going to put it in ${HOME}/.vim/_lsp.vim. This is where we will configure coc.nvim.

From the example. The following has been slightly modified moving some options to _options.vim, and configuring the statusline to be as close to vanilla vim with some lsp information.

" 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'

" Use <c-space> to trigger completion.
if has('nvim')
  inoremap <silent><expr> <c-space> coc#refresh()
  inoremap <silent><expr> <c-@> coc#refresh()

" 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 `[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)

" GoTo code navigation.
nmap <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 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')
    execute '!' . &keywordprg . " " . expand('<cword>')

" Highlight the symbol and its references when holding the cursor.
" autocmd CursorHold * silent call CocActionAsync('highlight')

" Symbol renaming.
nmap <leader>rn <Plug>(coc-rename)

" Formatting selected code.
xmap <leader>f  <Plug>(coc-format-selected)
nmap <leader>f  <Plug>(coc-format-selected)

augroup mygroup
  " 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 codeAction to the selected region.
" Example: `<leader>aap` for current paragraph
xmap <leader>a  <Plug>(coc-codeaction-selected)
nmap <leader>a  <Plug>(coc-codeaction-selected)

" Remap keys for applying codeAction to the current buffer.
nmap <leader>ac  <Plug>(coc-codeaction)
" Apply AutoFix to problem on the current line.
nmap <leader>qf  <Plug>(coc-fix-current)

" Run the Code Lens action on the current line.
nmap <leader>cl  <Plug>(coc-codelens-action)

" Map function and class text objects
" NOTE: Requires 'textDocument.documentSymbol' support from the language server.
xmap 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> for scroll float windows/popups.
if 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>"

" Use CTRL-S for selections ranges.
" Requires 'textDocument/selectionRange' support of language server.
nmap <silent> <C-s> <Plug>(coc-range-select)
xmap <silent> <C-s> <Plug>(coc-range-select)

" Add `:Format` command to format current buffer.
command! -nargs=0 Format :call CocAction('format')

" Add `:Fold` command to fold current buffer.
command! -nargs=? Fold :call     CocAction('fold', <f-args>)

" Add `:OR` command for organize imports of the current buffer.
command! -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-airline.
set statusline=\ %<%f\ %h%m%r
set statusline+=%=%-10.50{ShowCocStatus()}\ %-.(%l,%c%V%)\ %P

function! ShowCocStatus() 
  return get(g:, 'coc_status', '')

" Mappings for CoCList
" Show all diagnostics.
nnoremap <silent><nowait> <space>a  :<C-u>CocList diagnostics<cr>
" Manage extensions.
nnoremap <silent><nowait> <space>e  :<C-u>CocList extensions<cr>
" Show commands.
nnoremap <silent><nowait> <space>c  :<C-u>CocList commands<cr>
" Find symbol of current document.
nnoremap <silent><nowait> <space>o  :<C-u>CocList outline<cr>
" Search workspace symbols.
nnoremap <silent><nowait> <space>s  :<C-u>CocList -I symbols<cr>
" Do default action for next item.
nnoremap <silent><nowait> <space>j  :<C-u>CocNext<CR>
" Do default action for previous item.
nnoremap <silent><nowait> <space>k  :<C-u>CocPrev<CR>
" Resume latest coc list.
nnoremap <silent><nowait> <space>p  :<C-u>CocListResume<CR>
Enter fullscreen mode Exit fullscreen mode

There is a lot going on in there. This makes it so we get (tab) completion on typing, and setups tons of shortcuts for quickly doing things. Look for nmap for all the settings. Here are a few of the very basics.

Shortcut Description
gd go to def
K show hover
leader rn rename
leader f call format
  • Note some languages require formatters to be installed first. As an example in python the default formatter using coc-pyright server is autopep8. In order to use this formatter pip install autopep8 etc...


Now lets bring it all together. Open ${HOME}/.vimrc (I am not sure where this lives in windows sorry) and add the following.

source ~/.vim/_options.vim
source ~/.vim/_plugins.vim
source ~/.vim/_lsp.vim
source ~/.vim/_theme.vim
Enter fullscreen mode Exit fullscreen mode

Installing servers

Lets try installing a coc.nvim extension. Quick link to some extenstions. For the purpose of this post lets install coc-pyright and try it out with a python file.

Install extenstion

Lets create a simple python file. vim

  • Note line 4 has an error, and once we are setup with coc.nvim we should see it.
#!/usr/bin/env python

def echo(msg):
    print msg

if __name__ == "__main__":
    echo("Hello World!")
Enter fullscreen mode Exit fullscreen mode
  • Install coc-pyright :CocInstall coc-pyright
  • Save the file :wq

Next time the file is open it is expected to see an error indicated in line 4. Move the cursor to msg and the following should pop up.

example screen shot


If everything is working as planned you have successfully setup coc.nvim and are now off to the races to further configure things. Happy hacking.

Top comments (0)