Vim Cheatsheet
Configuration and Mappings
Use this Vim reference while you build software engineering projects, review code, or refresh the syntax you reach for most.
Where Config Lives
| Editor | File |
|---|---|
| Vim | ~/.vimrc or ~/.vim/vimrc |
| Vim (plugins, etc.) | ~/.vim/ |
| Neovim | ~/.config/nvim/init.lua or init.vim |
| Neovim (data) | ~/.local/share/nvim/ |
:echo $MYVIMRC " path to the config Vim actually loaded
:e $MYVIMRC " edit it
:source $MYVIMRC " reload it without restarting
:scriptnames " every file Vim has sourced, in order
:version " build features and config pathsSetting Options
:set number " turn a boolean option on :set nonumber " turn it off :set number! " toggle it :set number? " show the current value :set tabstop=4 " set a value :set tabstop& " reset to the default :setlocal number " only for this buffer or window :set all " every option :verbose set number? " which file last set this option
Options Worth Knowing
| Option | Does |
|---|---|
number / relativenumber | Absolute / relative line numbers |
expandtab | Insert spaces instead of tab characters |
tabstop | How wide a tab character renders |
shiftwidth | How much >> and autoindent move |
softtabstop | How many spaces Tab inserts |
autoindent / smartindent | Carry indent to the next line |
wrap / linebreak | Soft wrap, breaking at word boundaries |
textwidth | Hard wrap column for gq |
colorcolumn=80 | Draw a ruler at column 80 |
ignorecase / smartcase | Case handling in search |
hlsearch / incsearch | Highlight and live-preview search |
scrolloff=8 | Keep 8 lines of context above and below |
sidescrolloff | The same, horizontally |
hidden | Allow unsaved buffers in the background |
undofile | Persist undo history across sessions |
swapfile | Write a .swp recovery file |
clipboard=unnamedplus | Make y and p use the system clipboard |
mouse=a | Enable the mouse |
termguicolors | 24-bit color in the terminal |
signcolumn=yes | Always reserve the sign gutter |
updatetime=300 | Idle delay before CursorHold fires |
wildmenu / wildmode | Command-line completion menu |
list / listchars | Show tabs, trailing spaces, and so on |
spell / spelllang | Spell checking |
foldmethod | manual, indent, syntax, expr, marker |
laststatus=2 | Always show the status line |
showcmd / ruler | Partial command and cursor position |
backspace=indent,eol,start | Make Backspace behave normally in Insert |
splitright / splitbelow | Where new splits go |
A Reasonable Starting vimrc
set nocompatible syntax on filetype plugin indent on " Look set number relativenumber set cursorline set scrolloff=8 set signcolumn=yes set termguicolors set laststatus=2 set showcmd set colorcolumn=80 " Indentation set expandtab set tabstop=2 shiftwidth=2 softtabstop=2 set autoindent smartindent " Search set ignorecase smartcase set hlsearch incsearch " Files and history set hidden set undofile set undodir=~/.vim/undo set noswapfile set nobackup set autoread " Behaviour set backspace=indent,eol,start set splitright splitbelow set wildmenu set wildmode=longest:full,full set mouse=a set clipboard=unnamedplus " Leader let mapleader = " "
Create the undo directory once with mkdir -p ~/.vim/undo, or Vim will complain on every write.
Mappings
nnoremap <key> <action> " Normal mode, non-recursive inoremap … " Insert mode vnoremap … " Visual and Select xnoremap … " Visual only cnoremap … " Command line tnoremap … " Terminal mode map / imap / vmap " recursive versions: avoid these noremap " Normal, Visual, Select, Operator-pending <buffer> " scope the mapping to this buffer <silent> " do not echo the command <expr> " evaluate the right side as an expression
Always prefer the nore ("non-recursive") forms. A recursive map can loop or pick up a plugin's remapping and behave differently than you wrote it.
| Notation | Key |
|---|---|
<CR> | Enter |
<Esc> | Escape |
<Tab> / <S-Tab> | Tab / Shift-Tab |
<Space> | Space |
<BS> | Backspace |
<leader> | Whatever mapleader is set to |
<localleader> | maplocalleader, for filetype maps |
<C-x> | Ctrl-x |
<S-x> / <M-x> / <A-x> | Shift / Meta / Alt |
<F5> | Function key |
<Up> <Down> <Left> <Right> | Arrows |
<nop> | Do nothing (disable a key) |
let mapleader = " " nnoremap <leader>w :w<CR> nnoremap <leader>q :q<CR> nnoremap <leader>h :noh<CR> nnoremap <leader>e :Explore<CR> " Window navigation without the Ctrl-w prefix nnoremap <C-h> <C-w>h nnoremap <C-j> <C-w>j nnoremap <C-k> <C-w>k nnoremap <C-l> <C-w>l " Keep the cursor centered while searching nnoremap n nzzzv nnoremap N Nzzzv " Move the selected lines up and down vnoremap J :m '>+1<CR>gv=gv vnoremap K :m '<-2<CR>gv=gv " Paste over a selection without losing the register xnoremap <leader>p "_dP " System clipboard nnoremap <leader>y "+y vnoremap <leader>y "+y :map <leader> " list every mapping under leader :verbose nmap <C-h> " find out which file defined a mapping
Abbreviations
iabbrev teh the iabbrev @@ me@example.com iabbrev ssig -- <CR>Pablo :abclear " clear all abbreviations
Autocommands
Autocommands run a command when an event fires. Always wrap them in an augroup with autocmd! so re-sourcing your config does not register them twice.
augroup MyConfig autocmd! autocmd BufWritePre * %s/\s\+$//e " strip trailing whitespace autocmd FileType python setlocal shiftwidth=4 tabstop=4 autocmd FileType markdown setlocal wrap linebreak spell autocmd BufReadPost * if line("'\"") > 1 && line("'\"") <= line("$") \ | execute "normal! g`\"" | endif " restore cursor position autocmd TextYankPost * silent! lua vim.highlight.on_yank() augroup END
| Event | Fires |
|---|---|
BufRead / BufReadPost | After reading a file into a buffer |
BufWritePre / BufWritePost | Before / after writing |
BufEnter / BufLeave | Entering / leaving a buffer |
BufNewFile | Opening a name that does not exist yet |
FileType | The filetype has been detected |
InsertEnter / InsertLeave | Insert mode boundaries |
TextChanged | The buffer changed in Normal mode |
CursorHold | The cursor sat still for updatetime |
VimEnter / VimLeave | Startup / shutdown |
WinEnter / WinLeave | Window focus |
TermOpen | A terminal buffer opened |
Custom Commands and Functions
command! Reload source $MYVIMRC command! -nargs=1 Grep execute 'vimgrep /<args>/ **/*' command! -range Sortu <line1>,<line2>sort u function! ToggleNumber() if &number set nonumber norelativenumber else set number relativenumber endif endfunction nnoremap <leader>n :call ToggleNumber()<CR>
User commands must start with a capital letter, and the ! after command means "redefine if it already exists", which you want when re-sourcing.