CONFIGURATION
Learning Vim
Chapter 7 — Configuration
Why Configuration Matters
Out of the box, Vim is a capable but deliberately spartan editor. Its default settings prioritise compatibility with ancient systems over convenience for modern workflows. The good news: Vim's configuration system is among the most powerful of any editor — you can remap any key, define your own commands, add abbreviations, and change dozens of behaviours, all from a single plain-text file.
This chapter builds a foundational .vimrc — the configuration file Vim reads on startup — that turns the defaults into something genuinely comfortable for daily use.
The .vimrc File
Location
| System | Location |
|---|---|
| macOS / Linux | ~/.vimrc (a hidden file in your home directory) |
| Windows | C:\Users\yourlogin\.vimrc or C:\Users\yourlogin\_vimrc |
| Vim 8+ (any) | ~/.vim/vimrc (no dot, inside the .vim directory) — preferred modern location |
If the file does not exist, create it. Vim reads it automatically every time it starts.
Syntax basics
The .vimrc is a plain text file containing Vim commands, one per line — exactly as you would type them at the : prompt, but without the leading colon. Comments begin with " (a double-quote character).
set number " same as :set number at the command prompt
syntax on " same as :syntax on
Reloading your config without restarting
After editing .vimrc you can apply changes immediately without closing Vim:
:source ~/.vimrc # reload the vimrc file :so % # if you are currently editing vimrc, source the current file
Essential Settings
These are the settings most Vim users consider non-negotiable. Add them to your .vimrc and they will apply every time Vim opens.
set nocompatible " disable Vi compatibility mode — unlock all Vim features
filetype on " detect file type for syntax and indentation rules
filetype plugin on " load filetype-specific plugins
filetype indent on " load filetype-specific indentation rules
" ── Display ─────────────────────────────────────────────
set number " show line numbers (abbrev: se nu)
set relativenumber " show relative line numbers alongside absolute
set cursorline " highlight the line the cursor is on
set wrap " wrap long lines (default); set nowrap to disable
set showmatch " briefly highlight matching bracket when cursor is on one
set showcmd " show partial command in status bar as you type
set ruler " show line/column in status bar
syntax on " enable syntax highlighting
" ── Search ──────────────────────────────────────────────
set ignorecase " case-insensitive search (abbrev: ic)
set smartcase " override ignorecase when pattern has uppercase
set hlsearch " highlight all search matches
set incsearch " show matches as you type the pattern
" ── Indentation ─────────────────────────────────────────
set tabstop=4 " a Tab character is displayed as 4 spaces wide
set shiftwidth=4 " number of spaces used for indentation (>> and <<)
set expandtab " insert spaces instead of tab characters
set autoindent " copy indent from previous line when starting a new one
set smartindent " smart auto-indentation for code blocks
" ── Clipboard ───────────────────────────────────────────
set clipboard=unnamedplus " use system clipboard for all yank/delete/paste
" ── Behaviour ───────────────────────────────────────────
set hidden " allow switching buffers without saving first
set confirm " ask instead of silently failing on :q with unsaved changes
set history=1000 " remember 1000 commands in history (default is 20)
set undolevels=1000 " allow 1000 levels of undo
set backspace=indent,eol,start " make Backspace work as expected in Insert mode
set wildmenu " enhanced Tab completion menu for commands
set wildmode=list:longest " complete to longest common match, then list options
set nocompatible — always put this first. Without it, Vim runs in a compatibility mode designed to behave like the original vi, which disables many features introduced in Vim. Place it as the very first line of your .vimrc.
Checking and toggling settings
:set # show all non-default settings currently active :set all # show every setting with its current value :set number? # query the current value of a specific setting :set nonu # disable a boolean setting by prepending "no" :set nu! # toggle a boolean setting with ! :help option-summary # browse the full list of all settings in Vim's built-in help
Colour Schemes and Syntax Highlighting
:syntax on # enable syntax colouring (add to .vimrc without the colon) :syntax off # disable syntax colouring :colorscheme desert # switch to the 'desert' colour scheme :colorscheme morning # light theme :colorscheme delek # another built-in option :colorscheme <Tab> # Tab through all installed colour schemes
To list all available schemes: :colorscheme <Space><Tab> — this opens the wildmenu showing all options.
To make your chosen scheme permanent, add this to .vimrc:
.vim colour files in ~/.vim/colors/. Hundreds of schemes are available online. Popular choices include gruvbox, molokai, solarized, and nord. With a plugin manager (see the tip at the end of this chapter), installing them is a one-liner.
Key Mappings
Key mappings let you reassign any key (or key sequence) to any action. This is one of the most powerful customisation tools in Vim — the right mappings can eliminate dozens of keystrokes from your daily workflow.
Mapping commands
| Command | Mode | Use |
|---|---|---|
nnoremap | Normal | Map a key in Normal mode (recommended) |
inoremap | Insert | Map a key in Insert mode |
vnoremap | Visual | Map a key in Visual mode |
noremap | Normal + Visual + Operator | Map in multiple modes at once |
nmap / map | Normal | Map without the "no-remap" safety — avoid |
noremap variants, never plain map. The difference is that noremap (no-remap) prevents recursive mappings — if you map key A to key B, and later map key B to something else, noremap still runs the original action of B. Plain map would chain them, causing hard-to-debug loops. Use nnoremap for Normal mode, inoremap for Insert mode.
Mapping syntax
" Syntax: noremap {lhs} {rhs} " lhs = key to press, rhs = what it does " Special key notation: " <Space> = spacebar " <CR> = Enter (Carriage Return) " <Esc> = Escape " <Tab> = Tab " <C-f> = Ctrl+f " <leader> = your leader key (see below)
Practical mappings to add to .vimrc
" Space scrolls forward a page (like PgDn)
nnoremap <Space> <C-f>
" Tab jumps to the next sentence in Normal mode
nnoremap <Tab> )
" jj in Insert mode acts as Escape — keeps fingers on home row
inoremap jj <Esc>
" Clear search highlights with Enter in Normal mode
nnoremap <CR> :nohlsearch<CR>
" Save with Ctrl+s in Normal and Insert mode
nnoremap <C-s> :w<CR>
inoremap <C-s> <Esc>:w<CR>a
" Move between windows with Ctrl+direction (no need for 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
" Navigate buffers quickly
nnoremap <F2> :bprevious<CR>
nnoremap <F3> :bnext<CR>
The leader key
The leader key is a namespace prefix for your own custom mappings. By convention it is set to \ (backslash) by default, but most users change it to , (comma) or <Space> for easier reach. It prevents your mappings from clashing with Vim's built-in commands.
let mapleader = ","
" Now define leader mappings — press , then the letter
nnoremap <leader>w :w<CR> " ,w = save file
nnoremap <leader>q :q<CR> " ,q = quit
nnoremap <leader>e :e ~/.vimrc<CR> " ,e = open vimrc for editing
nnoremap <leader>s :source ~/.vimrc<CR> " ,s = reload vimrc
Abbreviations
Abbreviations (:ab or :iabbrev) expand short trigger strings into longer text when you type them in Insert mode followed by a space, Enter, or punctuation. They are useful for fixing common typos, expanding jargon, and inserting frequently used phrases.
" In the command line (interactive, not in .vimrc): :ab _me philip.osztromok@email.com # type _me + space → expands :ab recieve receive # auto-correct typo :ab _ys Youngster # shorthand for a word
" Typo corrections
iabbrev recieve receive
iabbrev teh the
iabbrev dont don't
iabbrev occured occurred
iabbrev seperate separate
" Quick expansions — underscore prefix avoids accidental triggers
iabbrev _em yourname@example.com
iabbrev _sig Kind regards,<CR>Your Name
iabbrev _dt <C-r>=strftime('%Y-%m-%d')<CR> " inserts today's date
Ctrl+V immediately before the space or Enter that would trigger expansion. This inserts a literal space without triggering the abbreviation.
_ (e.g. _me, _sig) means they can never conflict with ordinary words — no English word starts with an underscore. This is a widely followed convention among Vim users.
Custom Commands
The :command statement (abbreviated :com) lets you define your own Command-mode commands. This is perfect for wrapping external tools you run frequently.
" Syntax: :command! CommandName action " ! overwrites if it already exists " Command names MUST start with an uppercase letter :command! PY !python3 % # run current Python file (:PY to execute) :command! WC !wc % # word count of current file :command! LS !ls -la # list directory contents
The % in these commands is a special placeholder that expands to the current filename. So :PY runs python3 app.py (or whatever the current file is named).
command! PY !python3 %
command! WC !wc -w %
command! TODAY r!date +\%Y-\%m-\%d " insert today's date below cursor
command! SH !bash % " run current file as a shell script
Running external commands interactively
Without defining a custom command, you can run any shell command with :!:
:!ls # list directory contents :!python3 % # run current file (% = current filename) :!git status # check git status without leaving Vim :!git diff % # diff current file against last commit :!chmod +x % # make current file executable
After the command finishes, press Enter to return to Vim. The output is displayed in a full-screen shell overlay.
A Complete Starter .vimrc
Here is a well-commented, complete starter configuration you can use as a base and adapt to your own preferences. Every line is explained.
" .vimrc — starter configuration
" ════════════════════════════════════════════════════════
" Must be first — disable Vi compatibility, enable all Vim features
set nocompatible
" ── File type detection ─────────────────────────────────
filetype plugin indent on
" ── Appearance ──────────────────────────────────────────
syntax on
colorscheme desert " change to your preferred scheme
set number " absolute line numbers
set relativenumber " relative numbers alongside absolute
set cursorline " highlight current line
set showcmd " show partial commands in status bar
set ruler " show line/col in status bar
set showmatch " highlight matching brackets
" ── Search ──────────────────────────────────────────────
set ignorecase " case-insensitive search
set smartcase " case-sensitive when pattern has uppercase
set hlsearch " highlight all matches
set incsearch " incremental search as you type
" ── Indentation ─────────────────────────────────────────
set tabstop=4 " tab width
set shiftwidth=4 " indent width
set expandtab " spaces instead of tabs
set autoindent " copy indent from previous line
" ── Behaviour ───────────────────────────────────────────
set hidden " allow unsaved buffers to be hidden
set backspace=indent,eol,start" sensible backspace in Insert mode
set history=1000 " command history size
set undolevels=1000 " generous undo history
set wildmenu " enhanced command completion
set wildmode=list:longest " completion behaviour
set clipboard=unnamedplus " use system clipboard
" ── Leader key ──────────────────────────────────────────
let mapleader = ","
" ── Key mappings ────────────────────────────────────────
nnoremap <Space> <C-f> " Space = page forward
nnoremap <CR> :nohlsearch<CR> " Enter clears search highlights
inoremap jj <Esc> " jj exits Insert mode
nnoremap <C-h> <C-w>h " Ctrl+direction to move between windows
nnoremap <C-j> <C-w>j
nnoremap <C-k> <C-w>k
nnoremap <C-l> <C-w>l
nnoremap <leader>e :e ~/.vimrc<CR> " ,e = edit vimrc
nnoremap <leader>s :source ~/.vimrc<CR> " ,s = reload vimrc
" ── Abbreviations ───────────────────────────────────────
iabbrev recieve receive
iabbrev teh the
iabbrev dont don't
" ── Custom commands ─────────────────────────────────────
command! PY !python3 %
command! WC !wc -w %
The Help System
Vim has a comprehensive built-in help system that is worth using. Every setting, command, and mapping is documented.
:help # open the help index :help option-summary # list of all settings with brief descriptions :help :map # help for the map command :help set # help for the set command :help normal # help on Normal mode commands :help vimrc # help on the vimrc file itself :help insert.txt # full Insert mode documentation
Inside the help window, use Ctrl+] to follow a hyperlink (shown in |pipes|) and Ctrl+O to go back. Close the help window with :q.
.vimrc can install colour schemes, file trees, Git integration, and language servers — without cluttering your config.