My vim setup
Everybody does it differently.

I thought it would be fun to talk about my vim configuration. Everyone does it differently, and I wanted to toss my hat into the ring.
I don’t claim to have the best setup, but it works great for JavaScript (React, node) and TypeScript development.
I keep my .vimrc and other related files up to date on GitHub.
This has been a helpful exercise in evaluating what my configuration options do, and which ones I can get rid of. After a while these things tend to accumulate a lot of cruft.
I pledge to keep this page up to date as I add (or remove) changes to it.
nvim
I use Neovim (nvim) instead of vim because it has support for fancier plugins, and it handles asynchronous actions better than vim, in my experience.
Plus it has “neo” in the name, and that’s plain cool.
Basics
This section captures what I would consider to be the basics of vim: clipboard behaviour, backspace behaviour, spellchecking, all that jazz.
set nocompatible
This tells vim to use vim settings rather than vi. To be honest I don’t full understand what this does, but see it enough in other .vimrc I decided to include it.
set number
set relativenumber
This enables line numbers. You’re gonna need those if you’re developin’. relativenumber shows relative line numbers from the currently highlighted line.
set title
Sets the terminal window’s title to be the file currently being edited (I think).
set scrolloff=2
This changes the scroll offset, or in other words when vim decides to start scrolling. In my case, once I am on the 2nd to last line of my screen and I want to scroll down (or up), it will scroll the screen upwards and move to the next line.
set backspace=indent,eol,start
This makes the BACKSPACE key behave in a sane way while using vim. I don’t know why this behaviour isn’t default — probably some holdover from the “old days”.
set nowrap
No linewrapping allowed. I switch around this setting from time to time.
set noerrorbells
set belloff=all
I don’t see how playing a sound when there is an error is helpful — like when I try to scroll past the end or beginning of the file. Turn that off.
set hlsearch
This will highlight all search matches on any open buffers, like when using / to search for text.
set incsearch
As I start typing when using /, it will highlight things as they are matched (before pressing ENTER).
set signcolumn=yes
This enables the sign column in vim, which can be used by plugins to highlight lines with errors, warnings, and so on.
set hidden
vim by default will throw away buffers when you switch away from them. This stops that behaviour. A reasonable expectation with any modern text editor.
set nobackup
set nowritebackup
vim likes to create backup files (adding ~ to the extension) and I don’t like them. I use version control software and I’m content with that.
set cmdheight=2
This gives me more breathing room in the command window.
set shortmess+=c
Shortens messages from vim.
set path=$PWD/**
When running searches in vim, set the project directory to where I currently am.
set showmode
Shows which mode vim is currently in on the command window. I’m forgetful.
set ignorecase
set smartcase
Makes search patterns case-insensitive. Except when the search pattern contains uppercase characters (smartcase).
set clipboard=unnamed
Removes vim’s separate clipboard, and “shares” it between vim and the outside world (your computer).
set cursorline
Highlights the line the cursor is currently on. Makes it easier for me to find the cursor.
Tabs and spaces
set tabstop=2
set shiftwidth=2
set softtabstop=2
set expandtab
set shiftround
set smarttab
set smartindent
set autoindent
set copyindent
I don’t care if we use tabs or spaces anymore, I’ll use what the project at hand wants.
Tab uses spaces, and each tab is 2 spaces.
If I’m at a certain indentation level, then these options ensure I maintain it and it always a multiple of shiftwidth.
Spellchecking
autocmd FileType gitcommit setlocal spell
autocmd FileType markdown,md,mdx setlocal spell
When I am writing a git commit, or inside a Markdown file I want to add spellchecking.
Forcing myself to learn hjkl
noremap <Up> <NOP>
noremap <Down> <NOP>
noremap <Left> <NOP>
noremap <Right> <NOP>
inoremap <Down> <NOP>
inoremap <Left> <NOP>
inoremap <Right> <NOP>
inoremap <Up> <NOP>
hjkl is essential way to move around in vim. You don’t have to move your hands from home row. It’s hard to learn at first, but if you disable the arrow keys, you start to learn pretty quick.
netrw
let g:netrw_banner = 0
This hides the giant help banner when using netrw (:E). I use netrw to move around sometimes, when CTRL + P doesn’t cut it.
Split movement
nnoremap <C-J> <C-W><C-J>
nnoremap <C-K> <C-W><C-K>
nnoremap <C-L> <C-W><C-L>
nnoremap <C-H> <C-W><C-H>
I use splits a lot and this makes it easier to move around between them.
Plugins
call plug#begin('~/.vim/plugged')
I use vim-plug to manage all my plugins.
auto-pairs
Adds pairs of quotes, brackets, etc. If I type ”, it’ll add a closing quote. Works with () and {}.
let g:AutoPairsMultilineClose = 0
This disables the default behaviour of trying to close any pair even if it was on another line. When writing code blocks {}, it would jump to the next closing } if I was inside another code block. It might make sense to someone, but for me it just annoyed me. Thankfully it can be switched off!
vim-surround
Took me a while to get, but once I did I can’t imagine life without it. Wrap words/quotes/code blocks/whatever in more quotes or characters. A mnemonic from my coworker:
(y)olo (s)urround (i)n (w)ord/(“)quote/etc
vim-commentary
I use gc all the time. Comment entire blocks or lines super quick. Easy to remember.
vim-polyglot
Syntax highlighting for various languages. I use JavaScript (and adjacent stuff like JSON) 99% of the time, but nice to have for shell scripts, Ruby, and so on.
fzf
One day I might learn how to use vimgrep, but for now I have fzf. Requires extra binaries. I thought I needed NERDTree to move around, but fzf has got my back.
nnoremap <silent> <c-p> :GFiles --cached --others --exclude-standard<cr>
This makes CTRL + P filter files that are part of the project’s .gitignore by default.
vim-fugitive
I’ve got this installed but don’t use it much. It adds git support right in vim, but I almost always have a second tab open in my terminal explicitly for git operations.
vim-rhubarb
Like the above, it offers a neat feature, but I keep forgetting to use it. It will create a link directly to the line you’re on in vim.
coc.nvim
I bet this one will garner controversy. Getting intelligent autocomplete in vim was never something it was intended to do, but coc in combination with nvim gets us there. For it to function “just so” requires extra configuration, which I’ll highlight below.
let g:coc_global_extensions = [
\ 'coc-tsserver',
\ 'coc-json',
\ ]
This runs these coc plugins all the time. Since I’m always mucking about in JavaScript, this isn’t a big deal. It’s smart enough to know when I’m not in JavaScript and to not complain, which works for me.
if isdirectory('./node_modules') && isdirectory('./node_modules/prettier')
let g:coc_global_extensions += ['coc-prettier']
endif
if isdirectory('./node_modules') && isdirectory('./node_modules/eslint')
let g:coc_global_extensions += ['coc-eslint']
endif
This tells coc to load up eslint and prettier extensions if I’m using them in my project. Super handy to automatically load up prettier only when I need it.
nnoremap <silent> K :call CocAction('doHover')<CR>
Rarely do I need to trigger coc on its own, but this is for the odd time. Nice for when looking up variable types (using TypeScript), or method arguments.
command! -nargs=0 Prettier :CocCommand prettier.formatFile
Shortcut to run prettier using :Prettier. I don’t use this often since I have it configured to run on save.
coc-settings.json
"suggest.noselect": false,
This option pre-selects the first option in the autocomplete list.
"eslint.autoFixOnSave": true,
"eslint.filetypes": ["javascript", "javascriptreact", "typescript", "typescriptreact"],
This runs eslint on save, and ensures that the files in filetypes run eslint.
“coc.preferences.formatOnSaveFiletypes": ["markdown", "mdx", "javascript", "javascriptreact", "typescript", "typescriptreact"],
This runs prettier for me on these filetypes when saving. Somehow this doesn’t interfere with eslint, which is magic to me.
"coc.preferences.jumpCommand": "vsplit"
When using commands like gd (goto definition), it will open in a new :vsplit by default.
Theme
I saved the best for last.
I currently use the Rigel theme.
set statusline=%f%=%m%r%h%w%y[%04l,%04v]
This sets up my status line to show me what I need to know:
- The file I’m editing
- A marker if the file has been modified but not saved
- What language mode I’m in
- What line I’m on
- What column I’m on
highlight Comment cterm=italic gui=italic
My font of choice is Operator Mono, and it has beautiful cursive italics that I want to see. Anything comments in the file (or certain keywords) are converted into italics.