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 #3

Understanding Buffer Indicators

When you run :ls, each buffer shows status indicators:

Indicator
Meaning

%

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 hidden to allow switching buffers without saving. This is essential for a smooth workflow.

Tip: Use '0 to 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 :bufdo instead 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

Command
What it does

: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

Command
What it does

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

Command
What it does

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:

  1. Jump with gg, look, then Ctrl+o to return

  2. Or 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.nvimarrow-up-right 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.

Command
What it does

: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.nvimarrow-up-right) over Vim tabs.

Saving Files

Command
What it does

: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 :update over :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: undotreearrow-up-right 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 history

  • keepjumps — avoids changes to the jumplist

  • winsaveview/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 hidden is essential for fluid buffer switching.

  • The arglist is a controlled subset of the buffer list, making :argdo safer than :bufdo for 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

  1. Navigate between buffers — Open three files with vim file1.txt file2.txt file3.txt. Use :ls to list the buffers, then switch between them using :b2, :bn, :bp, and Ctrl+6 (alternate buffer). Close one buffer with :bd and verify it is gone from :ls.

  2. 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.

  3. Mass editing with argdo — Open several files with vim *.txt, then use :argdo to append a comment line to the end of every file. Undo the changes across all files afterward.

  4. Search across files with vimgrep — Use :vimgrep to 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.

  5. Create a scratch buffer — Add the Scratch command 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?