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

SystemLocation
macOS / Linux~/.vimrc (a hidden file in your home directory)
WindowsC:\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).

" This is a comment — anything after " on a line is ignored
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
The portability trade-off: A heavily customised Vim feels fast and natural on your own machine, but when you SSH into a server or pair program on someone else's machine, you are working with vanilla Vim again. The advice to keep your config lean is not about limiting power — it is about ensuring you stay comfortable in stock Vim. Aim for a config that enhances rather than replaces Vim's native behaviour.

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.

" ── Sensible defaults ──────────────────────────────────
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:

colorscheme desert
Installing additional colour schemes: Place .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

CommandModeUse
nnoremapNormalMap a key in Normal mode (recommended)
inoremapInsertMap a key in Insert mode
vnoremapVisualMap a key in Visual mode
noremapNormal + Visual + OperatorMap in multiple modes at once
nmap / mapNormalMap without the "no-remap" safety — avoid
Always use 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

" ── Key mappings ────────────────────────────────────────

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

" Set leader key to comma
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
" ── Abbreviations in .vimrc ────────────────────────────

" 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
Preventing expansion: If you genuinely need to type an abbreviation trigger without expanding it, press Ctrl+V immediately before the space or Enter that would trigger expansion. This inserts a literal space without triggering the abbreviation.
Use the underscore prefix convention: Prefixing your personal abbreviations with _ (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).

" ── Custom commands ─────────────────────────────────────
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.

Plugin managers: Once you are comfortable with the basics, a plugin manager dramatically simplifies adding third-party tools. The most popular options are vim-plug (minimal, fast), Vundle (classic), and lazy.nvim (for Neovim). A single line in your .vimrc can install colour schemes, file trees, Git integration, and language servers — without cluttering your config.

Commands Introduced in This Chapter

Chapter 7 — Command Reference

Vimrc
:source ~/.vimrcReload the vimrc without restarting Vim
:so %Source the current file (when editing vimrc)
Settings
:setShow all non-default settings currently active
:set allShow every setting with its current value
:set {option}?Query the current value of an option
:set no{option}Disable a boolean option
:set {option}!Toggle a boolean option on/off
set nocompatibleDisable Vi compatibility (always first in vimrc)
set number / nonuShow / hide line numbers
set relativenumberRelative line numbers
set cursorlineHighlight the current line
set showmatchHighlight matching brackets
set showcmdShow partial commands in status bar
set hiddenAllow switching buffers without saving first
set wildmenuEnhanced Tab-completion menu
set tabstop=4Tab display width
set shiftwidth=4Indent width for >> and <<
set expandtabInsert spaces instead of tab characters
set clipboard=unnamedplusUse system clipboard by default
set history=1000Increase command history size
set undolevels=1000Increase undo history depth
:help option-summaryBrowse all available settings in built-in help
Colour schemes & syntax
:syntax on / offEnable / disable syntax highlighting
:colorscheme {name}Switch to a colour scheme
:colorscheme <Tab>Browse all available colour schemes
Key mappings (vimrc)
nnoremap {key} {action}Map a key in Normal mode (safe, non-recursive)
inoremap {key} {action}Map a key in Insert mode
vnoremap {key} {action}Map a key in Visual mode
let mapleader = ","Set the leader key to comma
Abbreviations
:ab {trigger} {expansion}Define an abbreviation (interactive)
iabbrev {trigger} {expansion}Define an abbreviation in vimrc
Ctrl+V (in Insert)Prevent the next character from triggering an abbreviation
Custom commands & shell
:command! {Name} {action}Define a custom Command-mode command
:! {shell-command}Run a shell command from within Vim
% (in :! commands)Expands to the current filename
Help
:helpOpen the help index
:help {topic}Open help for a specific topic or setting
Ctrl+] (in help)Follow a help hyperlink