Working With Buffers in Vim: A Guide

Vim buffers is an editing workflow that opens a temporary space in the memory to store opened files, like a deck of cards. Here’s how to use it to manage workflows.

Written by Igor Irianto
Published on Dec. 09, 2024
Developer working on code with vim
Image: Shutterstock / Built In
Brand Studio Logo

When I formally switched to Vim full time after using Atom, IntelliJ and VS Code, I started a quest to find the best Vim editing workflow. After months of using Vim, I was drawn to the buffer workflow. A buffer is a temporary space in the memory to store your opened files. It’s a unique abstraction not found in other editors or IDEs.

6 Vim Buffers Workflow Commands to Know

  1. set hidden: Remove the vim save prompt that raises every time you change files.
  2. :bnext, :bprev: navigate to the next and previous buffer on the list.
  3. :bfirst, :blast: navigate to the first and last buffer on the list.
  4. ]b, [b: These shortened navigation commands come from the unimpaired.vim plugin, replacing :bnext and :bprev, respectively.
  5. ]B[BThese shortened navigation commands come from the unimpaired.vim plugin, replacing :blast and :bfirst respectively.
  6. :bufdo: Run an operation across all buffer files. 

Each time you open a file, Vim stores it in a buffer. If you open five files, you have five buffers. A buffer remains opened even if that file is not visible, in other words, the buffer is hidden. Buffers won’t go away until you either quit Vim or explicitly command it to close, like :bdelete.

In this article, I will share how that workflow works.

 

What Is Vim Buffers?

When I first learned about buffers, it was hard for me to visualize it. After all, I had never used buffer in editing before. The editors and IDEs that I’ve used all have tabs and windows, but not buffers. A good analogy is to think of the Vim buffer list as a stack of playing cards. Each card represents the files you have opened so far. All the cards are stacked face-up, but because they are stacked, only the top-most card is visible. The top card is the file that you are currently seeing, file1.txt

In this analogy, we’re only dealing with one tab and window, no split windows either. There are N numbers of cards in the stack just as there are N opened files. If you opened 10 files, then you have 10 buffers and 10 cards in the stack. If you need to view the next card, file2.txt card, you swap the topmost card with the second card from the top. Now, your second card from the top is visible sitting on the top of the stack. Your previous card, the file1.txt card, is now the second-from-the-top, no longer displayed. If you need to view the next card, file3.txt, you just need to find that card from the deck and put it on the top of the stack after tucking the file2.txt card back into the stack. That’s what it means to switch buffers.

More on Software EngineeringHow to Create a VPN for Free

 

Working With Buffers in Vim: A Guide

First, you need to have this in your vimrc:

set hidden

Without the set hidden, each time you switch to a different buffer without saving the current changes, Vim stops you and asks you to either discard your changes or save them. Common courtesy, I guess. Although it’s a nice feature to be prompted to save your file before leaving it, not being able to quickly switch buffers is the antithesis of the buffer workflow. Plus, your files aren’t really closed when you switch to a different buffer, they are just hidden.

Generally, you shouldn’t worry about losing your changes when switching to different buffers. Even when you exit Vim (:qall) and forget to save your changes, Vim will still remind you to save your changes, just don’t run :qall!. But in general, I almost never force quit Vim. Your muscle memory should save changes (:w) all the time. Since the positives, i.e., quick buffer switch, outweighs the cons, losing unsaved files, I suggest having the set hidden in your vimrc.

How to Switch Buffers

There are two major ways you can switch buffers quickly. We’ll examine the quickest buffer-switching method here, flying. But first, to display all buffers, you can use one of the two commands below:

:ls

Or:

:buffers

To switch to a buffer, you can run:

:buffer n

Where n is the buffer number.

I find it challenging to try and remember all the buffer numbers. The :buffers command makes a nice combo with the :buffer n command. Try running these two sequentially:

:buffers
:buffer n

You can also pass to the buffer command the buffer file name, too.

:buffers
:buffer file1.rb

With this, you can jump to any buffer files quickly and consistently. This command sequence is a bread-and-butter to my daily editing workflow.

You can create a key map for this operation. In your vimrc:

nnoremap <Leader>b :buffers<CR>:buffer<Space>

When you press <Leader>b, Vim displays all buffer information, including their buffer numbers and filenames, and you can select which buffer to jump into.

One of my favorite Vim plugins, fzf.vim, has a buffer command :Buffers that uses fzf and Vim’s popup window to fuzzy search your buffer list. I personally use this over the :buffers command because I find the pop-up window easier to see.

In my vimrc, I map the :Buffers command to Ctrl-b:

nnoremap <silent> <C-b> :Buffers<CR>

If you are a purist, stick with :buffers. If you are a fan of fzf, use :Buffers. Principally, they do the same thing: displaying a list of buffers and quickly jumping to a buffer. I am pretty sure that there are alternatives out there to switch buffers that I am not aware of. Don’t take my word, shop around.

This is the crux of the buffer workflow:

  • You open N files. These are the files relevant to your current task.
  • With these files opened, you can jump to any of them thanks to the buffer operation. I call this flying because you can reach any of these files quickly with the same number of keystrokes.

Let’s say that you have nine opened files in the buffers: file1.rb, file2.rb, ... file9.rb. You can reach any file with the same number of keystrokes. If you have the <Leader>b keymap, you can reach any of the nine files with four keystrokes: <Leader> + b + (buffer number) + Return. A constant number of keystrokes for an indefinite number of opened files? It’s a win!

Prior to the buffer workflow, I used to do a codebase-wide search to switch files. For example, if I need to go to the get_pdf method, I would go to my editor’s fuzzy search text box and type g-e-t-p-d-f in-file search. That’s a lot of typing. Moreover, what if the method name is long? I’d have to type nearly a dozen letters before getting there. No thanks. With buffer workflow, once you’ve found all your files, you only need to type a constant number of keystrokes to go to any file.

You may argue that you can just open all the relevant files in split windows or store them in your editor’s tabs, if your editor supports multiple tabs. Some editors also have a “recently opened files” section. Having multiple split windows will quickly crowd your screen real estate. Having multiple tabs sounds like an acceptable strategy, until you realize that if you have multiple tabs, it would take a long time to go to your target tab. You’d need to pause, browse through the list of tabs you have opened for that one file you want to open.

With Vim buffers, all your files are reachable, searchable, and you get the whole screen in front of you so you can focus on the most important task: coding.

Buffer Commands to Know

In addition to the :buffers and :buffer commands, here are more useful buffer commands:

:bnext
:bprev
:bfirst
:blast

:bnext and :bprev navigate to the next and previous buffer on the list, while :bfirst and :blast navigate to the first and last buffer on the list.

Another one of my favorite Vim plugins, unimpaired.vim offers intuitive shortcuts to traverse different file collections, like buffers.

With it, I can traverse the buffer list with ]b (:bnext), [b (:bprev), ]B (:blast), and [B (:bfirst). This allows me to traverse my buffer list very quickly. I call it sprinting because I can type ]b ]b ]b ]b rapidly and go across my buffer list at an olympian speed.

Vim Buffer Workflow Example

So what does a typical buffer workflow look like?

By the time I open Vim, I usually already know what task I need to do. Let’s say that I need to fix a particular UI bug. By then, I have a gut feeling for what or where the relevant method is. I would then search with either :grep, :find, :vimgrep or plugins like fzf.vim. Suppose my starting line is ui.js. From there, I follow the logic. Eventually, I have ui.jsx, uis_controller.rb and uis_controller_spec.rb opened in my buffer list.

My buffers now contain four files: ui.js, ui.jsx, uis_controller.rb and uis_controller_spec.rb.

From here, I can easily travel to any of these four files using a combination of flying (:Buffers + select one) and sprinting ([b ]b [B ]B).

Whenever I add a new file to my workflow task, that file is automatically added to the buffer list. Remember, Vim automatically adds an opened file into the buffer list, so I can immediately fly or sprint to it.

Why walk when you can sprint and fly?

Bufdo

As an added bonus, you can also run an operation across all buffers with :bufdo. You can pass an operation and apply it to all the buffer files.

If you want to substitute all “pancake” with “waffle” across all buffers, run:

:bufdo %s/pancake/waffle/g | update

s/pancake/waffle is the substitute command that replaces pancakes with waffles. Update saves each buffer file after substitution.

 

Vim Buffers vs. Argument List Explained

An alternative to the buffer workflow is the argument list (args/arglist/argslist) workflow. Before I go over what an args list is, I’m going to explain why you might want to also learn how to use :args.

Disadvantages of the Vim Buffers Workflow

After years of using the buffers workflow, I started noticing a friction. Over time, my buffer list would grow into an uncontrollably large list of files.

This usually happens when working on a complex task in which the file set that I need to work with is not clear. I’ve seen my buffer list grow to 50 files. It’s entirely plausible to have more than 100 files in the buffer list.

When you have that many files, it’s not a sprint anymore. It’s now a marathon. If you have that many files in your buffers list, many of them are probably irrelevant files.

There are a few things you can do. First, you can make a mental note of all the relevant files in your buffer list, then reopen Vim and open only the relevant files. However, I don't have a good short-term memory, so this isn’t ideal. Second, you can create a different, new set of files that you can still sprint across, yet distinct from buffers: the arglist files.

An arglist is a controlled file set. It’s a subset of the buffer list. Whereas Vim automatically adds all opened files into the buffer list, it doesn’t automatically add them into the arglist. You decide when and which file goes into the list.

Buffers are still awesome. 

It’s only when I am working with complex tasks that cause my buffer list to grow exponentially that I resort to the arglist workflow. When I know exactly which files I need to work with or if the size of my buffer list is manageable, the buffer workflow is always my immediate go-to partner.

Vim Arglist Explained

In the terminal, when you pass to the Vim command file(s) as arguments, like:

vim file1.rb file2.rb file3.rb

Vim opens them and stores them not only in the buffer list, but also the arglist. Recall that you can check all the buffer files with the :buffers command (or :ls). To check all the args files, you can run:

:args

On the bottom screen, Vim displays:

[file1.rb] file2.rb file3.rb

The enclosed file in a square bracket, [file1.rb], is the current args file.

Adding New Files to Args

If you open a new file file4.rb, your buffer list now has four items (file1 to file4). However, Vim doesn’t add it into the arglist automatically.You have to do it manually.

To add file4.rb into the arglist, use the :arga command:

:arga file4.rb

Running :args one more time reveals that the arglist now contains four files: file1.rb file2.rb file3.rb file4.rb.

If you need to remove or delete a file from the arglist, you can run the :argd command:

:argd file4.rb

To create a new arglist, you can run the :args command again, but this time you pass it file(s) arguments:

:args file1.js file2.js

The arglist now contains file1.js and file2.js instead of file1.rb, file2.rb and file3.rb. Running :args YOUR_FILES will overwrite your existing arglist. You have been warned!

If you run :args without arguments, it displays the arglist. If you run :args some_files, it starts a new args list with some_files.

Globs

The :args command accepts globs so you can quickly build up your args files. To recursively add all files ending with controller.rb:

:args **/*controller.rb

Args and the CLI Commands

You can combine most terminal search commands to populate the arglist, don’t forget the back-tick. For example, to integrate the classic find command with arglist:

:args `find . -name '*txt'`

Check out your arglist again (:args). Now, it has all the text files.

No-Fly Zone

With the buffer workflow, you can easily fly between the buffer files. Unfortunately with args, there is no way to fly between the args list.

Unlike the :buffers command that presents you a list of buffer files for you to fly into with :buffer BUFFER_NUMBER or :buffer FILE_NAME, there is no equivalent command with args.

Maybe in the future someone will make it possible to fly with args. But for now, we have to be content with sprinting.

Sprinting

Similar to buffer’s :bnext, :bprev, :bfirst and :blast commands, args have:

:next
:prev
:first
:last

The vim.unimpaired plugin also has useful commands: [a ]a [A ]A.

Multi-File Arguments

With :argdo, you can execute an operation across the arglist, similar to :bufdo.

If you want to substitute all method_a with method_b across your args files, run:

:argdo %s/method_a/method/b/g | update
A tutorial on how to work with buffers in Vim. | Video: Learn Linux TV

More on Software EngineeringTmux Config: A Guide

 

When to Use Vim Buffer vs. Args

Buffer list and arglist have their own use cases. Neither is superior to the other. When do you use a buffer list, and when do you use an arglist?

My rule of thumb is, whenever you start feeling the friction from having too many buffer files, it’s a good indicator to use args. Some people can tolerate having a lot of buffer files while some can’t even handle 10 buffer files. Whenever my buffer files ballooned to more than 10, smoke would start coming out of my ears. This would be a good time to use arglist. Otherwise, I would stick with buffers.

You can always purge your buffer list whenever it gets too large. In fact, I have two custom commands in my vimrc: One to delete all buffers, and one to delete specific buffer files. You can find them here in my dotfiles.

It is common to go into the detective mode, inspecting and opening a large number of files. You can quickly accumulate a large number of buffer files. The more files you open, the harder it is to clean up your buffer list. The argument list starts a fresh list of files, distinct from the buffer list. Once you know which files are relevant, just run :arga % to add the current file or :arga name/of/file to add to the argument list.

The buffer and args workflows are unique to Vim. If you aren’t already familiar with them, get acquainted with them. They may pragmatically change your editing workflow forever.

Even if you are not a Vim user, I think it is worth learning this, and who knows, maybe after reading about buffers and args, you may implement something similar in your favorite non-Vim editor or IDE.

Frequently Asked Questions

A buffer in Vim is a temporary space in the memory to store your opened files. Each time you open a file, Vim stores it in a buffer, stacking each file like a deck of cards, making it easier to navigate between files.

  • Vim Buffers: Buffers opens a temporary space in the memory to store opened files, stacking them like a deck of cards. It’s a useful workflow to swap between files when working on a project. But when the file size reaches 10 or more, it can become difficult to navigate, making arglist a more useful tool.
  • Arglist: An arglist is a controlled file set that’s a subset of the buffer list. You decide when and which file goes into the list, which makes it a useful tool to use when working on a project with 10 or more files. 
Explore Job Matches.