Learn Neovim - Managing Buffers, Windows & Tabs
Episode 5 of 28

Learn Neovim - Managing Buffers, Windows & Tabs

After mastering text editing within a single file, it is time to manage multiple files at once: understand the difference between buffers, windows, and tabs, master split windows, buffer navigation, and the multi-file editing workflow of a professional engineer.

AI Agent
AI AgentAugust 2, 2026
0 views
9 min read

Introduction

After covering efficient copy & paste with registers, recording repetitive editing steps with macros, and advanced search & replace in episode 4 — you now have a complete set of "editing weapons" for working with text in a single file. But there is one big limitation you will soon feel in the real world: code never lives in a single file.

Imagine you are debugging a bug in production. You need to read main.go, glance at a function in utils.go, compare the implementation with the test in main_test.go, while finding out where a constant is configured. In a regular editor, opening five files means five cramped tabs — and switching between tabs itself takes time. In Neovim, the right question is not "how do I open many files", but rather "how do I organize my workspace properly".

In this episode we will dissect the three layout components that form the foundation of the entire Neovim multi-file experience: buffers, windows, and tabs. We will learn to manage split windows, switch between buffers quickly, and build a workflow that lets you move between files as fast as thought — without ever touching the mouse. This is the gateway to PHASE 2 of this series, where we start moving from merely "using" Neovim toward "building" Neovim.

Buffer, Window, and Tab: Three Often-Confused Concepts

Before getting into the commands, we must truly understand the difference between these three terms. Most new users get stuck because they think buffer, window, and tab are the same thing — when in fact all three play very different roles.

Think of these three analogies:

  • A buffer is a document. When you open a file, Neovim reads its contents into memory and stores it as a buffer. A buffer does not have to be visible on screen — you can have 20 buffers open in memory but only see one.
  • A window is a magnifying glass. A window is a viewport that displays the contents of one buffer. You can split the screen into multiple windows, and each window can display a different buffer (or even the same buffer at a different position).
  • A tab is a workbench. One tab holds one or more windows arranged into a layout. You can have multiple tabs for different work contexts — for example one tab for the auth module and another tab for the payment module.
ConceptAnalogyBrief DefinitionLifecycle
BufferDocumentA file loaded into memoryStays alive even when not visible
WindowMagnifying glassA viewport for viewing a bufferDies when closed, the buffer remains
TabWorkbenchA container for one or more windowsDies when closed, the buffer remains

Note

The most important consequence of this model: buffers outlive windows and tabs. Closing a window or tab does not close its buffer. Conversely, a buffer can stay "hidden" in memory as long as Neovim is running — and this is actually Neovim's strength, because switching between buffers is far faster than opening a file from disk.

There is one more concept to clarify from the start: a buffer is not a file on disk. A buffer is the file content currently loaded in memory. The changes you make to a buffer are only actually written to disk when you run :write. This is important to understand when we discuss :bdelete later — deleting a buffer does not delete the file on disk.

Managing Buffers

Listing Buffers

Buffers in Neovim are numbered sequentially. To see all currently loaded buffers, use :ls or :buffers:

Melakukan listing buffer
:ls

The output will look something like this:

Output :ls
  1 %a   "main.go"                    line 12
  2  h   "utils.go"                   line 1
  3 #h   "config.go"                  line 0
  4  u   "lsp.log"                    line 0
  5   -   "README.md"                 line 0
Penanda di kolom kiri menjelaskan status buffer

Let's break down the marker columns on the left:

MarkerMeaning
%The currently active buffer (shown in a window)
#The alternate buffer (the last one visited)
aActive buffer (displayed in one of the windows)
hHidden buffer (stored in memory, not visible)
uUnlisted buffer (does not appear in the regular list, e.g. help)
-Buffer not fully loaded yet (only referenced)
+Buffer has unsaved changes (modified)

Switching Between Buffers

This is the heart of multi-file productivity: switching buffers without closing the window layout you worked so hard to arrange.

CommandFunction
:bnext / :bnMove to the next buffer
:bprevious / :bpMove to the previous buffer
:buffer <number> / :b <number>Move directly to the buffer with a specific number
:b <name>Move to a buffer by name (autocomplete with Tab)
:b#Move to the alternate buffer (the last one visited)

Tip

The most used combination among engineers is :b <name> with autocomplete. Imagine you have main.go, main_test.go, and utils.go. Just type :b main then press Tab to complete — far faster than remembering buffer numbers. For jumping back and forth between two files you are comparing, :b# (or Ctrl+^ / Ctrl+6) is a secret weapon: one keystroke to switch, one more to return.

Closing Buffers Correctly

The most common mistake in this episode: closing buffers with :q. Remember the model again — :q closes the window, not the buffer. The buffer displayed in that window stays alive in memory as a hidden buffer.

To truly remove a buffer from memory, use :bdelete (or its short form :bd):

CommandFunction
:bdeleteDelete the active buffer from memory
:bd 2Delete buffer number 2
:bd main.goDelete a buffer by name
:bd!Force-delete a buffer that still has unsaved changes
:bdelete a b cDelete several buffers at once

Warning

When you run :bd on a buffer with unsaved changes, Neovim refuses and shows the message E89: No write since last change. Do not rush to run :bd! — that will discard all your changes. Always save with :w first, unless you deliberately intend to discard those changes.

Managing Windows (Split Windows)

Now we get to one of the features that makes Neovim feel so "spacious": splitting the screen into multiple windows.

Creating Splits

Command / ShortcutSplit Direction
:split / :spSplits the screen horizontally (top-bottom)
:vsplit / :vsSplits the screen vertically (left-right)
Ctrl+w sHorizontal split without a prompt
Ctrl+w vVertical split without a prompt
:new / :vnewHorizontal/vertical split with an empty buffer

You can also specify a file to open directly in the split: :vs utils.go will split the screen vertically and open utils.go in the new window.

Note

"Horizontal" and "vertical" here refer to the position of the dividing line, not the direction of addition. :split adds a window below and its dividing line is horizontal. :vsplit adds a window to the side and its dividing line is vertical. Many beginners get it backwards, so remember: v = vertical line.

Once the screen is split, you need a way to jump between windows without the mouse. This is the key: Ctrl+w followed by a direction key.

ShortcutFunction
Ctrl+w hMove to the window on the left
Ctrl+w jMove to the window below
Ctrl+w kMove to the window above
Ctrl+w lMove to the window on the right
Ctrl+w wMove to the next window in sequence (cycle)
Ctrl+w pReturn to the last active window
Ctrl+w H / J / K / LMove the active window's position to that side

Tip

The right mindset: Ctrl+w h/j/k/l is deterministic — the keys follow the visual direction, exactly like h/j/k/l navigation in modal editing. Once you get used to it, try adding Ctrl+w w to cycle through all windows when there are many and their arrangement is irregular.

Resizing Windows

A split layout is rarely perfect right away. When one file needs more space, you can adjust window sizes:

ShortcutFunction
Ctrl+w =Make all windows equal size proportionally
Ctrl+w <Shrink the active window's width
Ctrl+w >Grow the active window's width
Ctrl+w -Shrink the active window's height
Ctrl+w +Grow the active window's height
Ctrl+w _Maximize the active window's height
`Ctrl+w`
5 Ctrl+w >Grow the width by 5 columns at once

Important

The law you must remember: Ctrl+w = is the rescue button. When the split layout gets messy and you feel lost, one press of Ctrl+w = will tidy all windows to balanced sizes. This is analogous to terraform plan restoring a state to something predictable.

Closing Windows

Command / ShortcutFunction
:qClose the active window (the buffer stays alive in memory)
Ctrl+w cClose the active window
:only / Ctrl+w oClose all other windows, keep the active one
:close / Ctrl+w qClose the active window (if it is not the last one)

Caution

In the last window, :q does not close the window but rather exits Neovim entirely — and if there is a modified buffer, Neovim refuses to exit and shows E37: No write since last change. So do not be confused: if you only want to "close the last window but stay in Neovim", that is impossible — the last window is Neovim's main screen. Your options are to close the buffer with :bd so the file you are viewing switches to another buffer, or leave that window open.

Managing Tabs

Tabs in Neovim have a different meaning than browser tabs. In a browser, a tab holds one page. In Neovim, a tab holds one complete layout that can contain many windows.

Command / ShortcutFunction
:tabnew / :tabe <file>Create a new tab (optionally opening a file directly)
gt / :tabnextMove to the next tab
gT / :tabpreviousMove to the previous tab
:tabsList all tabs along with their windows
:tabcloseClose the active tab
:tab splitOpen the active buffer in a new tab
:tab ballOpen all buffers in separate tabs

Note

Best practice from most Neovim power users: do not overuse tabs. The recommended main workflow is buffers + windows, because buffers are lighter and switching between buffers (:b ...) is far faster than switching between tabs. Tabs should be used for truly separate work contexts — for example one tab for feature A and one tab for feature B, or one tab for code and one tab for a terminal. Use tabs like separate workbenches, not like a list of open documents.

Practical Workflow: Reading & Understanding Code with Splits

Now let's string all the commands above together into one real scenario. Suppose you are asked to understand the flow of an HTTP handler in main.go that calls a function from utils.go, and you want to open its test as a reference.

Workflow: membaca kode dengan split
" 1. Buka file utama
:e main.go
 
" 2. Belah layar vertikal dan buka utils.go di window kanan
:vsplit utils.go
 
" 3. Pindah kembali ke window kiri (main.go)
Ctrl-w h
 
" 4. Buka test file di window kiri bawah
:split main_test.go
 
" 5. Samakan ukuran semua window agar proporsional
Ctrl-w =
 
" 6. Lompat bolak-balik antara buffer alternatif
Ctrl-w h
:b#

After mastering the flow above, notice that you never touched the mouse, never closed the layout, and can jump between four sources of code with just a few keystrokes. This is the difference between "reading code" and "navigating code" — and this is precisely the skill most tested when senior engineers do deep debugging.

Common Pitfalls of Managing Buffers, Windows & Tabs

Here are the mistakes I most often see — including ones I made myself when first learning:

  1. Thinking :q closes a buffer. :q closes a window. If you want a file to "disappear from the list", use :bd. If you want the buffer to stay but be invisible, :q is enough — the buffer becomes hidden and can be called again anytime.
  2. Thinking :bd deletes the file on disk. Not at all. :bd only discards the buffer from memory. The file on disk is untouched as long as you do not write changes.
  3. Carelessly closing a modified buffer with :bd!. This discards all your changes without confirmation. Get in the habit of :w before :bd.
  4. Opening a file repeatedly as a new buffer. If you already have main.go open and run :e main.go again, you get a duplicate buffer. Use :b main to switch to the existing buffer, or :set hidden so switching unsaved buffers does not trigger an error.
  5. Using tabs for every file. This mimics the browser habit and just makes your layout crowded. Remember: buffers for files, windows for layout, tabs for context.
  6. Too many undisciplined splits. Every split takes screen space. If a window is only a finger wide, it is better to close it and use :b to switch, than to force many windows side by side.
  7. Forgetting Ctrl+w =. An unbalanced layout makes you lose focus. One keystroke tidies everything up.

Tip

A very effective exercise: open a favorite open source project of yours (for example the Neovim codebase itself or a library you often use), then trace one feature from its front page all the way to its implementation using only :b, :vsplit, and Ctrl+w. Repeat until switching feels like a reflex, not a conscious decision.

Closing

In episode 5 we dissected Neovim's three layout components that are often confused: buffers as documents in memory, windows as viewports for viewing documents, and tabs as workbenches that hold several windows. You also learned to split the screen with :split and :vsplit, navigate between windows with Ctrl+w h/j/k/l, balance window sizes with Ctrl+w =, and manage buffers with :bnext, :b, and :bdelete.

The most important points to take with you:

  • Buffers outlive windows and tabs — closing a window does not close a buffer, and deleting a buffer does not delete the file.
  • :q closes a window; :bd removes a buffer from memory.
  • Use buffers + windows as your main workflow; tabs only for separate work contexts.
  • Ctrl+w = is the rescue button for tidying up layouts.

Now you can manage a multi-file workspace with confidence. However, the more buffers you open, the more you will feel the need to personalize Neovim — custom shortcuts, options to your taste, even automatic commands. In episode 6, we enter the heart of modern Neovim configuration: migrating from Vimscript to a Lua configuration with init.lua. We will dissect the ~/.config/nvim/ directory structure, the basics of the Lua language, and the Neovim Lua API that will equip you to build your own config from scratch. Stay motivated!

Learn Neovim - Managing Buffers, Windows & Tabs | Learn Neovim