Vim Cheatsheet

Buffers, Windows, and Tabs

Use this Vim reference while you build software engineering projects, review code, or refresh the syntax you reach for most.

Buffers

A buffer is a file loaded into memory. Windows are viewports onto buffers, and tabs are collections of windows. Vim can hold dozens of buffers with only one window open.

CommandAction
:e fileEdit a file in the current window
:e!Reload the file, discarding changes
:ls or :buffersList every buffer
:b 3Go to buffer 3
:b nameGo to a buffer by partial name
:bn / :bpNext / previous buffer
:bf / :blFirst / last buffer
Ctrl-^ or :b#Toggle between the two most recent buffers
:bdDelete (close) the buffer
:bd!Close it, discarding changes
:bufdo cmdRun a command in every buffer
:badd fileLoad a file without switching to it
:ls flagMeans
%The buffer in the current window
#The alternate buffer (Ctrl-^ target)
aActive: loaded and visible
hHidden: loaded but not shown
+Modified
-nomodifiable
=Read-only
:set hidden      " allow switching away from a modified buffer

Without hidden, Vim refuses to leave an unsaved buffer. Turning it on is one of the first things most people put in their config.

Windows (Splits)

CommandKeyAction
:spCtrl-w sSplit horizontally
:vsCtrl-w vSplit vertically
:sp fileSplit and open a file
:newCtrl-w nSplit with an empty buffer
:cloCtrl-w cClose this window
:onCtrl-w oClose every other window
:qCtrl-w qQuit this window
KeyMoves to
Ctrl-w h/j/k/lThe window left / below / above / right
Ctrl-w wThe next window, cycling
Ctrl-w pThe previously focused window
Ctrl-w t / Ctrl-w bThe top-left / bottom-right window
KeyResizes or moves
Ctrl-w =Equalize all windows
Ctrl-w _Maximize height
Ctrl-w |Maximize width
Ctrl-w + / -Grow / shrink height by one line
Ctrl-w > / <Grow / shrink width
10 Ctrl-w +Grow by 10 lines
:resize 20Set height to 20
:vertical resize 80Set width to 80
Ctrl-w H/J/K/LMove this window to the far left / bottom / top / right
Ctrl-w rRotate the windows
Ctrl-w xExchange with the next window
Ctrl-w TMove this window into its own tab
:set splitright splitbelow   " new splits open where you expect

Tabs

Tabs in Vim are workspaces, not files. Most people keep a handful of tabs and many buffers, not one tab per file.

CommandKeyAction
:tabnewNew empty tab
:tabnew fileNew tab with a file
:tabe fileSame thing
:tabngtNext tab
:tabpgTPrevious tab
:tabfirst / :tablastFirst / last tab
2gtGo to tab 2
:tabcClose this tab
:taboClose every other tab
:tabsList tabs and their windows
:tabm 0Move this tab to the front
:tabdo cmdRun a command in every tab

Finding Files

:e path/to/file            " Tab completes
:find file.txt             " search along 'path'
:set path+=**              " let :find recurse from the cwd
:e **/name<Tab>            " fuzzy-ish completion with a recursive glob
gf                         " open the file whose name is under the cursor
Ctrl-w f                   " open it in a split
gx                         " open the URL under the cursor externally
:pwd                       " current directory
:cd path                   " change it
:lcd path                  " change it for this window only
Netrw commandAction
:E or :ExploreBrowse the current file's directory
:Sex / :VexBrowse in a horizontal / vertical split
:RexReturn from netrw to the file you came from
- (in netrw)Go up a directory
EnterOpen the entry
%Create a new file
dCreate a directory
DDelete the entry
RRename the entry
IToggle the banner

Netrw is built in, so it is what you get on a bare server. In a configured setup a fuzzy finder (fzf.vim, telescope) usually replaces it for opening files.

Sessions and Views

:mksession ~/work.vim      " save windows, tabs, buffers, cwd
:mksession! ~/work.vim     " overwrite
vim -S ~/work.vim          " restore from the shell
:source ~/work.vim         " restore from inside Vim
:mkview                    " save this window's folds and options
:loadview                  " restore them
:set sessionoptions-=options   " do not bake options into sessions

The Arglist

The arglist is the set of files you passed on the command line, and it is the cleanest way to run one command over a known set of files.

CommandAction
:argsShow the arglist
:args **/*.tsReplace it with a glob
:argadd fileAdd a file
:argdelete *Clear it
:next / :prevNext / previous argument
:first / :lastJump to the ends
:argdo cmdRun a command on every argument
:args `git diff --name-only main`
:argdo %s/\<oldName\>/newName/ge | update