People ask me why on Earth would I subject myself to such dreadful text editor as vim. With it’s weird mode system, nonstandard keyboard shortcuts and all kinds of strange quirks it is not what you would call a user-friendly piece of software. Most users new to this particular editor hit a brick wall at step one: entering text. When you open vim and try to type, it will do strange things – like beep at you, or display some messages in the status bar. Unless of course you happen to hit a vovel like a or i or o, in which case it will suddenly come alive.
Years ago I have found this little illustration that perfectly describes learning difficulty curves for various common text editors:
In my experience this is 100% accurate. Vi and vim are just a bitch to learn to use properly. Unlike most editors you have used in your life, vim is modal. It has a bunch of modes that change the functionality of the keys, shortcuts and behavior. When you want to type something in, you put it in insert mode where it behaves mostly like what you would expect an editor to behave. If you want to move around the file, and issue commands you go into normal mode, and suddenly every single key on your keyboard has at least one or two powerful functions bound to it. This is probably my favorite illustration of just how complex vim is:
You can download full version of this sheet from here. This, by the way, is only a tip of the iceberg. Most keys have additional meanings in specific context. For example i means “enter insert mode” unless it is pressed immediately after another command in which case it usually stands for “internal”. But more on that later.
The point here is that while most editors bind few key commands (copy, paste, skip to the end of line) commands to key combinations (Ctrl+C, Ctrl+P) or control block keys (Home, End, PgUp, etc..) vim binds them to single key strokes, which can be chained in rapid succession. Vim is basically a unix shell for text editing – it gives you hundreds of small commands that can be scripted together to achieve daunting feats in small amounts of time.
Funny part is that the modality and complexity (which is at the same time the editor’s greatest flaw, and greatest strength) is mostly incidental. It is a product of the times when it was developed.
Here is an image that will probably tell you all you need to know about why vim is the way it is. Billy Joy wrote vi (vim’s predecessor) on a dumb terminal like this:
I shamelessly stole this image from Peteris Krumins’ blog, so full credit for finding this goes to him. But you can read his stuff later, now pay attention. I want you to look at the picture of the keyboard. See anything interesting?
No arrow keys. The designers of the ADM-3A terminal put the arrow keys on HJKL and forced modality onto their users. Billy Joy was using this thing, over a 300 baud connection which meant that every key stroke would take literal seconds to register. Think about that for a second.
Have you ever tried using a very, very crappy ssh connection that made editing files on the server a nightmare? It used to be like that all the time back in the day. Is it any surprise that vi was optimized to have incredibly powerful single stroke commands?
It turns out that the technological limitations of the time pushed Billy Joy into creating something brilliant – one of the most powerful text editing applications ever invented. One that is relevant now as much as it was relevant back in the day. The amount of power it puts at your fingertips is overwhelming. It lets you move around and manipulate text in ways you haven’t even considered before.
Let me give you an example – a simple use case by which you can gauge the value vim brings to the table. Let’s say you are coding something. Suddenly you realize you want to copy the current line and paste it directly below the first. How do you do this? Tell me your process step by step, and let’s count the keystrokes it takes to accomplish this. To be fair, let’s assume the cursor is already on the correct line, but somewhere in the middle of it.
If your first instinct is to take your paw of the keyboard and reach for a mouse, then you are what we in this business call a complete n00b. It’s a novice move. Taking your hand of the keyboard slows you the fuck down. In the time it takes you to locate the mouse cursor, highlight the paragraph I could probably retype the entire line from scratch. No seriously, time yourself one day and check it for yourself. If you are a semi-decent typist you can usually retype a line of code faster than you can mouse-copy it.
Power users and experienced coders will probably do something like this:
- Hit Home to skip to the beginning of the line
- Hold Shift and hit End to highlight the line
- Ctrl+C to copy
- Hit End again to de-highlight the line
- Hit Enter to insert a new line directly under the first
- Ctrl+V to paste
By my count that’s six key strokes, half of which are “chords” (two keys pressed simultaneously) and two motions requiring your right hand leave the home row to hit the Home and End keys on the control block. All in all not bad. Let’s see if a vim user can beat this score.
How do you copy and paste a line in vim?
- y y p
That’s it. Three key strokes, off the home row, executed by one hand in a single fluid motion, using no chords. I think it is a clear winner. That’s basically what vim does for you. It makes common operations quick easy and simple.
Ah, but who will remember these cryptic shortcuts? Well, they are not that cryptic. The character y stands for “yank” (a command akin to copying in regular editors). Repeating a command usually applies it to an entire line. So yy copies the current line. The letter p is of course for pasting, and by default vim pastes below the cursor (you could paste above by using upper case P). Not all that cryptic when you realize that most vim commands follow simple mnemonics.
Yan Pritzker apptly explained it like this: vim commands are like a language you can learn:
- There are verbs: c (change), d (delete), y (yank), p (paste), u (undo)
- There are nouns: w (word), s (sentence), p (paragraph), b (parenthetical block – something inside parentheses)
- There are some modifiers: i (inside), a (around), etc..
Eventually you learn to string these into sentences – here are some examples:
- change word: c w
- delete around sentence: d a s
- yank (copy) insides of a paragraph: y i p
- change text inside next quotation marks c i "
By the way, that last one can be issued from anywhere – it will jump to the first occurrence of a quotation mark, delete everything inside and put you in insert mode so you can type something in.
Some of the “nouns” only work when preceded by a modifier i or a. For example, you cannot say d s to delete a sentence. You must precede the s with one of the modifiers. Other “nouns” like w work without modifiers.
There are other useful commands that don’t follow this particular pattern but are stand alone and still easy to remember. For example J joins two lines together by concatenating the line below to the current. The t command followed by a character, moves the cursor forward ’till it finds that character. You can also open a new line with o.
You can string vim’s one-character commands to perform all kinds of different operations. And if you botch a command, you just hit u to undo the last change. It is an incredible amount of power at your fingertips.
But if that’s not enough, how about this: in Vim you can rebind any key. Any key in any mode – up to the point where the editor is rendered completely unusable. For example, I bound by F1 key to toggle the NerdTree plugin. Originally it opened the help documents in a new buffer, but never actually used it that way. But you are not limited to just single key – you can bind key combos.
Vim even gives you a freebie key you can use for binding your own combos – the leader key or \. For example, I have the following binding in my configuration:
nmap <silent> <leader><CR> i<CR><ESC>
What does this do? It is essentially reverse of J (join) command. It splits the line at the cursor. In most editors you accomplish it just by hitting enter. In vim, you usually have to enter insert mode (i), hit Enter, then hit Esc to go back to normal mode to continue issuing commands. This annoyed me so I reduced it to two keystrokes. I could have reduced it to one if I wanted to. Or I could extend this binding and make it skip to the end of the line upon successful split. Vim can be molded to your specific needs.
Hell, you can make vim behave like a “normal” text editor. Someone actually bundled that particular configuration and nicknamed it Cream. To me that’s kinda pointless though. It’s like buying a chainsaw, but never putting any fuel in. You lose half the power.
Need more convincing? Vim has macros. It lets you “record” keystrokes on the fly bind them to a key and then re-play them. Let me give you an example. Let’s say I give you a comma separated file like this:
jblack1, Jack Black tgreen1, Tom Green bwhite7, Bob White etc..
Let’s say it has 6,000 lines. I want it transformed into this:
<li><a href="http://example.com/~jblack1">Jack Black</a></li> <li><a href="http://example.com/~tgreen1">Tom Green</a></li> <li><a href="http://example.com/~bwhite7">Bob White</li> etc..
How do you do this quickly? Perl? Sed? Awk? All of that will require testing and fucking around. Optimistic estimate is that it will take you at least 10-15 minutes to write the script, and maybe another 5 to make sure it works for all the lines.
Me? I can do it in less than five minutes in vim? How? By using macros, and carefully choosing my editing commands to that they are generic and play off the common features on all the lines.
- Press q a to record keystrokes and bind them to “a”
- Hit I to enter insert mode at the start of the line
- Type in <li><a href=”http://example.com/~
- Hit Esc to go to normal mode
- Hit t , to put the cursor on the comma.
Since you know you are working with a csv, you can expect a comma followed by a space on every line. This will always work, regardless of the length of each username.
- Hit s to delete the comma and enter insert mode
- Type in “>
- Hit Del to remove the extra space to the right
- Hit Esc to go back to normal mode
- Hit capital A to skip to the end of the line and enter insert mode
- Type in: </a></li>
- Hit Esc
- Hit q to stop recording
I just taught vim how to do one line. I can now put the cursor on another line and hit @a to replay my macro, and boom – it will be turned into a link. Or better yet, I could type this in normal mode:
:2,$ norm @a
This basically tells vim “On lines 2 through $ (where $ means end of file) go to normal mode, and run the macro stored under a”. Wham, bam! We have the entire file done. And all I did was simply re-format the first line and then applied that template to the rest of the file.
Still not impressed? Geez, it’s hard to impress you, isn’t it.
There are plugins. Thousands of them. As I said – vim can be reconfigured quite easily. It is not as much that it has a plugin architecture and limited API (like Eclipse for example), as it has an scripting language (VimL) that lets you automate, redefine and hack everything – including changing standard behavior. Vim Plugin writers have been known to rip out neat functionality from other editors and transplant it into vim whether it makes sense or not. Plugins can make the editor do all kinds of crazy things:
- Fugitive – gives you git integration. For example you can do :Gblame from the editor to get a nice in-editor, two pane blame log.
- Syntastic will run your code through the compiler/interpreter in the background like an IDE
- SnipMate – gives you TextMate’s code snippets feature
There are many more – these just happen to be some of my favorites. There is a much bigger list in the forum.
Still not impressed? How about this: vi is ubiquitous. Vim is a superset of vi – so if you learn to use it well, you will also learn vi by extension. And vi is installed by default on just about any unix derived system out there. Chances are that one day you will have a web server of your own to maintain – maybe for work, maybe for fun, maybe for your startup that will change the landscape of social networking forever. That server will likely run a stripped down version of Unix, Linux or BSD. Why? Well, you want it to succeed, do you? Running windows on your production server is basically like aiming to fail. No, you will be a professional and you will be running unix-like system like big boys and girls do. Windows servers are what pointy haired MBA degree recipients straight out of school want to use – we are hackers. We are better than that.
Anyways, your unix like server will probably be running headless on some server rack. And you will manage it by ssh-ing to it. And you will likely configure it by editing text files using vi, because that’s what is going to be on the machine. Yes, you could install another editor on there – like Pico for example. But that’s just pathetic. You don’t want to be that guy. Do you know what Pico stands for? It’s an acronym for “Don’t Know How To Use Vi”. Besides, you can’t always rely on having root privileges and ability to install new software. And shared hosting companies will usually not be nice and install Pico for you.
The point is that if you know vi (you don’t have to be a pro at it, just know how to use it enough not to look like you are having a seizure at the keyboard) you can log into any Unix, Linux, BSD or Mac machine and fucking rock that shit like a pro. Your peers will be like “Woha, this guy knows his stuff!” and women will be totally like “I want to have his babies!”…
Ok, that last one was a lie. Vi skillz won’t get you anywhere with the ladies. Unless maybe with really awesome and cool geek ladies that can appreciate that sort of thing but that’s besides the point. The point is that vi is the most ubiquitously installed editor out there, and one most people don’t know how to use. If you do, that makes you more efficient than them. Which, is generally a good thing.
Still not impressed? You are an Emacs user, right? Listen I won’t convert you. Emacs is a whole different animal. I think it was Steve Yegge who said that Emacs is not a text editor. It is a feature full lisp based framework that can be used for text processing or writing text processors – or both at the same time. It is even more mutable and hack friendly than vim, and it’s internal language Elisp is actually more powerful (and more elegant, your stance on lisp parethesisis notwithstanding) than the ugliness that is VimL. If you are using Emacs, keep using it.
Hell, if you are using Java you should probably keep using Eclipse. Similarly you probably shouldn’t ditch Visual Studio and hack your C# code in vim. Emacs and IDE’s are useful – they have tools that will make your life easier. The IDE’s don’t have vim’s raw text manipulation power, but they make up for it by having great integrated debuggers, GUI building tools and etc. But if you are hacking in Perl, Python, PHP, Ruby or something like that, vim is usually a good choice.
Is it the best editor in the world? I don’t know. I guess it depends what you are doing. The bottom line is that you should choose a tool that fits the particular problem you are trying to solve. Not all problems are nails. If you try to apply a hammer to a philipsh-head you are probably gonna screw things up somewhere down the line. But vim is a great editor and you should definitely give it a chance. Especially if you have been discouraged by the steep learning curve before.