Vim is not just a text editor—it's a way of life for developers, system administrators, and power users around the world. What appears initially as a cryptic, arcane relic becomes, with practice, the most efficient text manipulation tool ever conceived. This comprehensive guide will take you from confusion to mastery, revealing why decades after its creation, Vim continues to be one of the most powerful weapons in a power user's arsenal.
Vim (Vi IMproved) is a highly configurable text editor built to enable efficient text editing. Originally created by Bram Moolenaar as an improved version of the Unix editor Vi, Vim has evolved into one of the most powerful text editors available.
Why should you master Vim?
Longevity: The skills you develop in Vim will serve you for your entire career. Unlike many modern tools, Vim's core concepts have remained relatively stable for decades.
Let's embark on this journey to transform how you interact with text forever.
Most Linux distributions come with Vim pre-installed or at least have Vi available. To install Vim:
Ubuntu/Debian:
sudo apt update
sudo apt install vim
Fedora:
sudo dnf install vim
Arch Linux:
sudo pacman -S vim
macOS comes with Vim pre-installed. For the latest version, you can use Homebrew:
brew install vim
Download the installer from the official Vim website, or install Gvim (Vim with GUI):
winget install vim.vim
Check your Vim version:
vim --version
#to open vim, simply type vim followed by the filename to open
vim myfilename.txt
#to go into edit mode press the letter i
i
#now add some text or edit text
#to get out of edit mode press ESC
#To exit Vim (saving changes):
#Press Esc to ensure you're in normal mode
#Type :wq and press Enter (write and quit)
:wq
#To exit without saving:
#Press Esc to ensure you're in normal mode
#Type :q! and press Enter (quit, discard changes)
:q!
Vim's power comes from its modal nature. Most editors are always in "insert mode" - what you type appears as text. Vim separates editing actions into different modes:
Esc
from any other mode to return to Normal modeEnter from Normal mode with:
i
- insert at cursorI
- insert at beginning of linea
- append after cursorA
- append at end of lineo
- open new line belowO
- open new line aboveEnter from Normal mode with:
v
- character-wise visual modeV
- line-wise visual modeCtrl+v
- block-wise visual modeEnter from Normal mode by typing :
, /
, or ?
Understanding these modes is fundamental to mastering Vim. The real power comes from the seamless transitions between them.
h
- move leftj
- move downk
- move upl
- move rightw
- move forward to the beginning of the next worde
- move forward to the end of the current/next wordb
- move backward to the beginning of the current/previous word0
- move to the beginning of the line^
- move to the first non-blank character of the line$
- move to the end of the linegg
- move to the beginning of the fileG
- move to the end of the file:{number}
- move to a specific line number{number}G
- move to a specific line numberCtrl+f
- page down (forward)Ctrl+b
- page up (backward)Ctrl+d
- half page downCtrl+u
- half page upzz
- center the cursor on the screenzt
- position the cursor at the top of the screenzb
- position the cursor at the bottom of the screen%
- jump to matching bracket/parenthesis*
- search for the word under the cursor (forward)#
- search for the word under the cursor (backward)f{char}
- move to the next occurrence of character {char} on the current lineF{char}
- move to the previous occurrence of character {char} on the current line
Practice these movements until they become second nature. Efficient navigation is the foundation of Vim mastery.
i
- insert before cursora
- append after cursorI
- insert at beginning of lineA
- append at end of lineo
- open new line below and enter insert modeO
- open new line above and enter insert modex
- delete character under cursorX
- delete character before cursordd
- delete current lineD
- delete from cursor to end of lineyy
or Y
- yank (copy) current linep
- paste after cursorP
- paste before cursoru
- undo last changeCtrl+r
- redo last undone changecw
- change word (deletes from cursor to end of word and enters insert mode)C
- change to end of line (deletes from cursor to end of line and enters insert mode)cc
- change entire line (deletes line and enters insert mode)c{motion}
- change text that the motion command would move overVim has the concept of "text objects" which allow you to operate on chunks of text:
iw
- "inner word" (the entire word under the cursor)
aw
- "a word" (the word plus surrounding whitespace)
is
- "inner sentence"
as
- "a sentence"
ip
- "inner paragraph"
ap
- "a paragraph"
i(
or i)
- "inner parentheses"
a(
or a)
- "a parentheses" (including the parentheses)
i{
or i}
- "inner curly braces"
a{
or a}
- "a curly braces" (including the braces)
i"
- "inner quotes"
a"
- "a quotes" (including the quotes)
Text objects are used with operators. For example:
diw
- delete inner word
ci"
- change inner quotes
ya)
- yank a parentheses (including parentheses)
Vim's power comes from combining operators with motions and text objects. The main operators are:
d
- delete
c
- change (delete and enter insert mode)
y
- yank (copy)
>
- indent right
<
- indent left
=
- auto-indent
g~
- swap case
gu
- make lowercase
gU
- make uppercase
Pattern: {operator}{count}{motion}
Examples:
d2w
- delete two words
y3j
- yank three lines down
>ap
- indent a paragraph
gUiw
- uppercase inner word
.
- repeat last change@:
- repeat last command-line commandMacros let you record a sequence of commands to replay later:
q{register}
- start recording to register (a-z)q
- stop recording@{register}
- play back the macro@@
- repeat the last played macro
Example:
qa
- start recording to register 'a'q
- stop recording@a
- play back the macro5@a
- play back the macro 5 timesguu
- make entire line lowercasegUU
- make entire line uppercaseg~~
- swap case of entire line>G
- indent from current position to end of file=G
- auto-indent from current position to end of fileMarks allow you to save positions and jump back to them later:
m{a-zA-Z}
- set mark at current position
a-z
) are file-specificA-Z
) are global across files`{mark}
- jump to the exact position of mark'{mark}
- jump to the beginning of the line containing markVim has multiple registers for storing text:
"{register}
prefix before a command to specify register
Registers a-z: named registers for user storage
Register 0: contains the last yanked text
Registers 1-9: contain the last deleted or changed text
Register +: system clipboard (OS dependent)
Register *: selection clipboard (OS dependent)
Examples:
"ayy
- yank current line into register 'a'
"ap
- paste content from register 'a'
"+yy
- yank current line to system clipboard
"+p
- paste from system clipboard
/pattern
- search forward for pattern?pattern
- search backward for patternn
- repeat search in same directionN
- repeat search in opposite direction:set ignorecase
- case-insensitive search:set smartcase
- case-sensitive if pattern contains uppercase:set incsearch
- show incremental search results:set hlsearch
- highlight all search matches:nohlsearch
or :noh
- turn off highlighting until next searchf{char}
- find next occurrence of character on current lineF{char}
- find previous occurrence of charactert{char}
- move till next occurrence of character (cursor before char)T{char}
- move till previous occurrence of character;
- repeat last f, F, t, or T motion,
- repeat last f, F, t, or T motion in opposite direction:{range}s/{pattern}/{replacement}/{flags}
- substitute command
Common ranges:
%
- entire file
'<,'>
- visual selection (appears automatically when you press :
after selecting text)
{number},{number}
- specific line range
.
- current line
$
- last line
.,$
- from current line to end of file
Common flags:
g
- global (replace all occurrences on each line)
c
- confirm each substitution
i
- case insensitive
I
- case sensitive
Examples:
:%s/foo/bar/g
- replace all occurrences of "foo" with "bar" in the entire file
:%s/foo/bar/gc
- same, but confirm each replacement
:1,10s/^/#/
- comment out lines 1-10 by adding # at beginning
Vim uses regular expressions for powerful pattern matching:
\<word\>
- match whole word^
- beginning of line$
- end of line.
- any single character*
- zero or more of the preceding character\+
- one or more of the preceding character\?
- zero or one of the preceding character\{n,m}
- between n and m of the preceding character[abc]
- any character from the set[^abc]
- any character not in the set\d
- digit\s
- whitespace character\S
- non-whitespace characterv
- character-wise visual modeV
- line-wise visual modeCtrl+v
- block-wise visual mode (rectangular selection)gv
- reselect the last visual selectionOnce text is selected, you can:
d
- delete selectiony
- yank (copy) selectionc
- change selection (delete and enter insert mode)>
- indent right<
- indent left=
- auto-indent~
- swap caseu
- make lowercaseU
- make uppercase:
- perform command on selection (e.g. :s/foo/bar/g
)With block-wise visual mode (Ctrl+v), you can:
I
to insert at the beginning of each line in the blockPress Esc
to apply the change to all selected lines
Similarly:
A
- append to end of each line in blockc
- change the blockr
- replace characters in the block
This is incredibly powerful for editing columnar data or making the same change across multiple lines at once.
Buffers are in-memory text of opened files:
:ls
or :buffers
- list all buffers:buffer {number}
or :b {number}
- switch to buffer by number:bnext
or :bn
- next buffer:bprevious
or :bp
- previous buffer:bfirst
or :bf
- first buffer:blast
or :bl
- last buffer:bdelete {number}
or :bd {number}
- delete a buffer (close a file)Windows are viewports onto buffers:
:split
or :sp
- horizontal split:vsplit
or :vs
- vertical split:new
- horizontal split with new file:vnew
- vertical split with new fileCtrl+w s
- horizontal splitCtrl+w v
- vertical splitCtrl+w w
- cycle through windowsCtrl+w h/j/k/l
- navigate to left/down/up/right windowCtrl+w H/J/K/L
- move window to far left/bottom/top/rightCtrl+w =
- make all windows equal sizeCtrl+w _
- maximize window heightCtrl+w |
- maximize window widthCtrl+w +
- increase window heightCtrl+w -
- decrease window heightCtrl+w >
- increase window widthCtrl+w <
- decrease window width:close
or :q
- close current window:only
or :o
- close all windows except currentTabs are collections of windows:
:tabnew
- open new tab:tabedit {file}
or :tabe {file}
- edit file in new tab:tabclose
or :tabc
- close current tab:tabonly
or :tabo
- close all other tabsgt
or :tabnext
- go to next tabgT
or :tabprevious
- go to previous tab{number}gt
- go to specific tab number:tabs
- list all tabsThe argument list contains files specified when vim was started:
:args
- display argument list:next
or :n
- edit next file in argument list:previous
or :prev
- edit previous file in argument list:first
or :rewind
- edit first file in argument list:last
- edit last file in argument list:args {files}
- set the argument listTo customize vim add your custom settings to a .vimrc file in your home directory. NOTE. comments in a .vimrc file are very unique - a double quote. “
~/.vimrc
$HOME\_vimrc
or $VIM\_vimrc
Here are some useful settings to include in your .vimrc:
" Enable syntax highlighting
syntax enable
" Show line numbers
set number
" Enable incremental search
set incsearch
" Highlight search results
set hlsearch
" Case insensitive search unless capital letter is used
set ignorecase
set smartcase
" Enable mouse support
set mouse=a
" Use spaces instead of tabs
set expandtab
set tabstop=4
set shiftwidth=4
set softtabstop=4
" Auto-indent
set autoindent
set smartindent
" Show matching brackets
set showmatch
" Highlight current line
set cursorline
" Keep cursor away from top/bottom of screen
set scrolloff=5
" Enable file type detection
filetype plugin indent on
" Allow backspacing over everything
set backspace=indent,eol,start
" Show incomplete commands
set showcmd
" Enable ruler (line and column number)
set ruler
" Enable wildmenu for command completion
set wildmenu
set wildmode=list:longest,full
" Set encoding
set encoding=utf-8
" Disable swap files
set noswapfile
" Enable persistent undo
set undofile
set undodir=~/.vim/undodir
You can create custom key mappings in your .vimrc:
" Map leader key to space
let mapleader = " "
" Quick save
nnoremap <leader>w :w<CR>
" Quick quit
nnoremap <leader>q :q<CR>
" Quick save and quit
nnoremap <leader>x :x<CR>
" Toggle line numbers
nnoremap <leader>n :set number!<CR>
" Clear search highlighting
nnoremap <leader>c :nohlsearch<CR>
" Split navigation
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>
" Move lines up and down
nnoremap <A-j> :m .+1<CR>==
nnoremap <A-k> :m .-2<CR>==
inoremap <A-j> <Esc>:m .+1<CR>==gi
inoremap <A-k> <Esc>:m .-2<CR>==gi
vnoremap <A-j> :m '>+1<CR>gv=gv
vnoremap <A-k> :m '<-2<CR>gv=gv
Autocommands execute actions automatically on events:
" Remove trailing whitespace on save
autocmd BufWritePre * :%s/\s\+$//e
" Return to last edit position when opening files
autocmd BufReadPost *
\ if line("'\"") > 0 && line("'\"") <= line("$") |
\ exe "normal! g`\"" |
\ endif
" Set specific settings for specific file types
autocmd FileType python setlocal tabstop=4 shiftwidth=4 expandtab
autocmd FileType javascript setlocal tabstop=2 shiftwidth=2 expandtab
:syntax on
:set autoindent
and :set smartindent
za
to toggle fold, zR
to open all folds, zM
to close all folds" Python-specific settings
autocmd FileType python setlocal
\ tabstop=4
\ softtabstop=4
\ shiftwidth=4
\ textwidth=79
\ expandtab
\ autoindent
\ fileformat=unix
" JavaScript/TypeScript settings
autocmd FileType javascript,typescript setlocal
\ tabstop=2
\ softtabstop=2
\ shiftwidth=2
\ expandtab
" HTML/CSS settings
autocmd FileType html,css setlocal
\ tabstop=2
\ softtabstop=2
\ shiftwidth=2
\ expandtab
" C/C++ settings
autocmd FileType c,cpp setlocal
\ tabstop=4
\ softtabstop=4
\ shiftwidth=4
\ expandtab
\ cindent
" Go settings
autocmd FileType go setlocal
\ tabstop=4
\ shiftwidth=4
\ noexpandtab
:terminal
or :term
- open terminal window (Vim 8.1+)Ctrl+w N
- switch to normal mode in terminal:shell
or :sh
- temporarily go to the shell:!{command}
- run external command:r !{command}
- read output of command into buffer:w !{command}
- send buffer to command as input:make
- run the make command:copen
- open quickfix window to see errors:cnext
and :cprevious
- navigate through errorsWith vim-fugitive:
:G
or :Git
- run git command:Gblame
- git blame:Gdiff
- git diff:Gstatus
- git status (navigate with -
to stage/unstage):Gcommit
- git commit:Gpush
- git pushvim scp://user@host/path/to/file
- edit remote file via SCPvim ftp://user@host/path/to/file
- edit remote file via FTPVim has excellent built-in documentation:
:help
or :h
- open general help:help {topic}
- get help on specific topic:help 'option'
- get help on an option:helpgrep {pattern}
- search help documentsCtrl+]
- follow tag/link in helpCtrl+t
- go back after following tag:help key-notation
- understanding key notation:help index
- list of all commands:help insert-index
- list of insert mode commands:help normal-index
- list of normal mode commands:help visual-index
- list of visual mode commandsCongratulations! You've reached the end of this comprehensive guide to Vim. What started as a seemingly cryptic, arcane text editor should now feel more like a powerful, customizable tool that can significantly improve your text editing efficiency.