Blog Archives

Piping Into Vim (and I/O Tidbits)

The Vim-related portion of this post is actually very small. In fact, it can be summed up in a single sentence: you can take the output of a pipe and place it into Vim for editing, without needing to use an intermediate file, by piping it to vim - (yes, the dash is significant). For example, grep foo bar.txt | vim - will grab all of the lines from bar.txt which contain “foo” and place them into a Vim buffer for editing.

If you look in the Vim manpage, you’ll see this functionality described as such:

The file to edit is read from stdin. Commands are read from stderr, which should be a tty.

At first glance, this might seem odd – the way many people think about the stdin, stdout, and stderr, it wouldn’t make much sense to “read” from something associated with “error output”.

The reality, however, is that all of these are merely pointers to devices. The devices themselves may support reading, writing, or both. In fact, for your normal interactive shell session, all 3 of the “standard” IO pointers all point to the same device. That device represents the terminal interface you’re using.

Note that this is a different concept of ‘device’ from that of hardware devices (e.g. keyboard, mouse, screen) – as far as command line I/O is concerned, “devices” are just things that can have data read from and/or written to them. For instance, an SSH session creates a virtual terminal device on the machine to which you connect, that proxies its input and output via your connection to the machine.

Once you understand this, the concept of “reading from stderr” makes a lot more sense – you’re not actually “reading from your output” but rather “reading from the same device that error output goes to by default”. Since stderr is typically output to your terminal, even if you redirect stdout (say, to a file), getting your input from stderr is a convenient way of accepting keyboard input from the terminal when stdin is being used by something else – in this case, from the pipe that’s filling the buffer with content for you to edit.

Embracing Vim, Step by Step

I’ve used Vim as my primary editor for years now after having mostly picked it up in college as a convenient editor for working on school servers. Having a lightweight editor that I was pretty much guaranteed to find already installed on any machine I happened to acquire SSH access to was what originally got me into using it; the speed and efficiency benefits were merely a nice side benefit.

As such, my first few years using Vim didn’t involve harnessing much of its power – I essentially used it at first like a version of pico that happened to have some use commands that were accessible by pressing Esc. (If you’re a Vim user, I can feel you cringing. I am too.) As the amount of time I spend coding has increased (from starting out as a hobbyist, somewhat time-starved college student to working full-time as a software engineer), however, I’ve slowly begun picking up more and more Vim tricks of the trade.

Along the way, plenty of people have suggested various books or tutorials or other such massive collections of Vim knowledge, but so far my experience has been that very little of that tends to stick. If I try to learn a giant chunk of Vim features all at once, none of them really have the chance to become a habit, ingrained in my usage patterns. As a result (and due to the perfectly reasonable terseness of the average Vim instruction), they tend to just sort of fade away.

Instead, I’ve adopted a slower but steadier pace when it comes to learning new Vim shortcuts. First, I find a handful of related commands that are both useful and relevant to something I’m doing. I then focus on integrating those commands into my daily usage. Once they become something I do out of habit rather than conscious recollection, I move on to another set. I’ve found this approach much more successful in changing my long-term usage habits, which in turn has made my overall editing experience much more enjoyable.

As an example, the most recent set of commands I’ve decided to work on incorporating are related to visual mode:

  • v% – select text from current side of a matching pair to the other side (for instance, from one parens to a matching parens)
  • vib – select all text from the parens block the cursor is currently in
  • vi' or vi" – select the entire quoted string the cursor is currently in (depending on which quotes are used)
  • viB or vi{ – select an entire curly-brace-enclosed block
  • The a variants of these (using a instead of i includes the surrounding markers, e.g. quote marks).

These particular commands are nicely demonstrated in this StackOverflow answer, including animated gifs to show the results. I’m almost certain I’ve run across these commands along with many others when perusing larger collections of Vim shortcuts before, but because I wasn’t focusing on them, they were lost in the noise. Time to fix that.

As I move on to other Vim shortcuts, you may find me writing other posts detailing each of them in turn. What you probably won’t see is a giant blog post summarizing every Vim shortcut I’ve ever learned. There are already enough monolithic guides out there.