Buffers, Windows & Tabs
One of the first things that confuses newcomers to Vim is how it handles multiple files. In most editors, each file gets its own tab. Vim takes a different approach — and once you understand it, you'll find it far more flexible.
The three concepts you need to internalize are:
Buffer: A file loaded in memory. Every file you open becomes a buffer, even if you can't see it on screen.
Window: A viewport into a buffer. You can have multiple windows showing different buffers — or even the same buffer twice.
Tab: A collection of windows (a layout). Think of tabs as separate desks, each with its own arrangement of windows.
The key insight is that buffers persist independently of windows. Closing a window doesn't close the buffer — the file stays in memory, ready to be displayed again. This is why :set hidden is so important: it lets you switch between buffers without saving each time.
What you'll learn in this chapter:
Understand the relationship between buffers, windows, and tabs in Vim
Navigate and manage multiple buffers efficiently using the buffer list and arglist
Split, resize, and arrange windows to create productive editing layouts
Use the Preserve function to run commands without disrupting your editing state
Perform mass file operations with
:argdo,:bufdo, and:cdo
Buffer Basics
" List all buffers
:buffers
" or
:ls
" Navigate buffers
:bnext " or :bn — go to next buffer
:bprevious " or :bp — go to previous buffer
:buffer 3 " or :b3 — go to buffer #3
:b filename " go to buffer by name (supports tab completion)
:bd " delete (close) current buffer
:bd 3 " delete buffer #3Understanding Buffer Indicators
When you run :ls, each buffer shows status indicators:
%
Current buffer (shown in active window)
#
Alternate buffer (switch with Ctrl+6)
a
Active (loaded and visible in a window)
h
Hidden (loaded but not visible)
+
Modified (has unsaved changes)
-
Buffer with modifiable off
=
Read-only buffer
Tip: Set
:set hiddento allow switching buffers without saving. This is essential for a smooth workflow.
Tip: Use
'0to jump to the position where you last exited Vim. This effectively reopens your last edited file at the exact spot you left off. You can also create a shell alias:alias lvim='vim -c "normal '\''0"'
Creating a Scratch Buffer
Sometimes you need a temporary workspace — a place to jot down notes, test a regex, or paste some text for reformatting. A scratch buffer is exactly that: a disposable buffer that Vim won't complain about when you try to close it without saving.
Or as a function:
Neovim: In Lua, you can create a scratch buffer with
vim.api.nvim_create_buf(false, true).
Bufferlist vs Arglist
This distinction trips up many Vim users, but it's simple once you see it. The arglist contains only the files you gave Vim as arguments when starting it (e.g., vim *.txt). The bufferlist contains all files loaded in memory, including those you opened later with :e. In other words, the arglist is a subset of the bufferlist.
Why does this matter? Because Vim has powerful commands that operate on entire lists of files:
:argdo {cmd}— execute command on all files in the arglist:bufdo {cmd}— execute command on all buffers
Mass File Editing with Arglist
Imagine you have 50 text files and need to add a disclaimer paragraph at the end of each one. Without Vim, you'd write a script. With Vim, it's a one-liner. First, copy the paragraph to your clipboard, then:
Tip: If you use
:bufdoinstead of:argdo, changes affect all loaded buffers — not just the files you opened from the command line. The arglist is a safer, more controlled subset.
Using vimgrep and cdo
Search across files and make changes:
The quickfix window shows results. Navigate with :cn (next) and :cp (previous). Close with :ccl, reopen with :copen.
Neovim: Use Telescope for a modern, fuzzy-finding alternative to vimgrep.
Windows
Windows in Vim are viewports — each one shows a buffer, and you can arrange them however you like. Need to see a header file while editing the implementation? Open a horizontal split. Want to compare two functions side by side? Use a vertical split. The flexibility is remarkable once you get comfortable with the keybindings (see Modes & Navigation Basics for foundational navigation commands).
Splitting Windows
:split or Ctrl+ws
Horizontal split
:vsplit or Ctrl+wv
Vertical split
:sp filename
Open file in horizontal split
:vsp filename
Open file in vertical split
:sbprevious
Open previous buffer in a split
Ctrl+wf
Open file under cursor in split
Navigating Windows
Ctrl+wh/j/k/l
Move to left/down/up/right window
Ctrl+ww
Cycle through windows
Ctrl+wr
Rotate windows
Ctrl+wo
Make current window the only one
Ctrl+wq
Close current window
Ctrl+w=
Make all windows equal size
Resizing Windows
Ctrl+w+
Increase height
Ctrl+w-
Decrease height
Ctrl+w>
Increase width
Ctrl+w<
Decrease width
Ctrl+w_
Maximize height
Ctrl+w
Reading Other Parts of the File
If you're at line 50 and want to see line 1, you can:
Jump with
gg, look, then Ctrl+o to returnOr type Ctrl+ws to split, navigate in one window, and close it with Ctrl+wq
Diff Mode
Compare two files side by side:
Or from within Vim: :vsp file2 then :diffthis in both windows.
Neovim: diffview.nvim provides a much richer diff experience. See Chapter 17: Git Integration.
Tabs
Tabs in Vim are not like browser tabs. Each tab is a layout of windows. Think of them as workspaces.
:tabnew
Open a new tab
:tabnew file
Open file in new tab
gt
Go to next tab
gT
Go to previous tab
:tabclose
Close current tab
:tabonly
Close all other tabs
Tip: Most Neovim users prefer buffers + a statusline/tabline plugin (like bufferline.nvim) over Vim tabs.
Saving Files
:w
Save current file
:up[date]
Save only if the file has been modified
:wa
Save all open files
:w !sudo tee %
Save as root (when you forgot sudo)
:e!
Discard all changes and reload
:earlier 10m
Go back 10 minutes in the undo history
Tip: Prefer
:updateover:w— it only writes if the file actually changed, preserving file timestamps.
The Undo Tree: Time Travel
Vim maintains a full undo tree (not just a linear undo stack). This means even after undoing and making new changes, the old branch is still accessible:
With :set undofile in your config, Vim persists the undo tree across sessions — you can undo changes from yesterday.
Neovim: undotree visualizes the undo tree as a sidebar, making it easy to navigate between branches.
The Preserve Function
Here's a problem every experienced Vim user faces: you run a substitution command, and suddenly your cursor has jumped to some random line and your last search pattern has been overwritten. The Preserve function solves this elegantly — it wraps any command so that your cursor position, scroll state, and search history remain untouched:
keeppatterns— runs the command without adding to search historykeepjumps— avoids changes to the jumplistwinsaveview/winrestview— saves and restores cursor position and scroll
Squeezing Blank Lines
Using the Preserve function to delete consecutive blank lines without moving the cursor:
Tip: For more advanced multi-file editing workflows that build on these concepts, see Advanced Workflows.
Summary
Buffers, windows, and tabs form the core of Vim's file management model. Unlike traditional editors where each tab represents a file, Vim separates the concepts: buffers hold file contents in memory, windows are viewports into those buffers, and tabs are collections of window layouts. Mastering these three abstractions — along with utilities like the Preserve function, the arglist, and the quickfix list — unlocks powerful multi-file editing workflows.
Key takeaways:
Buffers persist independently of windows; closing a window does not close the buffer, and
:set hiddenis essential for fluid buffer switching.The arglist is a controlled subset of the buffer list, making
:argdosafer than:bufdofor mass file operations.The Preserve function wraps commands to maintain your cursor position, scroll state, and search history.
Windows can be split horizontally or vertically, resized, and rearranged to suit any editing task.
Exercises
Navigate between buffers — Open three files with
vim file1.txt file2.txt file3.txt. Use:lsto list the buffers, then switch between them using:b2,:bn,:bp, and Ctrl+6 (alternate buffer). Close one buffer with:bdand verify it is gone from:ls.Split and resize windows — Open a file, create a vertical split with
:vsp, then a horizontal split with:sp. Practice moving between windows with Ctrl+wh/j/k/l. Resize the current window to maximum height, then equalize all windows.Mass editing with argdo — Open several files with
vim *.txt, then use:argdoto append a comment line to the end of every file. Undo the changes across all files afterward.Search across files with vimgrep — Use
:vimgrepto find all occurrences of a word across multiple files. Open the quickfix list, navigate the results, and perform a substitution on each match using:cdo.Create a scratch buffer — Add the
Scratchcommand from this chapter to your config. Open a scratch buffer, paste some text into it, and then close it. Verify that Vim does not prompt you to save.
Last updated
Was this helpful?