Why, oh WHY, do those #?@! nutheads use vi?

The VI Gang Sign

by Jon Beltran de Heredia, May 16th, 2007

Yes, even if you can't believe it, there are a lot fans of the 30-years-old vi editor (or its more recent, just-15-years-old, best clone & great improvement, vim).

No, they are not dinosaurs who don't want to catch up with the times - the community of vi users just keeps growing: myself, I only got started 2 years ago (after over 10 years of being a professional programmer). Friends of mine are converting today. Heck, most vi users were not even born when vi was written!

Yes, there are definite reasons why the vi/vim editing model is just superior to any other out there. And you don't need to be a Unix whiz to use it, either: vim is available for free for almost any platform out there, and there are plug-ins to get the functionality inside all major IDEs. Let's try to break a few misconceptions, and see some real examples of why it's the killerest:

Misconception #1: modal editing

The first time you stumble into vi or vim, you are shocked and disgusted that you have to use 'i' to start typing text. Can't remember which of hjkl moves in which direction. And you need to press 'a' if you want to insert after the last character of the line. Since you're already probably used to other editors, and if the arrow keys work in insert mode (they do if the system is configured properly, which is over 90% of the cases), you will stay in insert mode and not go back to normal mode except if absolutely necessary. You'll probably spend 20 minutes with it, and never go back. And also complaining: "How on earth am I going to remember whether I'm in insert or normal mode?"

Turns out, this is just a completely wrong way to use vi or vim. Using vi/vim properly, you don't use it modally. You are always in normal mode, and only enter insert mode for short bursts of typing text, after which you press <Esc> to go to normal mode. Thus, the remembering-the-mode problem just doesn't exist: you don't answer the phone in insert mode to get back to vi and not remember where you were. If you are typing text and the phone rings, you exit insert mode and then answer the phone. Or you press <Esc> when you come back. But you never think about insert mode as a mode where you stay.

Let me explain the philosophy behind this.

Commands in vi/vim are meant to be combined - 'd' means delete, 'e' means 'move to end of word', then 'de' is a complete command that deletes to the end of the current word (something like Ctrl-Shift-Right, Left, Del in most regular editors).

One good benefit of this is that the '.' command repeats the last complete, combined editing command (not movement commands). After doing 'dw', '.' will act as a command to delete to the beginning of the next word. You can move around at will with all the powerful navigation commands, and press '.' at will to delete to the next word quickly. This turns out to be incredibly powerful.

And now we come to insert commands. These commands enter insert mode and let you type text until you press <Esc>. Ok, in the case of these commands, the full command includes all the text you typed between 'i' (or whatever command you used to enter insert mode, as there are several) and <Esc>.

What this means is that if you type 'iHello<Esc>', which enters the text 'Hello' at the cursor's position, what now '.' does is "Type 'Hello' at the cursor's position". All of it. And you can understand that is pretty powerful. But it's better than this. 'A' goes to the end of the current line and enters insert mode there. So, after completing the insert by pressing <Esc>, you can press '.' anywhere to go to the end of the line and do the same thing.

One other even more powerful example: let's take the 'ce' command, which is composed of 'c' and 'e'. The 'c'hange command deletes the range specified by the next motion command, and also enters insert mode. It's the same as 'd', but with the distinction that it enters insert mode, instead of staying in normal mode. The boon is that the text you type in the next (short) input session is also part of the command. So if you do 'ceHello<Esc>>', what you do is replace from the cursor to the end of the word by 'Hello', and the '.' command afterwards will work exactly like that: replace up to the end of the word with 'Hello'.

Motions (cursor-moving commands) can also get more complex, and there are all sorts of insert-mode-entering commands ('o' to create a new line below, 'O' to enter one above, 'S' to delete to the end of line, etc... all of them entering insert mode afterwards) so you can imagine what type of powerful editing mini-ops you can build and repeat with simple '.'s!

Example #1: the wonderful dot command

Let's see a concrete example. Say you have declared three new functions in your header file, and you need to implement them in the module. You copy the following text and paste it into your implementation file:

All code starts like this, doesn't it?

Now you have to remove their semicolons, and adding an empty body would be a good idea. With the cursor as above, you can use 'A' to go straight into insert mode at the end of the line:

After 'A' - see the insert mode cursor (vertical line) at the end

Now you delete the semicolon with <backspace>:

Deleting is simple

And type <return> { <return> } <return> to insert the body:

Inserting too, as in any other editor

And finally, type <Esc> to return to normal mode:

And now, quickly!, we return to normal mode

And now you have to repeat this with the other two. How do you do it? Easy: first, press 'j' to move the cursor down. And then, press '.' to repeat the last full editing command (the 'A' command with the backspace and the inserted text). If you do 'j.j.', that is, twice, you get the following:

Just j.j. to do this!

The vi command architecture was key here, together with the fact that <backspace> is as part of the editing sequence as regular typing, and the editing operations being pretty repetitive. But think about it, how much of your daily editing is repetitive? Yeah, I thought so.

Misconception #2: it's not all about regular expressions

Vi/vim is pretty powerful handling regular expressions. All half-serious editors have regular expression support for searching, replacing, etc, but only vi (that I know) can use them in highly complex ways, such as doing a certain regex search and replace in the second occurrence of 'begin' after lines that contain 'proc', or whatever you think up.

So this is not to demean the power of regexes, or the vi/vim regex-using power. But the main power of vi, and the power that you can't live without after you've got used to it, is the power of the basic editing model:

  • One- or two-key motions to move directly anywhere on the line, or on the screen
  • Operators such as 'd' or 'c' that can be combined with any motion to directly modify some text and maybe enter insert mode, and being able to repeat it all as many times as you wish with '.'
  • Anything can be done without moving your hands away from home row! No more suffering when editing on a laptop with a braindead keyboard layout (most of them)

Example #2: smart ranges

Let's see the following typical example. It's just a function call embedded in a somewhat complex expression:

Complex expression and function call

As you see, we have the cursor positioned at the start of the call. Now imagine that we want to extract this and assign it to a local variable. The first part is selecting the relevant call, then copying and deleting it to move above, typing the var name, and moving above to type the declaration. In regular editing models, you will play hunt-and-peck with Ctrl-Right and left/right until you get it exactly right. Not with vi or vim. The '%' motion moves from a parenthesis (or similar grouping character) to its matching one - but if you're not positioned at one of these special characters, it will scan character by character to the right, until the first one is found, and then moving to the character matching that one. So, in the above situation, it will move to the right closing parenthesis!

Knowing about the 'c' command, which deletes the extents of the next motion (also copying it to the clipboard) and enters insert mode, we can type just 'c%' ("change match") from the above case and we get the following:

After just 'c%' ("change match")

The relevant call has gone to the clipboard, and we're also ready to type the name of the variable. Not bad for just two keystrokes! After typing the variable name and pressing <Esc> to go back to normal mode, it will look like this:

Typing and <Esc>

Now in normal mode, you can type 'O' to open a new line above the current one and enter insert mode, and start typing the declaration:

Just pressed 'O' and typed the start of the declaration

And now, when we have to insert the previous expression, since we have it in the clipboard, we can use Ctrl-R, " to paste it in insert mode (admittedly a bit unintuitive to remember, but it's the key to simple multiple-clipboard support). This will bring in the function call we deleted at the previous point. So Ctrl-R, ", we type a semicolon, and <Esc> to get back to insert mode gest us here:

Finished!

Misconception #3: you gotta be nuts and/or a genius to use it

Well, I hope that with the above explanations and examples, you have already seen some of the power that vi/vim provides. Learning it is tough (see below), but if you're going to be editing code 8 hours or more a day for years, it's the second best investment after learning touch typing (which you already know, right? If not, don't bother with vi, learn that first). A learning curve of weeks make sense for such a lifetime investment. And, at least, you won't have a dumb assistant to annoy you to death.

The point is, with vi, your keyboard becomes a huge specialized text-editing gamepad with almost a hundred buttons. Each of them has at least two functions, shifted and unshifted, so you have almost two hundred functions at a single keypress (not counting Shift). Commands are incredibly powerful for text editing, and you can even combine them to obtain the best results. While typing some text, it is a regular keyboard, but when you're back to normal mode you have the best-designed text-editing machine there is, and it shows.

Example #3: manipulating delimited blocks

One other simple example. This one only works with vim (uses one of vim's specific motions). Say you are inside an angle-bracketed section, as is so common in these days of XML:

Life at an XML tag...

How do you select the text inside for copying/deleting/modifying it? In regular editors, once again, you have to move your hands off their current, comfortable position, and go for the arrow keys or, even worse, the mouse. Any of those is probably a pain, especially when working on a laptop. How do you do it in vim? You just use one of the text-object motions, which all start with 'i' or 'a' (they can only be used after an operator like 'd' or 'c'). 'i>' refers to "the current 'i'nner angle bracket block", so you can do 'di>' ("delete inner angle-block") to just delete all the contents from the above situation:

After typing di> ("delete inner angle-block")

You can use '(' or ')' for the current parenthesized block (or even 'b' from 'b'lock), '[' or ']', '{' or '}', 'w' for punctuation-delimited-word, or 'W' for the current space-delimited word, prepending 'i' to any of them for the 'inside' contents, or 'a' to include the delimiting characters too.

Misconception #4: hjkl to move around?

Many people find it weird to use hjkl instead of arrow keys for moving around. The actual reason for this implementation seems to be that terminals of the time didn't reliably have arrow keys, and that this terminal in particular had hjkl keys doubling as cursor keys. But the side effect is that you don't need to move your hands off the home row to move around, which is great.

But in any case, although you will use hjkl to move around at first, once you master vi/vim you probably won't use 'h' and 'l' ('left' and 'right') at all, and you will use 'j' and 'k' sparingly. Why is that? Because there are other, more powerful motions, that will often get you where you want to go much faster. When moving inside a line, I find that there is always a motion to take me straight to where I want to go, so I use those motions: 'f' followed by any other character to find its next occurrence, '%' to use matching parens to go where you want to go, etc... When navigating the file, you have motions to go to the top/middle/bottom of the screen directly, '/' which is effortless to type to search for a string, ']]' and the likes to navigate by functions, etc.

Example #4: nice commands

Some commands are just so useful that you would miss them if you knew them. 'H', 'M' and 'L' take the cursor directly to the 'H'ighest, 'M'iddle, or 'L'ower line on the screen. 'zt', 'zz' and 'zb' keep the cursor at the current position, but scroll the view so that it falls at the 't'op, 'z' center, or 'b'ottom of the screen. '*' searches forward for the next occurrence of the word under the cursor ('#' does the same backwards, at symmetrical positions so its easier to remember). And there are dozens more...

Misconception #5: since you are thinking 90% of the time, and editing 10%, the productivity gain might be there, but it's useless anyway

Well, those are exaggerated figures, but this fact is often mentioned against any editing gains being important to development productivity. I'll wager that this is wrong.

First thing, in the chances where I really have to think a problem, and there is no need to look at code, I pick my bike and go for a one hour ride. Or a two hour ride. At least if the weather is good. It's much nicer than staying in front of the computer.

Also, when I have to analyze some hard problem and design a solution, I often bring out a notebook (a real notebook, made of paper with cardboard covers and bound with a spiral), and a pen, and try to clarify my thoughts there.

You can bet that, with a few exceptions, productive work can't be done away from the computer. This is because, most of the time, you have to look at the code to think and design. And this involves navigating the code with an editor. And also, very often, you *are* indeed typing or editing continuously. You maybe just think for 1 minute, but then you spend one other full minute editing the changes you just thought about. And when you are editing, you want to have the best damn tool for the job.

Comfortable editing helps you stay in "the zone", the state of concentration that gets you the maximum productivity. As you master a powerful tool such as an editor, it just disappears from your conscious, and you are free to concentrate in the problem, and your editing happens unconsciously. Regular editing makes you hunt-and-peck, use Ctrl-Right, Ctrl-Right, Ctrl-Right, Ctrl-Right, Ctrl-Right to get to where you want to go, it makes you move your hand to your mouse, open a menu, select an option, enter stuff into a dialog and click 'Ok' to accept it. In vi/vim most stuff is a surprisingly small number of keystrokes away, in a direct fashion.

Other vi users have also shared this with me, so I know I'm not alone in the feeling: once you start to master vi, there are times in which, after finishing a 30-second-long full-steam editing session, you kind of 'wake-up' to a faint memory of the sound of a continuous stream of keystrokes. It feels like you have been hearing them in the back of your head while you were dicing and slicing lines of text, blocks, motions and modifications. And this during this period of editing, you are feeling a tremendous sensation of power.

Example #5: indenting a block

Vi and vim know your code has some structure. Many of the commands reflect this. Say 'aB', as described in example #3 above: it selects the current '{' and '}' delimited block, including the braces themselves ('a}' does the same). And let's take it and combine with the '>' operator, a useful operator that indents the region indicated by the next motion. Picture the following code:

Improperly indented

How often do you encounter such a case? Yes, you can paste with auto-reindent (just ']p' in vim), but often you forget to, or you reach this case not because of pasting the block, but because you added or removed stuff above. You just have to indent it a bit, and you'll be done. In other editors, you move around, you select, you type TAB or the shortcut to auto-indent. Not so with vim, just three keystrokes: '>aB' ("indent a Block") and you get this:

We didn't even have to move the cursor!

How cool is that? You didn't move or select, you just told it directly what you wanted to do, and it did it. I believe it's this type of "straight" editing that gives you the feeling of power and helps you enter and stay in "the zone".

Misconception #6: it's just sticking to a disappearing past

Vi has been around for 30 years, and it's still there. Vim, a full-vi-clone which introduces even more improvements than vi has features, has been alive and kicking for 15 years, available for free on almost every single platform on earth. People who love vi have found a way to use it everywhere: there is a plug-in to get vi emulation in Eclipse, a plug-in to get vi emulation in many Mac OS X apps, a plug-in to add vi emulation to IntelliJ IDEA, even Emacs has not one, but several built-in vi emulators (when I end up tinkering lisp code in emacs, I start by trying to use emacs keybindings, and always end up typing "M-x viper-mode"), I develop and sell ViEmu, a family of plug-ins to get vi/vim emulation in Visual Studio, SQL Server, Word and Outlook, Paul Graham still uses it for his lisp and arc hacking, Tim O'Reilly is a confessed vi-er, SlickEdit and Crisp have vi emulation...

Of course, the vi/vim community is not a majority: most computer users are not even touch-typists, and vi adds yet another steep learning curve. Those who have seen the light, though, won't go back to other, poorer, editing systems - so vi/vim editing is guaranteed to survive for many years to come. Actually, using vi(m) keybindings is probably the closest you can get to ensure you have it available in any environment you are or will be in the future, from old Unix systems to the latest popular IDE.

Example #6: visual nature

And as a final example, even if it seems vi is just about cryptic and unreadable commands, we are going to see some of the more visual aspects (actually, they are vim features, rather than vi original ones). One of them: with 'hlsearch' enabled (off by default in vim, but easily enabled with ":set hlsearch"), when you search for a string, all its matches are highlighted on the screen. Say you have the following html code:

Some html source

If you press '*', the word under the cursor ('div') is searched for. It results in this:

Powerful asterisk!

As you see, the cursor has moved, and the different occurrences are conveniently highlighted.

Let's see some more. We've seen operators like 'd' and 'c' act upon the region given by the next command. Well, if we want visual feedback, we can use visual mode: press 'v', move around while you see the region from the initial point highlighted, and then press the operator directly to see its effect. Search commands work here as well. If you use 'V' instead of 'v', highlighting will be done by lines. Let's press 'V' and then 'k' (up) after the above:

After Vk ("visual-lines, up")

As you see, the two lines are highlighted as selected. Say we want to select until the closing div tag (the search highlight shows it). Type 'N' (previous match), and we get the following:

After 'N' ("previous-match")

And now we can do whatever we want, say, the 'gU' operator to make everything upper-case (and return to normal mode):

Lovely upper case

And now, let's just go for a correct common 'conception' about vi/vim:

Correct-conception #1: steep learning curve

There is one thing which is a commonly held piece of knowledge, and which is true as well. It is shown on this page to the best effect. It's the fact that learning vi/vim is an activity that will take a long time (weeks to months), and that the first experience is not pleasant. I take it this is the main reason why vi/vim editing isn't, and will never be, a popular thing. You need to invest quite some effort to learn, memorize, and internalize the 30 or so commands that start making you more productive than with other editors. Since they're all arbitrary one-key commands (although all of them have some easy mnemonic to aid in remembering them, and even some form of coherence), this is not an easy task. It's easy to throw in the towel and go back to familiar jedit or pico, ultraedit or textmate, or even emacs. But once the effort to learn it has been made, I know of no one who goes back. And I know dozens of people that have told me that they've been using 'vi' for over 10 years, and that they're accustomed to and expecting even the smallest details.

Closing words

Do whatever you want. Don't learn it if you feel it's too much effort just for nothing. Learn emacs instead. Or stay in your IDE using a lousy editor. Whatever. But in any case, don't ever claim again that those 'vi guys are nutheads' - I hope that I have succeeded in showing you why they (we) stick to it, and you should at least be able to understand its power, even if you prefer to stay away from it.

If you want to research vi/vim editing some more, here are some useful references:

And of course:

(Special thanks to Ivan Vecerina, Andrey Butov, Jose Gonzalvo, Mark Petrik Sosa, Aitor Garay and Woody Thrower for commenting on early drafts of this article)

(All captures taken from Visual Studio with ViEmu, my (commercial) vi emulator, and with codekana, my upcoming product, providing the enhanced syntax highlighting)


You can comment the article at my blog