DEV Community

Igor Irianto
Igor Irianto

Posted on • Updated on

Using buffers, windows, and tabs efficiently in Vim

Follow @learnvim for more Vim tips and tricks!

Vim has never been like most editors. I've used different editors (Notepad++, Atom, VSCode, and yes, emacs, briefly). Most editors use tabs and windows system. Vim has buffers, windows, and tabs. Some of these abstractions Vim use are different.

If you are new to Vim, I will explain what buffers, windows, and tabs are. I will also show how to use them efficiently.

Table of Contents:

Before we start, if you haven't, add set hidden in your ~/.vimrc and source it. Without this option, whenever a changed buffer goes to "hidden", Vim will prompt you to save the file. For more information about this setting, check out this article and :h hidden.

Vim buffers

A buffer is the in-memory text of a file.

When you open a file in Vim, it creates a new buffer. Do this from your terminal:

vim file1.js
Enter fullscreen mode Exit fullscreen mode

Buffer Vim File 1

After running this, Vim creates one buffer for file1.js. This buffer is stored in-memory.

Exit Vim. Back to console, run:

vim file1.js file2.js
Enter fullscreen mode Exit fullscreen mode

Vim creates 2 buffers: one for file1.js and one for file2.js. You are probably still seeing file1.js.

Buffer file 1 2

However, right now Vim has 2 buffers. You can see all buffers with :ls (or :buffers, or :files).

Buffer File 1 2 ls

There are several ways to go between file1.js buffer and file2.js buffer:

  1. :bnext to go to next buffer (:bprev to go back)
  2. :buffer, then type the name. Vim can autocomplete with <Tab>
  3. :bufferN where N is buffer number. :buffer2 for example, will jump to buffer #2.
  4. Jump between your last 'position' with <Ctrl-O> and <Ctrl-i>. This is not buffer specific, but it works.
  5. Toggle between previous file with <Ctrl-^>

For method #2, you can combine buffers list with buffer name. For example, with this mapping, pressing <Leader>b will display my buffers and types :buffer<space> command. All that is left for me to do is typing the buffer number or buffer name (that Vim can autocomplete).

:nnoremap <Leader>b :buffers<CR>:buffer<Space>
Enter fullscreen mode Exit fullscreen mode

Vim buffer shortcut Leader b

Once a buffer is opened, it remains in your buffers list. We have two buffers opened: file1.js and file1.js buffers. Still in the same vim session, if we want to open a new file, we can do :e file3.js. If we check with :ls, we'll see that we have 3 buffers.

Buffer Vim file 1 2 3 ls

You can type :bdelete to close a buffer. To be honest, in my years of editing with Vim, I almost never needed to delete buffers.

The way I see it, buffer is like Z axis in X-Y-Z coordinate. Imagine X axis to right, Y axis to top, and Z axis towards screen. Your buffers files are lined up in the Z axis. You can traverse the Z axis one file at a time with :bnext/:bprev. You can jump to any coordinate in Z axis with :buffer <filename>. The number of file buffers you have is how long your Z axis is. Vim makes it almost frictionless to travel anywhere along this Z axis.

Vim buffer z axis analogy

Vim windows

A window is a viewport on a buffer. In Vim, you can have multiple windows opened.

From your console, run this again:

vim file1.js
Enter fullscreen mode Exit fullscreen mode

Buffer Vim File 1

What you are looking at the screen is one window that displays buffer file1.js. Window is what you are seeing buffers through.

Exit Vim. In console, run

vim file1.js file2.js
Enter fullscreen mode Exit fullscreen mode

Buffer file 1 2

We've seen this many times now. This time, we have two buffers and still one window.

Don't quit vim yet. Run:

:split file2.js
Enter fullscreen mode Exit fullscreen mode

Window Vim two windows

You are looking at two windows. It's kind of hard to see the texts on bottom window, but the bottom one says file1.js (and top one file2.js). The top window is a viewport for buffer file2.js, the bottom window is a viewport for buffer file1.js.

Remain in this vim session - don't quit yet. Run:

:vsplit file3.js
Enter fullscreen mode Exit fullscreen mode

Window Vim file3 file2 file1

You are now seeing three windows. Top left window displays file3.js buffer. Top right window displays file2.js buffer. Bottom window displays file1.js.

I hope you are starting to see the difference between vim buffers and windows. Don't worry if you aren't - take your time. It took me a while to understand it when I was learning this.

You can have multiple windows displaying one buffer. Right now I am still on top left window that views file3.js buffer. I will type:

:buffer 2
Enter fullscreen mode Exit fullscreen mode

Window Vim file2 file2 file1

Now both top left and top right windows are displaying file2.js buffer (bottom window still displays file1.js buffer). If I start typing on top left, you'll see that both top left and top right window are changing as I type.

Window typing multiple buffers

To close current window, you can run <Ctrl-W>+C. Alternatively, you can do :quit. When you close a window, a buffer will still be opened (check :ls).

Some useful shortcuts for window:

<Ctrl-W>+v       # Opens a new vertical split
<Ctrl-W>+s       # Opens a new horizontal split
<Ctrl-W>+c       # Closes a window
<Ctrl-W>+o       # Makes current window the only one on screen and closes other windows
<Ctrl-W>+h/j/k/l # Moves the cursor to left/bottom/top/right
Enter fullscreen mode Exit fullscreen mode

Some useful Ex commands:

:vsplit <filename>     # Split window vertically
:split <filename>      # Split window horiontally
:new [filename]        # Create new window
Enter fullscreen mode Exit fullscreen mode

For more, check out :h window.

Vim tabs

A tab page is a collection of windows. In Vim, a tab has different meaning than most text editors. In most text editors (and modern browsers), a tab usually means an open file/ page. When we close it, that file/page goes away.

In Vim, a tab does not represent an open file. We just learned that vim saves opened files in buffers. When we close a tab in vim, the files in that tab are still stored in buffers. A tab can have one or many windows. Think of tabs like layouts or templates.

Let's try it. In console:

vim file1.js
Enter fullscreen mode Exit fullscreen mode

Let's open file2.js in new tab:

:tabnew file2.js
Enter fullscreen mode Exit fullscreen mode

Vim tabs

More tabs navigation:

:tabnew file.txt # open file.txt in a new tab
:tabclose        # Close current tab
:tabnext         # Go to next tab
:tabprevious     # Go to previous tab
:tablast         # Go to last tab
:tabfirst        # Go to first tab
Enter fullscreen mode Exit fullscreen mode

You can also run gt to go to next tab page in Normal mode.

To start vim with multiple tabs, you can do this from console:

vim -p file1.js file2.js file3.js
Enter fullscreen mode Exit fullscreen mode

Thinking in 3D

Moving between windows in Vim is like traveling along X-Y axis in cartesian coordinate. We are moving two-dimensionally. We can move to top, right, bottom, left with <Ctrl-W>+h/j/k/l.

Earlier I said that Vim buffers are like Z axis. Inside each window, you can move along the Z axis with buffer navigation. When we combine window movement with buffer traversal, we are moving in three-dimensional space.

Vim window-buffer in 3d

Each window can view any of our buffers.

Vim 3 windows as viewport to buffers

This X-Y-Z movement is possible thanks to Vim's window and buffer features.

Using buffers, windows, and tabs efficiently

To learn how to use buffers, windows, and tabs efficiently is to understand what they are designed to do.

Use buffers to open up all required files to get current task done. It may be eight or eighty buffer files. Having many buffers opened doesn't effect spatial distribution. Vim has designed switching file buffers to be frictionless. Use that to fly between buffers.

Use windows when you need to view multiple buffers. Like when diffing files, referencing codes, or following code flows.

Use tabs when working on different projects. Like one tab for server codes and one tab for client codes.

In most code editors there are 2 abstractions in their workflows: windows (ex: split screen) and tabs. In Vim there are 3: buffers, windows, and tabs. When I started using Vim full-time, it required a significant paradigm shift. My personal suggestion is to take your time to use it the way they were designed first. If after you've tried it and you still don't think it's for you, use the process that suits you most.

In addition, you can look at plugins such as ctrlp.vim or fzf.vim to boost your workflows.

Ultimately, do what works for you. Just because a certain feature was designed to for X doesn't mean everyone should do X. Feel free to experiment around and find your best workflow.

This is a good place to stop. Thank you for reading. Happy coding!


Top comments (12)

gurdeepgss profile image
thicckWire • Edited

Is there any way we can have buffers containerized in tabs.

I mean suppose I open 3 buffers in vim.
then I create a new tab and open 3 completely new buffers in that tab.
Now if I :ls it shows all the buffers, the behaviour that I expect or think-of-as-better-one is that if I :ls in second tab, only buffers opened in that tab are shown.
And first tab buffers are only shown for the first tab on :ls.

Though it should be configurable, if one want to access buffers from the first tab then some variant of :ls or some other command should give me all the buffers so that I can use vim's default behaviour.

what do you guys think of it?
Should it be this way, as I described or should this be left to tmux+new-vim-instance?

iggredible profile image
Igor Irianto

I never thought of containerizing buffer in tabs before, but that's a good point. I personally don't use Vim tabs. I may have multiple Vim instances in different Tmux windows, so they are automatically containerized.

I think it comes down to a design decision. The people who wrote Vim (Bram etc) probably decided that buffers are shared objects instead of tab-specific objects. It could've gone either way haha.

Again, this is a really good point that you brought up!

konfekt profile image

vim-ctrlspace is a plug-in to containerize buffers in tabs.

Thread Thread
gurdeepgss profile image

Will look into that.

gurdeepgss profile image

from a users perspective I think this should be configurable, for the folks who do not have tmux available (like I on my employer's windows machine).

Or I think we could make a plugin that does this somehow. I don't know the details of it, but I think it might be possible.

khalidwilliams profile image
Khalid Williams

Super helpful -- thank you!

nickfun profile image
Nick F

This was useful. Getting familiar with the terms really helped me back when I was using Emacs. Now I'm learning VIM and this is a good reference.

iggredible profile image
Igor Irianto

Thanks Nick! Appreciate it. If you find how I can present my article better, please feel free to put it in comment :)
Any feedback will be highly coveted.

timabell profile image
Tim Abell

Use of ctrl-p with fzf to switch buffers/tabs/files is a superb tip, I'd forgotten I had that set up. So much easier & faster than :tabn etc.

alexgnatrow profile image
Alex Row

Nice! Looks like it was kind of article I needed so much.
Super helpful! Thank you.

axl989 profile image
Sergio Olivieri

I still don't get it. What's the practical usage of buffers?

rafaelbdb profile image
Borjovsky • Edited

This is one of the best explanations I've ever seen about anything (not only VIM resources)!! The X/Y/Z axis thinking makes everything soooooo much cleaner!