...making Linux just a little more fun!

A Slightly Advanced Introduction to Vim

By Pranesh Srinivasan

What is it?

        "It is the little things that make up great men." 

This introduction is about the little things. Things that help ease everyday tasks but go a long way into making you a better user, editor, programmer - a better computer user.

This piece started out as a 'write-while-you-learn' exercise while reading a vim tutorial. As I kept writing, I felt that with a little more work, and some polishing, this could be turned into vim introduction of sorts.

Who is it for?

This is not a five minute introduction to vim for a complete newbie. I presume you have used vim before and are comfortable with moving around, and making changes. Although :vimtutor is not a prerequisite to this tutorial, I highly recommend it.

This document contains some mnemonics, and some slightly advanced features of vim that can help the average vim user/programmer increase his/her productivity by leaps and bounds.

Why does it exist?

I find a large number of people around me who have used vim a few times while writing programs. Very few of them have grown into becoming effective vim users. The majority drop out because of its initially daunting interface. A good number of the interested users switch to emacs, because they think the 'power' just isn't there with vim. I am not saying emacs is bad, but I just cannot stand decisions made on lack of information.

This document is written with an aim to convert the odd "I-just-use-vim-over-ssh" user to a full-fledged user, and to illustrate the kind of power that vim provides.

Most importantly, vim is not just for programmers; it can be used by anybody and everybody who deals with text in any form. Vim runs on many platforms including Mac, Windows, and Solaris, and is a standard on every Linux machine. Someday you might find yourself sitting on a terminal with only vim installed.

Some Notation

Any command mentioned here is to be typed in the normal mode. The normal mode is the mode one gets when he/she presses <Esc> in vim. There are three main modes in vim: insert, normal and visual (vim documentation says there are six BASIC and five Additional modes...)

Commands are generally indented with respect to the rest of the text. Any command prefixed by a ":" is also to be typed in the normal mode, with the colon. Of course they have to be suffixed by an 'Enter' or carriage return.

In cases where a command has to be typed in the visual mode, it will be mentioned explicitly.

The commands described here should work with any recent version of vim, or gvim. I used vim 7.0 for this, and some features like omni-completion and spell checking are available only on it. If several commands in this document do not work, you might wish to try :set nocompatible followed by a carriage return or 'Enter' in your vim.

Just in case

Just in case you are new to vim, or have completely forgotten the vim commands, and are still brave and enthusiastic to try reading this, I won't leave you behind. Here is a five minute tutorial to vim.

Type 'vim' followed by a filename in your prompt to bring up vim.

	$ vim filename
	# Or, for a GUI interface:
	$ gvim filename

This will launch vim with the default directory in vim set to the directory the terminal was in.

You can quit vim by typing

	:q
	# Or, for the 'quit without saving' mode:
	:q!

Once, in vim, you can move around using h, j, k, and l.

        h - left
        j - down
        k - up 
        l - right

Try to refrain from using the arrow keys. These keys were chosen, because they lie on the home row and save the user a lot of time, and unnecessary fumbling with the arrow keys. After you get used to them, you'll hate having to use arrow keys in other text editors.

To insert text at a location, hit i. This will put you into insert mode. The bottom left of your screen should read something similar to

        -- INSERT --

[ This presumes that 'showmode' has been set. If you don't see the above, and would like to, add 'set showmode' to your ~/.vimrc file. -- Ben ]

Type in text till you are done. Use backspace if necessary. Avoid using delete and the arrow keys. If you are done, or you think you need to navigate elsewhere, hit <ESC>. Control+[ should also do. I do not recommend the second however, since it is present only as backward compatibility on several old machines that did not have the Esc Key.

You are now back into the normal mode. You can move around with h, j, k, l again. That should be just enough. Spend some time trying to get comfortable with it.

Save and exit with

        :w followed by :q
        or simply :wq

Let's begin!

The art of insertion

Several people around me often tell me that their greatest difficulty with a major-mode editor like vim, is that they never know which mode they are in.

If you are one like them, the answer is pretty simple. Vim was not designed to be used the way you are using it. Vim was designed for short bursts of insertion. Vim was designed around the idea that people tend to type text for a much shorter time than they spend reading, editing, and revising it. Therefore if you need to get up for coffee, or pick up the phone, or are done with that sentence of yours, hit the Esc button.

Vim provides several keys to help you get to the right cursor position to insert characters. We list some of the more useful ones here.

        i               insert BEFORE Cursor
        a               insert AFTER Cursor (append)

        shift+i (or I)  insert at BEGINNING of line
        shift+a (or A)  append at the END of line

Noticing similarities? Good, because that is what vim is about. A lot of vim is actually very intuitive.

Great! So how do you go about creating new lines?

        o               create a new line BELOW the current line, and put the cursor at the start of
                        the new line.

        shift+o (or O)  create a new line ABOVE the current line, and put the cursor at the start of
                        the new line

Wonderful! I do not have to <End><Enter> or <Home><Shift+Enter>. How do I edit text?

        r               replace the char at the cursor position and come back into escape mode.
                        In other words, replace a char
        shift+r (or R)  go into what people would generally call the replace mode. Vim is pretty 
                        intelligent. Have a look at how the backspace works in this mode.

Ok! How do I remove characters?

        x               remove char under the cursor. Similar to delete.
        shift+x (or X)  remove char before cursor. Works like backspace.

Visual Mode

Selecting in vim, can be done with the mouse, if mousemodel is set properly. See :help mousemodel on this. But the recommended way of selecting is to use the visual mode.

In normal mode, hit v . You will notice at the bottom left of your screen

                -- VISUAL --

or something similar.

Moving around with h, j, k, l will now select text. You can delete (cut) the selection with x, or copy, paste, them with keys y and p. As soon as you have done any of these, you should be out of visual mode. To otherwise exit visual mode, you can hit the magic key, Esc.

y stands for Yank and p for Paste. Try them out. More on this will follow.

Undo and Redo

With all that copying and pasting, you are bound to make mistakes. So how do you undo? Control+Z? No. In normal mode simply hit u . Are you beginning to see the power of major modes here? Keys are often very short and intuitive.

How do you redo? r? No, both r and R were taken by replace modes. You do Control+R to redo.

How much can you undo? Quite a lot actually. In the more recent versions, you can undo to any point since the current session of vim was started.

The latest version of vim at the time of writing, vim 7.0 even has support for undo branches.

You can say something like

	:earlier 10m
	
	 # or
	
	:earlier 2h

and it would take you to 10 minutes or 2 hours ago. (If vim was open two hours ago.)

Similarly :later.

What we have covered so far, are just the mere basics. This is stuff that most people know. If you didn't, you do now! What comes from here on is the important part. Learning to use vim as a Swiss Army knife for text and programming.

Copying, Deleting, Pasting

In vim, a selection can be copied by yanking, or y. This is different from emacs' yank, which pastes. In vim, the paste command is p. Pasting and yanking can be done into registers too. There are no deletes in vim. Everything goes into the paste buffer - or, optionally, into a register named with a single character from the {a-zA-Z0-9} list.

        y       : copy selection. (Use visual or implicitly copy like yas to yank a sentence - see 
                  Mnemonics below)
        yy      : copy current line.
        Y       : copy current line.
        d       : delete (cut) selection. Same usage as y.
        dd      : delete (cut) current line.
        D       : delete from here till end of line.
        p       : paste selection (Pasting is intelligent. If you copy a whole line, it will put 
                  it below the current line.) see 'ddp' below in keyboard combos

Note that the scope of the action of Y is different from that of D; indeed, Y = yy. If you want to set it to what would you have expected normally read the section on mapping below.

        "fy     : copy selection and paste in register f
        "fd     : delete selection and paste in register f
        (This works with "xyy "xY and all other similar things too.)

        "fp     : paste what is present in registers f.

You can look at the registers by using the ':reg[isters]' command. In your version of vim, uppercase registers may be restricted by default, so I suggest not using them.

[ Using an uppercase register name appends a 'y'ank or a 'd'elete to the existing register content; the lowercase version replaces it. -- Ben ]

The other registers are special, often storing text, or marks (see below) for other commands. Therefore these should not be touched. An exception is the '+' register.

Vim's clipboard is independent of the external OS clipboard. Vim imports the text in the OS Clipboard into the '+' register. In order to paste something copied into another application use the '+' register. Command : "+p

As expected, copying or cutting into that register '+' will write to the OS clipboard. So if you want to copy something into another program, use "+y

Mnemonics

Mnemonics are commands to perform common tasks. What separates them from being normal commands is the underlying ability to remember them from the task they do. To understand and use mnemonics well, one must first understand text objects. See :help text-objects, or read the subsection under "text objects" below. As an example of a mnemonic, take 'ctx':

	ctx - change till x (deletes from here until first character 'x', and puts you insert mode)
	dtx - delete till x 

Mnemonics that fall under text objects

There are several objects in vim that act as text-objects: words, sentences, blocks, etc.. Vim gives you the power to use them in selections and edits.

        daw - delete a word
        dw - delete from here till end of word
        daW - delete a Word(includes special chars, except space)
        dW - delete from here till end of Word

        das - delete the sentence we are in
        daB - delete an inner Block of code {}

Rules like the above can be applied in general to text objects:

        s - sentence
        w - word
        W - WORD
        t - tag ( 'dat' removes from <xml-style-tag> till </xml-style-tag>
        p - paragraph
        B - block of code ( '{' or '}' works only for C-style blocks)

        Bracket forms:
                ( or ) - parenthesis ( ... )
                [ or ] - [ .. ]
                < or > - refers to <....>
                { or } - a { block also referred to by the above b

        Quote forms:
                Just like the bracket forms
                ", ', ` - can be used for referring to text-objects delimited by them.

These things can therefore be used in a manner similar to

        da<text-object> : delete a text object
        di<text-object> : delete the inner part of the text object.
        (This leaves the () or the spaces in words or the {} in blocks)

Their use does not end here; remember, vim is intelligent. They can be used during visual selections as well. In visual mode hit as to select a sentence. Similarly a word can be selected with aw or a block in with a '}'.

Read :help text-objects for more info.

Prefixing Numbers

Almost every command can be prefixed with a number to repeat it in a sensible way. E.g.,

	# Go down 6 lines
	6j
	# Delete the next 10 lines
	10 dd

This is a very underused function that can greatly improve text editing ease.

Slightly Advanced Navigation

Simple Navigation on a line

Vim provides you with several one touch commands to get to a particular character on the line. This coupled with a good use of vim's insertion techniques should put you where you want with almost no effort.

We first learn how to move by words, since moving by characters can often be slow and demanding.

        (ptca = puts the cursor at)

        w - Takes you a word ahead. ptca the start of the
            next word. ('W' does nearly the same thing, but for "words"
			that may include special characters (excluding 'space'))
        e - ptca the end of this word. If the cursor is already
            under the end of this word, takes you to the end of the next word.
        b - move back a word; ptca the start of the previous
            word

Next, it is important to know how to get to particular positions on a line. Important places are the start of the line, and the end of the line.

        0 - ptca the start of line

Remember regular expressions? Vim tries to make the learning curve easier. The following two commands should come naturally if you keep regular expressions in mind.

        ^ - ptca the first non-blank character of line
        $ - ptca the end of the line 

The following commands are really useful as well. They let you get to the nearest instance of a character on a particular line.

        fx - ptca at the next instance (in the forward direction)
             of character 'x' in the same line.
        Fx - ptca the previous instance of the character

These also form the building blocks whenever generic movement is required - like in macros.

The g commands

The 'g' commands, as I call them, refer to a useful set of 'goto' commands that ease moving around. Merely stating them should suffice.

        1G - takes you the start of the file
        0G - to the end of file

A good way to remember this is that '1' often appears before (to the left) of '0' on the number row (above the qwerty row) on a qwerty keyboard.

 
        gD - takes you to the first (intelligent) instance of the word under
             the cursor in the same file. It is intelligent, since in a programming
             language, it takes you to the definition or the declaration of the function
             or variable.
        gj - goto next line. (Huh?). This is the same as j when the lines do not wrap.
             When the lines do wrap around the editor, hitting j would take you over to the next
             new line. gj will take you the same character in the next row. (Try it).
        gk - Similar.
        (To avoid wrapping do :set nowrap)

Note indeed that the small 'g' is called the extended operator in vim. It performs a lot more than merely goto. Indeed the user can see :help g for more information. I'll mention a few useful ones:

		gf - Open the filename under the cursor
		ga - Print ascii value of character under the cursor.
		gs - put vim to sleep for 1 second. Of course, like most
			 vim commands, you can prefix this with a number to get
			 a general sleep command.

Mark Mnemonics

Marks are a very useful feature in vim. They enable you to mark your current position, and move away for a while. You can then go back to the old cursor position by hitting a couple of keys.

        ma      - mark current position with letter 'a'.
        `a      - go back to mark a
        'a      - put the cursor at the start of line a
        :marks    to see a list of marks made.

Marks are intelligent. Even if you make edits to the text before the mark, thereby changing its line number or make edits on the line itself (affecting character number), vim will manage the marks aptly. You will still be able to return to your old mark with the same key combination. Note that mark movements are often called jumps.

There are a few registers that are set by default. I list a few helpful ones below:

        ``      - go back to the last cursor position before a jump.
        `.      - go back to where the cursor the last time an edit was made.
                  This puts your cursor at the start of the edit.
        '(      - go to the start of the current sentence
        ')      - go to the end of the current sentence
        '{      - go to the start of the current paragraph
        '}      - go to the end of the current paragraph

Moving to a line

To navigate to line foobar, simply type :foobar or foobarG . E.g., to navigate line 234:

	:234 
	234G

I strongly recommend using the :number, because you will be able to see the line number you are typing.

As always, remember in vim, if you make a mistake in the middle of a command hit <Esc>

Of course, if you have been there before, and go there frequently enough, I would suggest marking it. Even though it does not seem that great a feature, it comes in handy when you have to debug programs.

Navigating Screenfulls

As mentioned earlier, a design aspect in vim was to allow your hands to stay on the home row. So how do you do it without moving your hands to PageUp and PageDown?

	Control+(f/F)   move forward a screen  (PageDown)
	Control+(b/B)   move backward a screen (PageUp)
	Control+u       moving up half a screen
	Control+d       moving down half a screen

There is one last thing you should know about navigation. In case the line number does not show to the bottom left (ruler is set to off), just hit Control+G. This should show you the line number and some other statistics in the bottom status bar.

Power Keystrokes

Think of Power Keystrokes as combos in an arcade-style fighter game. It helps you do several mundane oft-repeated tasks with a couple of key strokes. The meaning of each of the key strokes is already known, just like light punches and hard kicks. Putting them together in specific ways produces several desirable results. We illustrate a few of them to follow.

        xp  - switch the current char and the next
        ddp - switch the current line and the next
        A;  - append a semicolon to the end of the line.
        >>  - increase indent of current line.
        <<  - decrease indent of current line.

Finding and Substituting

Finding is a relatively simple job in vim. Just hit '/' in normal mode, and start typing. Hit Enter to search. The key n will take you to the next search, and Shift+n or N to the previous.

A very useful tip when it comes to searching is the '#' key and the '*' key. These search for the word under the cursor, backwards and forwards respectively. To sum it up,

        /foobar<Enter>  search for foobar
        n               go to the next result
        N               go to the prev result
        #               search for the word under the cursor (back)
        *               search for the word under the cursor (fwd)

The substitute command is slightly more complicated. However, when in the right hands it can prove to be wizardly. The syntax of the substitute command is as follows:

        :[range]s[ubstitute]/pattern/string/[options]

The range is a very interesting argument to play around with. Here we take a look at vim's :help range to see what we can do.

        Range           What it means
        ------          --------------
        {number}        an absolute line number
        .               the current line                          
        $               the last line in the file                 
        %               equal to 1,$ (the entire file)            
        *               equal to '<,'> (the Visual area)          
        't              position of mark t (lower case)           
        /{pattern}[/]   the next line where {pattern} matches     
        ?{pattern}[?]   the previous line where {pattern} matches 
        \/              the next line where the previously used search
                        pattern matches
        \?              the previous line where the previously used search
                        pattern matches
        \&              the next line where the previously used substitute
                        pattern matches

Most substitution commands in vim are often written as :%s/old_string/new_string, for obvious reasons.

Again looking into vim's help for the options we get (in brief):

        Option          What it means
        ------          --------------
        c               Ask before substitution. (Check)
        e               Don't cough Error messages if no such pattern is not found.
        g               Global (replace all occurrences in the line).
        i               Ignore case.
        I               Do not ignore case.
        n               Do not substitute. Only return the number of successful matches.

For, e.g., a substitution of the form

        :1,'bs/dog/cat/ceg

would replace dog with cat after checking with you, for all instances in that line, from line 1 to the line where mark was set as b. It will not throw any errors if 'dog' was not found.

See the section on "Dealing with Multiple files" for substituting and searching across multiple files.

Useful Navigating Techniques for Programmers

Even though this could have been fit into the section on navigation above, I decided to make it another section to emphasise it further.

Vim provides various techniques to the programmer. The most useful one is the jump parenthesis shortcut.

        %       jumps between matching pairs of parenthesis () {} [] <>. With the match-it addon,
                it will jump between matching tags in html files - between the <div ... > and the 
                corresponding </div>

One might also find the 'goto' command very useful.

	gD      takes you to the global declaration of the variable or function under the cursor.
			However, this will only do so in the same file.

	gF		takes you to the filename under the cursor. Very useful for
			jumping to header files.

Vim also integrates with ctags, in a nice and natural way. However, I suggest that you read the help manual for this.

Folds

Folds are a wonderful way to organise and group code. Of course, it can be used for editing text, LaTeX documents, and several other things, but the clarity it gives to code is fascinating.

There are several folding methods available in vim. I shall describe only the manual ones, and briefly mention the rest. More information can be gotten from :help fold .

As with a few other things of this kind, I feel that folds are best illustrated by an example. Pick a text file, preferably a large one, that does not fit on one screen. Open it in vim, and place your cursor anywhere you like. In normal mode, type

        zf3j 

After you press j, vim will create a fold covering the next 3 lines. How did it happen? Well, zf means to close a fold, and knowing vim's movements 3j is to come down 3 lines. So from the current position to 3 lines down, vim folds.

Vim also supports folding using visual mode. Simply select a piece of text, and type zf. It should fold as well. Another option is to specify a range in command mode. For instance, if you wanted to create a fold from 3 lines above to 101th line, you would do

        :-3, 101 fold 

and hit enter. From 3 lines above to line 101, vim should have folded. Vim will suitably reverse the range for you if 3 lines above was greater than 101 after prompting. You could have also used markers if necessary.

Vim can also make some smart text selections. Suppose you are writing C code. You can position your cursor on a '{' and hit

        zfa} 

This will fold till the matching '}'. Of course, as we learnt above you could also use the more natural

        zf% 

to perform the same operation. Finally, you can also use a search-fold technique. You can hit z/ and start typing for the string required. It will fold from the current line to the first instance it finds the search string. Therefore, typing in

        z/SearchString

would fold appropriately.

Like someone once said, folding is only half the fun. At some point, you'll no doubt want to unfold the text. To do this, simply place your cursor on the same line as the fold and type

        zo

This will reopen the fold. This will not delete the fold. Type

        zc

to close it back up when you are finished. To move between various folds quickly, use

        zj for next fold
        zk for previous fold

Nested folds

As said before, vim allows nested folds. If you use zo, it will open only the first fold; the other folds will stay closed. The following commands will prove helpful in dealing with nested folds

        zO (shift+o)    open all nested folds on that line (zc will close them too)

        zr              open the highest level of folds in the file. For eg, all the first 
                        level folds.
        zR              open all folds of all levels in the file

        zm              close all highest level of open folds in the file.
        zM              close all folds of all levels in the file.

        zE              delete a fold

Delete a fold with caution. vim's undo and redo features don't apply to folds; if you delete a fold, you can't press u and bring it back, and the . command won't run the last fold command.

How does vim deal with folds when searching for text? It acts as if the fold is not present. If the word is found while searching within a fold, it will open the fold. Vim is untidy with this. It does not close the fold when you move your cursor out. However a quick zm will restore the folds.

Once you close the document you created all the folds in, all the folds will be lost. Therefore, you must ensure to save your folds before you exit. You must also load the saved folds after you open it again. This can be done with the following commands.

        :mkview         make a foldview
        :loadview 

You can of course automate this by adding the following to your .vimrc:

        au BufWinLeave * mkview
        au BufWinEnter * silent loadview

There exist other folding methods like those mentioned before. Notable ones are diff (via 'vim -d file1 file2'), which set only the edited lines unfolded, and indent which folds depending on indent.

Visual mode Selections

Visual mode provides what can be called 3 minor modes.

        v       - enters visual mode.
        Shift+v - enters visual mode, where only lines (in full or none) can be selected. 
        Ctrl+v  - enters rectangular visual (block mode).

Play around with these for a while. This should let you become more adept at using Visual. The rectangular visual mode is very useful in temporarily commenting code, or in removing comments.

Suppose we had a code block like

        int main()
        {
                register int k;
                ...
                ...
        }

Put your cursor at the start of the main declaration. Hit Ctrl+v followed by 6j. Then hit Shift+i and type //. Finally hit Esc to come out of the visual mode.

This should comment the entire block with C++ style comments.

Filters

Vim lets you run shell commands from itself by typing

        :! shell-command

With the concept of a GNU-like "one utility per action" system, the concept of filters is inevitable. By using a filter, we can send text in our buffer (screen) to an external command - say 'indent' or 'sort' - whose output is then sent back into vim.

Using the range concept given above, one could write things like

        :%!gpg

to encrypt one's message with their personal key.

Here are a couple of other examples

        :%!tr a-z n-za-m (This will ROT13 our data :))

        :.,+5!sort

As mentioned above in the range section, . represents the current line. A positive number means below, and a negative number means above.

Making Projects

With tools like filters learnt above, we could 'make' our projects with commands like

        :!gcc -Wall -g foo.c -o bar

or syntax check them with

        :!gcc -fsyntax-only % 

Vim however provides its user with a make command. You can set a make program with the command

        :set makeprg=gcc\ -g\ %

and subsequently make by doing

        :make

It accepts command line arguments, enabling you to do things like

        :make all
        :make install

The default makeprg is set to 'make' in the directory vim currently is in. This by default was the directory our terminal was in, when vim or gvim was called. See the section on "Browsing files with Vim" below to find out the current directory and to change it.

If there were any errors, vim will display them to you. If you are using a fairly common language, vim can even parse the error file and tell you a whole lot more. Pressing 'Enter' in the error window should by default take you to the first error.

In the case the errors can be parsed, the following should be the holy-grail combinations:

        :cc     -       will show you the current error
        :cn     -       will take you to the next error
        :cN     -       will take you to the prev error
        :copen  -       opens the error window in a small buffer
                        where you can browse errors. Hit <Enter> to be
                        taken to that error.

This should make your compile -> edit -> compile cycle a lot easier on you.

Dealing with Multiple Files

Often, programmers or developers have multiple files in their buffers. I assume you know how to split windows, and all that jazzy stuff. If not, you could read the Vim tutorial :help vsplit

From vim7.0 onwards, tabs are supported. Tabs can be opened by

        :tabnew file.txt

To cycle through tabs one would use :tabnext (:tabn) and :tabprevious (:tabp). One can by default, also go to the previous/next tab by using Control+PgUp and Control+PgDwn provided of course there are no other open programs mapped to that application. (A common program is gnome-terminal with multiple tabs.)

Another way to open and edit multiple files is the buffer. Any file you open is in your buffer till you close it. To open a file in a buffer simply use the normal edit command

        :e foo.txt 

For dealing with buffers, one should find the following commands useful:

        :bfirst         switch to the first buffer
        :bn             switch to next buffer
        :bp             switch to prev buffer
        :blast          switch to the last buffer
        :ls             list all currently open buffers
        :buf foo.txt    switch to foo.txt in the buffer

The main power of buffers comes in dealing with them in a batch. Vim has the command bufdo, which allows you to run a command over all the files in your buffer.

        :bufdo {cmd}

Quoting the vim Manual,

What this basically does is

        :bfirst
        :{cmd}
        :bnext
        :{cmd}
         etc ...

When the current file can't be abandoned and the [!] is not present, the command fails. When an error is detected on one buffer, further buffers will not be visited. Unlisted buffers are skipped. The last buffer (or where an error occurred) becomes the current buffer. {cmd} can contain '|' to concatenate several commands. {cmd} must not delete buffers or add buffers to the buffer list.

To search in multiple files one would simply do

        :bufdo /searchstring/

To search and replace for example, one might do

        :bufdo %s/oldtext/newtext/ge

There are other cool things you could do with buffers. You could backup your entire project into a tarball by doing something like

        :silent bufdo !tar -rvf backup.tar %

Of course, the files do not have to be open in vim, you could set the args variable in vim, and use a similar argdo.

For eg. to indent all files in foobar/ one would do

        :args foobar/*
        :argdo !indent % | update

update writes the file only if changes were made.

Browsing files with Vim

Open a directory with 'vim path/to/dir' or from within vim, :e path/to/dir. A file browser opens up that one can use to browse, and make modifications. Use <Enter> to enter a directory, and j, k to move up and down.

The following should be helpful:

        d - to make a directory
        D - to delete one
        R - to rename

You can set the directory vim is in by using the cd command as

        :cd path/to/dir

As expected you can use :pwd to find out the present directory vim is in.

Having the netrw plugin installed, allows one to access and edit files on a remote machine as well, through protocols like ssh and ftp.

Mapping Commands and abbreviations

Mapping commands and abbreviations are an essential part of the programmer's lifeline in vim.

Commands can be mapped as follows:

        :map <keystrokes> command-to-be-executed

This will map it in both modes. Use nmap if you want to map it only in the normal mode and imap for the insert mode.

As an example, one might consider

        :nmap \cc !gcc\ -g\ %

This would mean typing \cc (quickly) in the normal mode would execute the gcc compilation on the current program with debugging enabled.

Abbreviations are really useful things to have in one's armory. They let you substitute a larger word for a smaller one, or fix your common mistypes. An example should state this clearly enough:

	:iab cs Computer Science.
	:iab mroe more

This would replace 'cs ' (followed by the space) with Computer Science every time I type it, and replace 'mroe' with 'more'. The i stands for insert mode, and the ab for abbreviate. One could do :ab as well, though it is not recommended. (It might substitute one of your \cs commands with '\Computer Science'.)

To unset the above mapping or abbreviation simply type

        :unmap \cc  or 
        :unab cs 

respectively.

If you want these abbreviations or mappings to remain over various uses of vim, simply put them in your '~/.vimrc'.

As a final example, let us take the remapping of Y to the more intuitive way of using it. You would do

        :map Y y$

for this session, and to store it permanently, append

        map Y y$

to your '~/.vimrc'.

Macros

These are amazingly powerful tools to help you automate your work. It is like a writing a program to help you do some word processing, without having to learn another programming language.

Imagine the power you'd have if you could write programs with vim keystrokes to process text. This is precisely what Macros allow you to do. Macros take a set of keys as input from you and store them in a register of your choice. (Yes, this is the same set of registers you copy into and paste from, so don't accidentally overwrite them). You can then run the command specified by the keys in that register.

The syntax for declaring macros is:

        qx<set of commands>q
        (The second q has to be hit in the normal mode only.)

This stores the set of commands in register x. To run it simply type @x. @@ runs the last run macro.

Macros are best illustrated with an example. Suppose you have a table, the field delimiter being ':'. An example is shown below:

        Name    Age     Fav. Animal
        Bob   : 24   :  Duck
        Harry : 18   :  Tiger
        John  : 36   :  Dog
        ...   : ..   :  ....

Suppose the list is very long consisting of 50 or so names. Your job is to extract everybody's favourite animal and put them in a list.

Of course you could use sed, but you could do it using macros with ease as well. To do so you would do the following:

  1. Put your cursor on Bob, and hit q followed by a register letter say a (for animal)
  2. Type 2f:w which should take you to the second cursor, and then to the start of the next word, "Duck".
  3. Yank the word with a yaw.
  4. We want to move to the end of file, and paste this. However, we should mark our position before we leave. Mark it in some register, say f, with mf.
  5. Goto end of file with 0G.
  6. Put in a new line with o and come back to normal mode with <Esc>
  7. paste with p
  8. Go back to the original cursor position with `f
  9. Finally to make the macro repeatable put the cursor at the start of the next line, with j0 . Exit the macro mode by hitting q.

If you now type :regs you will see the following in register a:

        2f:wyawmf0G0^[`fj0

(<Esc> has been replaced by ^[.)

Now to run this macro simply put your cursor on Bob, and do @a. It should perform the macro and leave you at the beginning of Harry. You can repeat it once again with @@ or simply with a full stop, . (repeat last command). To repeat it several times you could say 50@@, which would repeat it 50 times.

If you found this macro very useful, you could copy it into your .vimrc, replace ^[ with <Esc> and map it to a keystroke. As an example, the above macro would transform to

	" Collect all the animals at the end of the file
	nmap \fa 2f:wyawmf0G0<Esc>`fj0

Macros are terribly underused. Learn to use them effectively.

Completion

Vim now supports omni-completion as well as intelligent buffer completion. The following commands should sum this up:

        Ctrl-n - complete (a small popup should appear. You can browse this with
              Ctrl-n and Ctrl-p. Simply continue typing when done.

        Ctrl-x f - complete this filename.

        Ctrl-x i - complete from included files.

SpellCheck

With Vim 7.0, Vim now supports built-in spellchecking. To enable it simply type

        :set spell 

and to disable

        :set nospell

You can navigate spelling errors by using ]s and [s . You can correct them by hitting z= . This will pop up a list of possibilities that you can choose from.

Common Settings

This section simply describes a list of common settings that people might find useful. You can see my .vimrc to look at what I use.

Options are set to true using :set option , unset (set option to false) using :set nooption and set to other values using :set option=value. You can invert an true/false option by using :set invoption.

Options often have shorter names that enable you to type them faster. An example would be 'ft' for filetype, enabling you to do :set ft=value instead of the longer :set filteype=value

Options

        autoindent  -   automatically indents your cursor on the new line, depending on where 
                        this line started.
        smartindent -   is smarter than autoindent. Knows to go back a tab, if you have closed
                        a block using '{' or goes front a tab if you have opened one with '{'.
                        This is also language specific, and knows the block delimiters for several 
                        languages.
        hlsearch    -   sets highlight of search on or off.
        incsearch   -   sets incremental search on or off. Incremental search is the name 
                        programmers give to "find as you type" search. This is VERY useful.
        expandtab   -   fill tabs with spaces when a tab is hit. The number of spaces depends on 
                        the tabstop option.
        showmatch   -   show matching (), {}, [] when typing. Very useful for programmers.
        ft=VALUE    -   set filetype = VALUE

As an example you could do

        :set hlsearch           switches hlsearch on
        :set nohlsearch         switches hlsearch to off
        :set invhlsearch        inverts hlsearch (which was previously off due to the last
                                command) to on.

To change file types from 'txt' to 'html' you would do

        :set ft=html

and if you still find no syntax highlighting,

        :enable syntax
        # or
        :syntax on

For help on an option, do :help option

There is a very useful option that I often use. I am one of those compulsive <Esc> hitters. If I am decide to change my command, or abort my command, or simply feel itchy I hit the <Esc> button (often more than once). Vim deals with it graciously, and simply beeps, which does not bother me at all. However, in a work situation like the office or the lab, people sitting near you may get irritated with the beep(s). You can tell vim to switch off the sound alert, and switch on a visual one with

        :set visualbell

Try hitting two <Esc>'s in a row now. The screen should just flash.

Miscellaneous Commands

This section lists a few miscellaneous commands that would not fit anywhere else in this document.

        Shift+j (or J) - This will bring up the next line and join it to the end of the current one.
		                 Learn to use this well. It is what people in other editors would perform as 
                         <End><Del> . A mnemonic for Join the previous line with current line.

        Shift+k (or K) - Displays the man page for word under cursor

        ~              - Swap Case of character under cursor, and move to the next character.

        .              - repeat the last command, whatever it is. (The command could be the insertion of a
                         sentence or even a macro). What most editors would call 'repeat'.

Vim can also increment and decrement numbers for you. This is extremely useful in writing larger more generic macros. As usual, numbers prefixed with a '0' are considered octal; numbers prefixed with a '0x' are considered hexadecimal. Numbers not beginning with a zero, are decimal.

        Control+A      - Increments the number under the cursor
        Control+X      - Decrements the number under the cursor

Useful Plugins

Vim, much like Emacs is an extensible editor. There are thousands of plugins for vim, that make one's life a lot easier. Purely for completeness, I list some of the more popular plugins here

        taglist explorer        opens a wonderful little function list by your side,
                                just like an IDE

        matchit                 enables matching of regular expressions using %

        gpg                     encrypts your data with with your private key. Performs
                                decryption as well. 

        calendar                displays a calendar in your vim window, to which you can
                                add notes, et al, ala org-mode

        minibufexplorer         displays all open buffers and tabs on a horizontal list at
                                the top/bottom of your screen.

        tetris                  yes, with rotating game play and high scores!

Besides all this, there are a lot of programming suites available for the more popular languages like C/C++, LaTeX, Java, Python, Ruby, etc...

There are currently more than 2200 plugins available at http://vim.org, some of which are bound to make your life easier or a little more fun. Taking advantage of such a wealth of hard work and talent is more than just good fun; it makes a lot of sense.

Final Tips

When all said and done, it is up to you to become proficient in using vim. There is no harm in thinking out what is the best way to do something when you do it for the first time. It will save a lot of time in the future. At one point of time, all efficient vim users thought about the commands they were typing. Reflect on it, before it becomes a habit. It might be slow initially, but the effects you reap later on will be very high.

If you are the kind who keeps forgetting which mode insert/normal/visual mode you are in, remember, as mentioned before that vim is meant to be kept in the normal mode. Words are to be inserted in short bursts. As soon as you finish typing/selecting, come back to normal mode, by hitting <Esc>.

Also, remember that vim commands can be repeated by prefixing numbers to the commands. Like 7j or 3w, etc.. This is probably the most underused vim powertool. Write macros that can be repeated too.

Finally, remember to customise your .vimrc with useful functions, macros, abbreviations, and settings. Before hurriedly writing your own plugin, search vim.org. There are lots of plugins that can help improve daily productivity. And yes, do remember that vim's :help is a wonderful piece of documentation.

Good Luck Vimming!

Talkback: Discuss this article with The Answer Gang


[BIO]

Pranesh Srinivasan is currently pursuing a B. Tech (and subsequently, an M. Tech) in Computer Science and Engineering at the Indian Institute of Technology Madras. He has been using GNU/Linux for the last two years.

Initiated into Linux by laboratories in his department, he switched voluntarily to GNU/Linux soon after, realising the potential power and control it could give him. Apart from loving to script in python, he loves using vim, LaTeX, perl, git, and Gnome. He dual boots his personal machine with Debian GNU/Linux and Ubuntu GNU/Linux.

His other interests include writing, reading, swimming, playing football, and general mathematics.


Copyright © 2008, Pranesh Srinivasan. Released under the Open Publication License unless otherwise noted in the body of the article. Linux Gazette is not produced, sponsored, or endorsed by its prior host, SSC, Inc.

Published in Issue 152 of Linux Gazette, July 2008

Tux