Git Gud at Vim 1: Buffers

October 16, 2018

This is part one of a four part series. To see all the articles, click here.

I’m doing a four part little workshop in Birmingham over lunch for some vim enthusiasts, and I thought I’d record my rough outline as a blog post for the rest of the internet.

I’ve been a user of vim for about ten years, and I’m still constantly learning new things that I didn’t know before… it’s a super fun tool. I got into it originally as a step in reducing the number of tools I used as part of work/school. I had eclipse for java homework, homesite+ for web development work, textmate for c homework… and my friend Tom had challenged me to learn one editor well. I chose vim, and I haven’t regretted it one bit. I can’t stop using it… it’s too powerful. It would be like giving up superpowers.

Vim was designed to edit text, which is what most of us spend a lot of our time doing. It is also installed on pretty much every *nix system out there, so if your job ever involves ssh'ing into a server (and it will!) vi will be there, so I think everyone should have at least a rudimentary knowledge.

Concepts

How vim thinks about files and buffers (from :help buffers):

buffers and windows
    Summary:
       A buffer is the in-memory text of a file.
       A window is a viewport on a buffer.
       A tab page is a collection of windows.
    

It’s worth briefly thinking about how totally different this is from most other text editors we use! Most of the time, we open files into tabs… and when we close that tab, the file is closed and we lose all the undo history, state… even unsaved changes. If we try to open the same text file twice, the application will usually present you with the same window on the file. A file in most editors is exactly the same as the view on the file.

Vim doesn’t think this way exactly. As you open files in vim using :e or by passing the filename as an argument when you start vim (vim foo.txt), those files are loaded in memory as Buffers. Usually, that file will also be presented to you in a single Window, which is where we work. We can split the current Window (using :vs or :sp) which without an argument will open a Window on the current Buffer… two views on the same file. You can of course look at multiple files in splits, but this is important: Multiple Windows, open on the same buffer. It’s a viewport, a literal Window on the Buffer, not the file itself like it is in Textmate. I can have one Window open on the top of a long .c file to look at the includes, and one Window 300 lines down the file looking at a particular function, both editing the same buffer.

Very powerful. But you may not realize it yet… Just hold those definitions in your mind as we go forward.

Commands

We are going to talk more about Command mode later, but for now, to enter a command you just type : while in Normal mode and start typing the command… tab completion works and all that just like your terminal.

:e

This lets you :e[dit] files… but it has a few tricks up it’s sleeve:

For instance, you can open .zip and other archive files, and see what’s inside!

Network capabilities… you can even edit over ftp and ssh using :e ftp:// and :e ssh://. (Vim has a powerful tool called netrw that powers all the reading, writing, browsing of files over network or locally.)Try :e http://tired.com/ to see the source code of a website. If you wonder if vim can open it or work over some connection… the answer is probably yes. :P

example of using vim :e with globbing
Here I’m using globbing to fuzzy find a path I never can remember…

One of the powerful things you can do with :e is you can use globbing to edit a file deep in a file structure. For instance, the last time I opened the firmware keymap for my keyboard, I used :e **/*fullmods/keymap* to open layouts/community/ortho_4x12/fullmods/keymap.c. Very powerful… and yes, it even works over :netrw, so you can use it over ftp!

:e has a lot hidden inside it thanks to vim’s handling of files and netrw, so if you are having difficulty moving through your project, do some reading. There’s probably a better way.

:ls

This lists your currently open buffers, along with some useful flags to let you know their current state (current buffer, modified, unmodified, read-only, etc.)

:b[uffer]

This lets you switch the window between open buffers… either by the number coming from :ls… or by a loose fuzzyfind string. :b css -> “style.css” if that’s a buffer you have open.

:bn[ext] and bp[revious]

If you want you can go back and forth between two files. I used to use these a lot to move between my open buffers, until I learned I can jump right to the buffer I want using :b, I use it still less since I use the jumplist which we’ll talk about in a later post.

:bd[elete]

This will unload a buffer and remove it from the buffer list. I mostly use this if I accidentally opened a lot of files trying to find the file I actually need to edit, and I want to avoid collisions when switching buffers using :b <pattern>. I’ll pass some patterns or buffer indexes to it to close the buffers I don’t want.

(Nearly) Everything is secretly a buffer…

using `q:` to access the command history buffer
Here, I’m using q: to access the command history buffer, then using reverse search (?) to find a previously run command and repeat it!

Why is it soooo important to understand the idea of Buffers vs. Windows vs. Tabs? Because so much of vim is actually a buffer in disguise. Your search history? Actually a buffer (you can see it using q/). Help system? It’s a buffer. The quickfix list that’s returned from a plugin? It’s a special buffer. Understanding what a buffer is and how to move and interact with it will help you interact with nearly every other part of vim.

Further Reading:

  • 2018-10-24 11:33:20 -0500

    Fix img with bad src

  • 2018-10-16 13:33:12 -0500

    Publish

  • 2018-10-15 15:22:44 -0500

    Add some corrections before the post

  • 2018-10-14 17:07:13 -0500

    Schedule the post out there for Tuesday