Appearance
Vim Setup
Published: February 25, 2026 · Last edited: February 25, 2026
A practical Vim configuration that gives you visual feedback, prevents common mistakes, and gets out of your way.
Core Philosophy
- Always know your state — mode, file status, and cursor position always visible
- Sensible defaults — every setting has a clear reason; no cargo-culting
- Safety nets — persistent undo, central backups, no silent overwrites
- Muscle memory over mnemonics — keymaps grouped by how you actually work
- Minimal plugins, maximum value — only add a plugin if it removes daily friction
1. Installation
bash
# macOS
brew install vim
# Ubuntu/Debian
sudo apt install vim
# Check version (Vim 8+ recommended for async support)
vim --version | head -1If you're on macOS, the system Vim is old. Use the Homebrew version.
2. Core .vimrc
Create ~/.vimrc:
vim
" ============================================================
" GENERAL
" ============================================================
set nocompatible " Be Vim, not Vi
filetype plugin indent on " Enable filetype detection
syntax on " Syntax highlighting
set encoding=utf-8 " Always UTF-8
set history=10000 " Long undo history across sessions
set autoread " Reload file if changed outside Vim
set hidden " Allow switching buffers without saving
" ============================================================
" VISUAL FEEDBACK
" ============================================================
set number " Show absolute line number on current line
set relativenumber " Show relative line numbers for easy jumps
set cursorline " Highlight the current line
set showcmd " Show partial command in bottom bar
set showmatch " Highlight matching bracket
set laststatus=2 " Always show status line
set ruler " Show line/column in status line
set wildmenu " Visual autocomplete for command menu
set scrolloff=8 " Keep 8 lines visible above/below cursor
set sidescrolloff=5 " Keep 5 columns visible left/right
" ============================================================
" STATUS LINE
" ============================================================
set statusline= " Reset
set statusline+=%#PmenuSel# " Colour: active
set statusline+=\ %f\ " Filename (relative)
set statusline+=%m " Modified flag [+]
set statusline+=%r " Readonly flag [RO]
set statusline+=%= " Switch to right side
set statusline+=%y\ " Filetype [python]
set statusline+=L%l/%L\ " Current line / total lines
set statusline+=C%c\ " Column number
" ============================================================
" SEARCH
" ============================================================
set incsearch " Search as you type
set hlsearch " Highlight all matches
set ignorecase " Case-insensitive search...
set smartcase " ...unless you type a capital letter
" Clear search highlight with Enter
nnoremap <CR> :nohlsearch<CR><CR>
" ============================================================
" INDENTATION
" ============================================================
set expandtab " Use spaces, not tabs
set tabstop=4 " Display tabs as 4 spaces
set shiftwidth=4 " Indent/dedent by 4 spaces
set softtabstop=4 " Backspace deletes 4 spaces at a time
set autoindent " Maintain indent from previous line
set smartindent " Indent after { and before }
" Two-space indent for common web/config files
autocmd FileType yaml,json,html,css,javascript,typescript setlocal
\ tabstop=2 shiftwidth=2 softtabstop=2
" ============================================================
" SAFETY NETS
" ============================================================
" Central backup and undo directories — keep project dirs clean
silent !mkdir -p ~/.vim/backup ~/.vim/swap ~/.vim/undo
set backupdir=~/.vim/backup//
set directory=~/.vim/swap//
set undodir=~/.vim/undo//
set undofile " Persist undo history across sessions
set undolevels=10000 " Deep undo
set noswapfile " Skip swap files (undo file is enough)
set writebackup " Write backup before saving, remove after
" ============================================================
" BEHAVIOUR
" ============================================================
set backspace=indent,eol,start " Backspace works as expected in insert mode
set clipboard=unnamed " Use system clipboard (macOS / X11 with +clipboard)
set splitright " New vertical splits open to the right
set splitbelow " New horizontal splits open below
set nowrap " Don't wrap long lines
set list " Show invisible characters
set listchars=tab:›\ ,trail:·,nbsp:· " Mark tabs, trailing spaces
" ============================================================
" KEY MAPPINGS
" ============================================================
" Leader key — space is easiest to reach
let mapleader = " "
" Fast save and quit
nnoremap <leader>w :w<CR>
nnoremap <leader>q :q<CR>
nnoremap <leader>Q :q!<CR>
" Save as sudo if you forgot to open with sudo
cnoremap w!! execute 'silent! write !sudo tee % >/dev/null' <bar> edit!
" Navigate splits with Ctrl+hjkl (no need for Ctrl+W first)
nnoremap <C-h> <C-w>h
nnoremap <C-j> <C-w>j
nnoremap <C-k> <C-w>k
nnoremap <C-l> <C-w>l
" Move lines up and down in visual mode with J/K
vnoremap J :m '>+1<CR>gv=gv
vnoremap K :m '<-2<CR>gv=gv
" Keep cursor centred when jumping
nnoremap <C-d> <C-d>zz
nnoremap <C-u> <C-u>zz
nnoremap n nzzzv
nnoremap N Nzzzv
" Paste without replacing the register in visual mode
vnoremap <leader>p "_dP
" Yank to end of line (consistent with D and C)
nnoremap Y y$
" Indent without losing selection
vnoremap < <gv
vnoremap > >gv
" Next/previous buffer
nnoremap <leader>] :bnext<CR>
nnoremap <leader>[ :bprev<CR>
" Toggle line numbers between absolute and relative
nnoremap <leader>n :set relativenumber!<CR>
" Toggle word wrap
nnoremap <leader>W :set wrap!<CR>
" Open netrw file browser in the current window
nnoremap <leader>e :Explore<CR>3. Plugin Setup
Use vim-plug — one file, no dependencies.
Install vim-plug
bash
curl -fLo ~/.vim/autoload/plug.vim --create-dirs \
https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vimAdd to ~/.vimrc (before other config)
vim
" ============================================================
" PLUGINS
" ============================================================
call plug#begin('~/.vim/plugged')
" Fuzzy file/buffer/history search (integrates with fzf from CLI setup)
Plug 'junegunn/fzf', { 'do': { -> fzf#install() } }
Plug 'junegunn/fzf.vim'
" gc to comment/uncomment lines and motions
Plug 'tpope/vim-commentary'
" cs, ds, ys to change/delete/add surrounding brackets/quotes
Plug 'tpope/vim-surround'
" Shows git diff in the gutter (+, -, ~)
Plug 'airblade/vim-gitgutter'
" Color scheme
Plug 'morhetz/gruvbox'
call plug#end()Install plugins: open Vim and run :PlugInstall
Plugin Key Mappings
Add after the call plug#end() line:
vim
" --- FZF ---
nnoremap <leader>f :Files<CR> " Fuzzy-find files
nnoremap <leader>b :Buffers<CR> " Fuzzy-find open buffers
nnoremap <leader>r :Rg<CR> " Ripgrep across project
nnoremap <leader>h :History<CR> " Recently opened files
" --- Gruvbox ---
set background=dark
colorscheme gruvbox4. Netrw File Browser
Vim's built-in file browser is good enough for most tasks. No plugin needed.
vim
" Add to ~/.vimrc
let g:netrw_banner = 0 " Hide the help banner
let g:netrw_liststyle = 3 " Tree view
let g:netrw_winsize = 25 " 25% width when splitUseful commands inside netrw:
| Key | Action |
|---|---|
<Enter> | Open file |
v | Open in vertical split |
o | Open in horizontal split |
t | Open in new tab |
d | Create directory |
% | Create new file |
D | Delete file/directory |
R | Rename file |
- | Go up one directory |
5. Complete .vimrc
The sections above are meant to be read in order, but here is everything in one block ready to paste:
vim
" ============================================================
" PLUGINS
" ============================================================
call plug#begin('~/.vim/plugged')
Plug 'junegunn/fzf', { 'do': { -> fzf#install() } }
Plug 'junegunn/fzf.vim'
Plug 'tpope/vim-commentary'
Plug 'tpope/vim-surround'
Plug 'airblade/vim-gitgutter'
Plug 'morhetz/gruvbox'
call plug#end()
" ============================================================
" GENERAL
" ============================================================
set nocompatible
filetype plugin indent on
syntax on
set encoding=utf-8
set history=10000
set autoread
set hidden
" ============================================================
" VISUAL FEEDBACK
" ============================================================
set number
set relativenumber
set cursorline
set showcmd
set showmatch
set laststatus=2
set ruler
set wildmenu
set scrolloff=8
set sidescrolloff=5
" ============================================================
" STATUS LINE
" ============================================================
set statusline=
set statusline+=%#PmenuSel#
set statusline+=\ %f\
set statusline+=%m
set statusline+=%r
set statusline+=%=
set statusline+=%y\
set statusline+=L%l/%L\
set statusline+=C%c\
" ============================================================
" SEARCH
" ============================================================
set incsearch
set hlsearch
set ignorecase
set smartcase
nnoremap <CR> :nohlsearch<CR><CR>
" ============================================================
" INDENTATION
" ============================================================
set expandtab
set tabstop=4
set shiftwidth=4
set softtabstop=4
set autoindent
set smartindent
autocmd FileType yaml,json,html,css,javascript,typescript setlocal
\ tabstop=2 shiftwidth=2 softtabstop=2
" ============================================================
" SAFETY NETS
" ============================================================
silent !mkdir -p ~/.vim/backup ~/.vim/swap ~/.vim/undo
set backupdir=~/.vim/backup//
set directory=~/.vim/swap//
set undodir=~/.vim/undo//
set undofile
set undolevels=10000
set noswapfile
set writebackup
" ============================================================
" BEHAVIOUR
" ============================================================
set backspace=indent,eol,start
set clipboard=unnamed
set splitright
set splitbelow
set nowrap
set list
set listchars=tab:›\ ,trail:·,nbsp:·
" ============================================================
" KEY MAPPINGS
" ============================================================
let mapleader = " "
nnoremap <leader>w :w<CR>
nnoremap <leader>q :q<CR>
nnoremap <leader>Q :q!<CR>
cnoremap w!! execute 'silent! write !sudo tee % >/dev/null' <bar> edit!
nnoremap <C-h> <C-w>h
nnoremap <C-j> <C-w>j
nnoremap <C-k> <C-w>k
nnoremap <C-l> <C-w>l
vnoremap J :m '>+1<CR>gv=gv
vnoremap K :m '<-2<CR>gv=gv
nnoremap <C-d> <C-d>zz
nnoremap <C-u> <C-u>zz
nnoremap n nzzzv
nnoremap N Nzzzv
vnoremap <leader>p "_dP
nnoremap Y y$
vnoremap < <gv
vnoremap > >gv
nnoremap <leader>] :bnext<CR>
nnoremap <leader>[ :bprev<CR>
nnoremap <leader>n :set relativenumber!<CR>
nnoremap <leader>W :set wrap!<CR>
nnoremap <leader>e :Explore<CR>
" ============================================================
" PLUGINS CONFIG
" ============================================================
" FZF
nnoremap <leader>f :Files<CR>
nnoremap <leader>b :Buffers<CR>
nnoremap <leader>r :Rg<CR>
nnoremap <leader>h :History<CR>
" Netrw
let g:netrw_banner = 0
let g:netrw_liststyle = 3
let g:netrw_winsize = 25
" Gruvbox
set background=dark
colorscheme gruvbox6. Daily Workflow Tips
- Open a project:
vim .opens netrw; press<leader>einside Vim to return to it - Find a file fast:
<leader>ffuzzy-finds files,<leader>rsearches file contents - Jump around:
<leader>hshows recently opened files - Work in splits:
Ctrl+W vfor vertical,Ctrl+W sfor horizontal; navigate withCtrl+hjkl - Undo anything:
:earlier 5mtakes you back 5 minutes; undo survives closing Vim - Comment out quickly:
gcctoggles a line,gc5jcomments 5 lines down
7. Customization
Adjust based on your habits:
- Tab width: Change
shiftwidthandtabstopfor your preferred indentation - Color scheme: Try
:colorscheme+ Tab to cycle through installed themes - Wrap long lines:
:set wrap linebreakfor prose; unwrap for code - Clipboard: If
set clipboard=unnameddoesn't work on Linux, tryset clipboard=unnamedplus - Language servers: Add vim-lsp if you want IDE-style completion
Remember: add to this config only when you hit friction, not before.
Related
- CLI Setup — The shell environment your editor lives inside
- Vim Quick Reference — Scannable cheatsheet for Vim commands