The Mental Model#
Vim uses three layers for organizing open files:
- Buffers — an open file in memory (you can have many, even without seeing them)
- Windows — a viewport into a buffer (splits on screen)
- Tabs — a collection of windows (like workspace layouts)
The relationship:
Tab
├── Window (shows Buffer A)
├── Window (shows Buffer B)
└── Window (shows Buffer A again — same buffer, two views)Multiple windows can show the same buffer. Buffers exist whether or not they’re visible.
Buffers#
A buffer is created every time you open a file. Even if you switch to another file, the first one stays in memory.
Opening files into buffers#
:e file.txt " Open a file in the current window
:e src/main.js " Relative paths work
:e . " Open file explorer (netrw)Listing buffers#
:ls
" or
:buffersOutput looks like:
1 %a "index.md" line 42
2 # "config.toml" line 1
3 "about.md" line 1| Symbol | Meaning |
|---|---|
% | Current buffer (shown in active window) |
# | Alternate buffer (last edited, toggle with Ctrl-^) |
a | Active (loaded and visible) |
h | Hidden (loaded but not visible) |
+ | Modified (unsaved changes) |
Switching buffers#
| Command | Action |
|---|---|
:bn | Next buffer |
:bp | Previous buffer |
:b3 | Go to buffer 3 |
:b file | Go to buffer matching “file” (partial match works) |
Ctrl-^ | Toggle between current and alternate buffer |
:bd | Close (delete) current buffer |
:bd 3 | Close buffer 3 |
The alternate buffer#
Ctrl-^ switches between your two most recent buffers. This is extremely useful when you’re editing two related files (a module and its test, for example).
Windows (Splits)#
Windows divide your screen to show multiple buffers simultaneously.
Creating splits#
| Command | Action |
|---|---|
:sp or Ctrl-w s | Horizontal split (same file) |
:vsp or Ctrl-w v | Vertical split (same file) |
:sp file.txt | Horizontal split with a different file |
:vsp file.txt | Vertical split with a different file |
Navigating between windows#
All window commands start with Ctrl-w:
| Command | Action |
|---|---|
Ctrl-w h | Move to window left |
Ctrl-w j | Move to window below |
Ctrl-w k | Move to window above |
Ctrl-w l | Move to window right |
Ctrl-w w | Cycle to next window |
Resizing windows#
| Command | Action |
|---|---|
Ctrl-w = | Equalize all window sizes |
Ctrl-w + | Increase height |
Ctrl-w - | Decrease height |
Ctrl-w > | Increase width |
Ctrl-w < | Decrease width |
Ctrl-w _ | Maximize height |
| `Ctrl-w | ` |
:resize 20 | Set height to 20 lines |
:vertical resize 80 | Set width to 80 columns |
Moving windows#
| Command | Action |
|---|---|
Ctrl-w H | Move window to far left (vertical) |
Ctrl-w J | Move window to bottom (horizontal) |
Ctrl-w K | Move window to top (horizontal) |
Ctrl-w L | Move window to far right (vertical) |
Ctrl-w r | Rotate windows |
Closing windows#
| Command | Action |
|---|---|
:q or Ctrl-w q | Close current window |
:only or Ctrl-w o | Close all windows except current |
Closing a window doesn’t close the buffer — the file stays in memory.
Tabs#
Tabs in Vim are not like browser tabs. Each tab is a layout of windows. Use them when you want completely different workspace arrangements.
Managing tabs#
| Command | Action |
|---|---|
:tabnew | Open a new empty tab |
:tabnew file.txt | Open file in a new tab |
:tabn or gt | Next tab |
:tabp or gT | Previous tab |
:tabclose | Close current tab |
:tabonly | Close all other tabs |
3gt | Go to tab 3 |
When to use tabs#
Tabs are best for separate contexts, not separate files:
- Tab 1: application code (splits for module + test)
- Tab 2: configuration files
- Tab 3: documentation
If you just want to see multiple files, splits are usually better.
The Argument List#
The argument list tracks files you opened from the command line:
vim src/*.js:args " Show the argument list
:next " Go to next file in arglist
:prev " Go to previous file
:first " Go to first file
:last " Go to last fileRun a command across all files in the arglist#
" Replace in all argument files
:argdo %s/old/new/gc | update
" Set indentation in all files
:argdo set tabstop=4 | updateModify the arglist#
:args src/*.js " Set arglist to all JS files in src/
:argadd test/*.js " Add test files to arglistPractical Workflows#
Edit a file and its test side by side#
:e src/auth.js
:vsp test/auth.test.jsUse Ctrl-w l and Ctrl-w h to move between them. Use Ctrl-^ in either window to toggle to the last file you viewed there.
Compare two files#
vim -d file1.txt file2.txtOpens in diff mode with changes highlighted.
Open a file from netrw (file explorer)#
:e . " Open explorer in current directory
:vsp . " Open explorer in a splitNavigate with j/k, press Enter to open a file.
Quick reference lookup while editing#
" You're editing code, need to check something
:sp /etc/hosts " Open reference in a split
" ...read what you need...
Ctrl-w q " Close the reference splitRun a substitution across multiple files#
:args src/**/*.js
:argdo %s/oldFunction/newFunction/g | updateBest Practices#
- Think of buffers as open files and windows as views — don’t close buffers just because you can’t see them
- Use
Ctrl-^constantly to toggle between two related files - Use splits for files you need to see at the same time
- Use tabs for separate workspaces, not as a replacement for buffers
- Use
:bwith partial names instead of buffer numbers —:b authis faster than remembering:b7 - Learn
Ctrl-w =to reset window sizes after resizing your terminal - Use
:argdofor batch operations across files — it’s Vim’s version of find-and-replace across a project

