Buffers, Windows, Tabs: Vim's Three Kinds of Container
This chapter explains the difference between a buffer, a window, and a tab page, and teaches you how to move between them without getting lost.
The Three Concepts
Most editors have one concept: a file you're editing, optionally with tabs across the top. Vim has three:
- Buffer: a file loaded into memory. You may or may not be looking at it
- Window: a viewport onto a buffer. You can split a window to see two buffers at once, or the same buffer twice
- Tab page: a layout of windows. Vim tabs are not a list of open files; they are a collection of windows with their own arrangement
Think of it this way. You have a stack of documents on your desk (buffers). You pick up some of them and lay them out in front of you (windows). If you need a different arrangement for a different task, you flip the desk over to a second surface (tab page) and lay out other documents there.
Most Vim users live in buffers. Windows are common. Tabs are rare.
Buffers
Every file you've opened is a buffer. Switch between them without closing anything:
:e path/to/file open a file (and create a buffer for it)
:ls or :buffers list all buffers
:b {num} switch to buffer number {num}
:b {name} switch to a buffer by partial name
:bnext or :bn next buffer
:bprevious or :bp previous buffer
:bfirst :blast first, last
:bdelete or :bd delete a buffer (closes the file)
:bwipeout stronger: delete the buffer entirely
A typical session, opening three files:
:e src/main.js
:e src/util.js
:e src/index.html
:ls
The output:
1 #h "src/main.js"
2 #h "src/util.js"
3 %a "src/index.html"
Symbols: % is the current buffer, a means active, h means hidden. Numbers are the buffer IDs.
:b 1 switch to main.js
:b util switch to util.js (partial name works)
Hidden buffers
By default, Vim won't let you leave a buffer with unsaved changes without warning. Set:
:set hidden
Now you can switch away from unsaved buffers and come back. Vim keeps them in memory. This is almost always what you want. Add it to your .vimrc and forget about it.
Buffer-based workflow
Most Vim users work mostly with buffers and very few windows. Rough loop:
- Open a handful of files with
:e - Navigate between them with
:bnext,:bprev,:b partial-name - Close finished ones with
:bd
Map a couple of these to leader shortcuts (chapter 9) and buffer switching becomes invisible.
Windows
Windows are visual splits of the current tab page.
:split or :sp horizontal split
:vsplit or :vsp vertical split
:new horizontal split with an empty buffer
:vnew vertical split with an empty buffer
:sp path/to/file split and open a file
:vsp path/to/file vertical split and open a file
Window commands
All window commands start with <C-w>:
<C-w>h move to the window on the left
<C-w>j down
<C-w>k up
<C-w>l right
<C-w>w cycle to the next window
<C-w>p previous window you were in
<C-w>s split horizontally
<C-w>v split vertically
<C-w>c close the current window (same as :close)
<C-w>o close all other windows (same as :only)
<C-w>q quit: close window and possibly Vim
<C-w>= equalise all window sizes
<C-w>_ maximise height
<C-w>| maximise width
<C-w>H move the window to the far left
<C-w>J move to the bottom
<C-w>K move to the top
<C-w>L move to the far right
<C-w>r rotate windows
<C-w>x swap with next window
That looks like a lot. The ones you'll actually use every day:
<C-w>h j k l navigate
<C-w>s v split
<C-w>c close
<C-w>= re-equalise
Five. That is what you need.
Resizing windows
:resize 20 set height to 20 lines
:resize +5 grow by 5 lines
:vertical resize 80 set width to 80 columns
<C-w>+ <C-w>- grow, shrink height
<C-w>> <C-w>< grow, shrink width
A count works too: 10<C-w>+ grows 10 lines.
Tab Pages
Tabs in Vim are not a list of open files. They are separate window layouts. Think of them as workspaces. Each tab can have its own set of windows, each showing whatever buffers you want.
:tabnew open a new empty tab
:tabnew path/to/file open a file in a new tab
:tabedit same as :tabnew
:tabclose close the current tab
:tabonly close all other tabs
gt next tab
gT previous tab
{n}gt go to tab number n
:tabs list tabs
Tabs are useful when you're working on two unrelated things in the same session, each with its own window arrangement. Most of the time, buffers serve you better.
A rule I try to follow: one tab per distinct task. If I start context-switching, I open a tab. Otherwise, everything is buffers.
A Concrete Example
Say you're editing a Python file and want to see the test file beside it.
:e src/app.py open the implementation
:vsp tests/test_app.py vertical split with the test file
Now you have two windows side by side. Jump between them:
<C-w>l move right (to the test file)
<C-w>h move left (back to implementation)
Switch the implementation buffer to a helper file while keeping the test visible:
<C-w>h move to the implementation window
:b helpers switch that window's buffer
The test window is unchanged. That is the buffer / window split in action.
The Argument List
A fourth, older concept: the argument list, :args. It is the list of files passed on the command line:
vim src/*.py
Inside Vim:
:args show the argument list
:next :prev cycle through arg list
:first :last
:argadd path add a file
:argdelete path remove
In practice, use :args when you open Vim on many files and want to iterate through them, especially with :argdo (run a command on every file in the arglist):
:argdo %s/\vold/new/g | update
That runs a substitute on every file in the arglist and saves them all. Useful for renames.
Diffing Two Buffers
Fast side-by-side diff:
:e a.txt
:vsp b.txt
:windo diffthis
Or from the shell:
vim -d a.txt b.txt
Normal diff commands then apply: ]c next diff, [c previous, do obtain (pull from the other side), dp put (push to the other side).
Common Pitfalls
"I closed a window and Vim quit." <C-w>c closes the last window, which closes the tab, which if it's the last tab, closes Vim. Use <C-w>o if you want only the current window.
"I opened a file and lost my splits." :e replaces the buffer in the current window. To open in a split, use :sp path or :vsp path.
":bd says I have unsaved changes." Save with :w, or force with :bd!. Or set hidden so you can abandon a modified buffer temporarily.
"I can't tell which window is focused." Vim highlights the status line of the active window. If your colorscheme doesn't, set statusline can help (chapter 9). Another tell: the cursor is only in one window at a time.
"I'm drowning in tabs." You're probably using tabs for what should be buffers. Close tabs with :tabonly, open files with :e, use :ls and :b to switch. Treat tabs as rare.
Next Steps
Continue to 08-registers-and-macros.md to learn Vim's 26 clipboards and the macro system that sits on top of them.