why is vim useful?

There is nothing intuitive or easy about learning vim. It's hard. It is every bit as cryptic and undecorated as a text editor could be.

Somehow though, nearly 20 years after its development, and nearly 35 years after its roots, in a world ruled by VisualStudio and Eclipse, vim is still relevant. It is maintained and developed by a thriving online community and it continues to be the work horse of many modern operating systems.

Why is that?

It is the opinion of this author that vim has something to offer that has not yet been matched by the more mouse-oriented text editors and development environments. Vim capitalizes on the fact that you can do more with ten fingers than one mouse pointer. If you're willing to put extra time in up front while learning vim, you will be more productive and effective in the long run. And that is what makes vim powerful.

the building blocks

If you haven't learned the basics about insert mode, command mode, etc., open up a command prompt and enter vimtutor. Come back to this article once you're done with that.

When you first look though this section it will probably seem very dull, but pay attention! These are the building blocks that lead to a productive, effective proficiency in vim.

  gettin' around  
CommandDescription
fx Move forward to the next occurrence of 'x' on the current line ('x' can be any character)
Fx Move backward to the next occurrence of 'x' on the current line
; Repeat the last movement command
w Move forward a word (EXTREMELY useful)
W Move forward to the next white-space delimited word
e Move forward to the end of the next word
b Move backward a word
B Move backward a white-space delimited word
gg Jump to the beginning of the file
G Jump to the end of the file
ma Bookmark the current cursor location as 'a' ('a' can be any character)
`a Jump to bookmark 'a'
`. Jump to the last place you entered text
`` Jump to the previous line you were at in the file
  inserting/editing text  
CommandDescription
I Insert text at the beginning of the current line
A Insert text at the end of the current line
o Add a new line below the current one and enter insert mode
O Add a new line above the current one and enter insert mode
>> Indent the current line one level
<< Un-indent the current line one level
== Auto-indent the current line. (not always possible, depending on what you're coding... i'm looking at you, python)
D Delete everything until the end of the line
C Delete everything until the end of the line and then enter insert mode (change it)
d{motion} Delete the text from the cursor to the point indicated by {motion}
c{motion} Delete the text from the cursor to the point indicated by {motion} and enter insert mode (I use this most frequently with 'w' to delte a word and change it to something else)
ci( Delete all of the text within the parenthases and enter insert mode (Brackets, braces, or any other character pair could be used instead)
ca( Delete all of the text within the parenthases inlcuding the parenthases themselves and enter insert mode
. Repeat the last insert command

Those last few can make for some interesting combos. If, for instance you have several places in your code with following conditional:

if (a < b) { ...

And you wanted to substitute it with this:

if (b < c) { ...

Search for the conditional:

/a < b

Change it to the new condition:

ci(b < c

Jump to the next instance of the original:

n

And repeat your last action:

.

This will all be very important when we get to macros...

  editing blocks of code  
As I mentioned previously, vim has several different modes, one of which is visual mode, which allows you to operate on a block of text. It is fairly intuitive to use this in the same way as a word processor, the only nuance is the manner in which the text is selected:
CommandDescription
v Enter standard visual mode
V Enter linewise visual mode
Control-v Enter blockwise visual mode

You can easily see how this works by trying it out yourself. Keep in mind that once you're in visual mode, vim sticks with the convention that y copies (yanks) the selection, d deletes the selection, and c deletes the selection and enters insert mode (changes it).

  dynamic edits  
CommandDescription
Control-a Increment the next number in the current line
Control-x Decrement the next number in the current line
gUw Make the rest of the word uppercase
guw Make the rest of the word lowercase

Notice that the 'w' in the uppercase/lowercase commands is a movement. The 'gU' tells vim that you want to capitalize something, and the 'w' tells vim how far you want to go. You could also use 'gU$' to capitalize until the end of the line, or highlight a block in visual mode, and press 'gU' to capitalize it.

the re-map

Any given developer has strong opinions about how things should work, however no two developers ever quite agree. This absolutely applies to work environments -- we all have our reasons, but at the end of the day, there's a specific way we want to do things. Vim acknowledges this disparity between preferences and reconciles it with the mighty re-map: any keystroke or combination of keystrokes can be re-mapped to anything else. When the user puts all of these mappings in the their ~/.vimrc file, the changes are automatically loaded at startup. Of course excessive re-mapping is ill-advised since they are non-standard configurations, so use them with caution.

Below is a short list of re-mappings I use which will hopefully serve to instruct and inspire.

noremap U <C-R>
control-r is the default 'redo' in vim. I find it annoying to be going through undo's, overshoot by one or two, and then have to change to control-r to redo, so I just re-mapped it to shift-u
nnoremap <silent> <Space> :silent noh<Bar>echo<CR>
vim will highlight search matches, and this is extremely helpful until you no longer need the search, at which point it becomes extremely annoying. This re-map allows you to clear the search highlighing simply by pressing the space bar.
cmap w!! w !sudo tee % >/dev/null
We've all been there... you make a bunch of edits to a file only to realize you need to be root to save them. When you find yourself in this situation, use this re-map by typing :w!! and you won't lose your edits.
map ,e :!bk edit%<Cr>:e!<Cr>
If you use BitKeeper or any other source control software with RCS roots you know it's handy to be able to check out a file as you're viewing it. This is the re-map that gets you there.
map ,e :!bk unedit%<Cr>:!bk get %<Cr>:e!<Cr>
Same as the above except for un-editing a file.

At this point you should stop reading. Spend a week applying each of these techniques to everything (code, e-mails, online forms, everything), and then come back to this tutorial. It's been dull and dry up to this point, but if you quit now vim will remain difficult and it will never be worth the trouble; it will never be powerful.

a robot in every vim...

Computers are great because they can do all of the little tedious things humans can't stand. Whenever you find yourself doing something over and over you need to stop and figure out how to get the computer to do it for you. Vim does this. Like a robot.

  macro commands  
CommandDescription
q{register} Start recording every keystroke into a register. Register names could be any character or number, so 'qa' will start recording to register 'a'
q If you're already recording a macro, pressing 'q' again will stop recording
@{register} Replay the macro recorded in the speicified register
@@ Replay the last macro that was replayed

If you did what you were supposed to and diligently internalized the previous sections, you're now equipped to do some vim trickery. Let's say you've got a C++ class with ten private member variables that all need getters and setters:

class Class { public: Class(); ~Class(); private: int m1, m2, m3, m4, m5, m6, m7, m8, m9, m10; };

With a little vim macro magic you can avoid carpal tunnel:

"but VisualStudio has tab completion!"

Vim likewise has tab completion... with a bit of hacking.

  macro commands  
CommandDescription
Control-p Complete the current word by searching backwards for the first match
Control-n Complete the current word by searching forward for the first match

If you're sharp you noticed that pressing tab doesn't complete anything, for that you need a re-map:

inoremap <tab> <C-P>

This can be limited since it only completes words in the file (and in the #indlucde'd files for C), but if that ends up being a problem, you may want to look into SuperTab.

editing multiple files

Any good editor has a way to edit multiple files, and vim provides numerous ways to do this. My favorite is split-windows, so that's what we'll discuss here.

  split-window commands  
CommandDescription
:sp [filename] Split the screen in half horizontally and open the specified file in the upper split, if no filename is specified, vim will just replicate the current file (Note that this is run in ex mode)
:vs [filename] Same as above except split the window vertically
Control-w j Move to the next split down
Control-w k Move to the next split up
Control-w _ Fill the screen with the current split, minimizing the others
I like to re-map those last three:
map <C-J> <C-W>j<C-W>_
Use control-j to move to the next split down and maximize it
map <C-K> <C-W>k<C-W>_
Use control-k to move to the next split up and maximize it

If you're using vim to edit a number of source code files, it would be extremely convenient to be able to jump to a function and drill down into heavily-nested code. Vim uses files generated by a program called ctags to accomplish this.

$ ctags my_file.c

Now you've got a file in your directory called 'tags', and when you open my_file.c in vim, you can use the following commands.

  tag commands  
CommandDescription
Control-[ Jump to the function implementation or variable definition of the word under your cursor
Control-t Go back to where you were before the last Control-[

In the real world you'll be working on projects that span multiple files in multiple directories. For this I would reccomend obtaining a copy of Exuberant Ctags. Say you have a directory structure that looks like this: - RootDirectory - LibDirectory - library_file1.h - library_file2.h - library_file3.h - AppDirectory - App1 - main.c - App2 - main.c - other_file.c - other_file.h You would go to the root directory and run ctags -R (for recursive), and open files from there: $ vim AppDirectory/App1/main.c This way you still have the benefit of being able to drill down into function calls, but without the hassle of an elaborate tagging system. Also note that ctags works with many more languages than just C.

plugins

Vim has a powerful plugin architecture, and plugins exist for everything under the sun (I've already mentioned SuperTab). I only use a couple of plugins, which are listed below, but there are many smart plugins for specific languages and frameworks that are also worth looking into.

  • The NERD Commenter - Comment any code with one easy command. This may also be accomplished with re-map's in your .vimrc (as you can see from mine below), but NERD Commenter is nice because once installed it's like syntax highlighting -- it just works.
  • Javascript Indentation - At first javascript looks like any other curly-brace language, but some of the language's flexibilities really throw vim's standard cindent for a loop. This plugin solves those issues.

a few powerful links

There's an incredible amount of information out there about vim, probably too much, but below are several links to get you going.