Vim Cookbook

by Steve Oualline

This is the Vim cookbook page. It contains short recipes for doing many simple and not so simple things in Vim. You should already know the basics of Vim, however each command is explained in detail.

Each set of instructions is a complete package. Feel free to pick and choose what you need.

Contents

Character twiddling
Interactively replacing one word with another
Interactively replacing one word with another (command line method)
Replacing one word with another using one command
Moving Text (Vi style commands)
Moving Text (Visual mode)
Copying a block of text from one file to another
Copying a block of text from one file to another (Visual Method)
Sorting a section (Vi Style)
Sorting a section (Visual Method)
Dealing with Makefile and other SOB files
Formatting a text paragraph
Finding a procedure in a C program
Drawing comment boxes
Reading a man page
Removing carriage returns from MS-DOS file
Trimming the blanks off an end of line
Oops, I left the file write protected
Changing "Last, First" to "First Last"
How to edit all the files containing a given word
How to edit all the files containing a given word using the built-in grep


Character twiddling

If you type fast your fingers can easily get ahead of your mind. Frequently people transpose characters. For example the word "the" comes out "teh".

To swap two characters, for example "e" with "h", put the cursor on the cursor on the "e" and type xp.

The "x" command deletes a character (the "e") and the "p" pastes it after the cursor (which is now placed over the "h".)


Interactively replacing one word with another (n. method)

Suppose you want to replace every occurrence of the word "idiot" with the word "manager". But you want the chance to review each change before you do it.

Here's what you do:

1. 1G Go to the top of the document
2. /idiot<enter> Find the first occurrence of the word "idiot"
3. cwmanager Change the word (cw) to manager.
4. n Repeat the last search (find the next idiot.)
5. . Repeat the last edit (change one word to manager)
(If you do not want to change the word, skip this step.)

Repeat steps 4 and 5 until you have replaced all occurred.

The Virgin What!?

A church had just bought their first computer and were learning how to use it. The church secretary decided to set up a form letter to be used in a funeral service. Where the person's name was to be she put in the word "<name>". When a funeral occurred she would change this word to the actual name of the departed.

One day, there were two funerals, first for a lady named Mary, then later one for someone named Edna. So the secretary used global replace to change "<name>" to "Mary." So far so good. Next she generated the service for the second funeral by changing the word "Mary" to "Edna." That was a mistake

Imagine the Minister's surprise when he started reading the part containing the Apostle's Creed and saw, "Born of the Virgin Edna."


Interactively replacing one word with another (command line method)

Suppose you want to replace every occurrence of the word "idiot" with the word "manager". But you want the chance to review each change before you do it.

Execute the command:

:%s/\<idiot\>/manager/gc

This command will make the change and pause after each change to give you a chance to confirm it. You can enter "y" to accept the change or "n" to not accept it.

The parts of this command are:

: Enter command mode
% Perform this command on all lines (% is a synomim for the first to last line.)
s The short form of the :substitute command.
/\<idiot\>/ This text specifies the text we are looking for wand want. The \< tells Vim to match a word start and the \> tells Vim to match the end of a word.
/manager/ The replacement text
gc The flags. These are
g
Global -- Change every occurance, not use the first one on each line
c
Confirm -- Ask before making each change

Replacing one word with another using one command

Suppose you want to replace every occurrence of the word "idiot" with the word "manager". No confirmation needed because all idiots are managers.

Use the command:

:%s/\<idiot\>/manager/g

The parts of this command are:

: Enter command mode
% Perform this command on all lines (% is a synomim for the first to last line.)
s The short form of the :substitute command.
/\<idiot\>/ This text specifies the text we are looking for wand want. The \< tells Vim to match a word start and the \> tells Vim to match the end of a word.
/manager/ The replacement text
g Global flag -- This flag tells Vim to change every occurance on the line, not use the first one.

Moving Text (Vi style commands)

Suppose you want to move a paragraphs from the top of the document to the bottom. There are several ways of doing this. In this example, we do it using Vi style command. In the next section Moving Text (Visual mode) we do it using using the Vim visual commands.

To do the move the commands:

Command Explaination
1.   Move the cursor to the top of the paragraph you want to move.
2. ma Place a mark named "a" at this location. (Vim will give you no indication that this command has been executed. In other words, the screen will not change.)
3.   Move the cursor to the bottom of the paragraph to be moved.
4. d'a Delete to mark "a". This puts the deleted text in a cut buffer.
5.   Move the cursor to line where the text is to go. The paragraph will be placed after this one.
6. p Paste the text in below the cursor.

Moving Text (Visual Method)

Suppose you want to move a paragraphs from the top of the document to the bottom. There are several ways of doing this. In this example, we do it using the Vim Visual mode. In the previous section Moving Text (old method) we do it using using the Vi style commands.

To do the move the commands:

Command Explaination
1.   Move the cursor to the top of the paragraph you want to move.
2. v Start visual mode. (If you want to move only full lines, use the V command which starts visual line mode.
3.   Move the cursor to the bottom of the paragraph to be moved. The text to be moved will be hightlighted.
4. d Perform a visual delete. In other words delete the highlighted text.
5.   Move the cursor to line where the text is to go. The paragraph will be placed after this one.
6. p Paste the text in below the cursor.

Copying a block of text from one file to another (Vi Style)

There is more than one way to copy text between files. In this section we use the more triditionally Vi commands. In the next section Copying using visual mode, we perform the same operations using the Visual mode.

To copy a block of text between files execute the commands:

Command Explaination
1.   Edit the file containing the text you want to copy.
2.   Go to the top line to be copied.
3. ma Mark this line as mark "a".
4.   Go to the bottom line to be copied
5. y'a Yank (y) the text from the current cursor location to the mark "a" ('a)
6. :split second-file Open another window containing the second file. (This the file in which the text is to be inserted.)
7.   Go to the line where the insert is to occur. The text will be place after this line.
8. p Put the text after the cursor.

Copying a block of text from one file to another (Visual Method)

There is more than one way to copy text between files. In this section we use the newer visual mode commands. See the previous section for the older Vi Style of doing things.

To copy a block of text between files execute the commands:

Command Explaination
1.   Edit the file containing the text to be copied.
2.   Go to the top line to be copied.
3. v Start visual mode. If you want to copy a block of full lines, use V to go start Visual Line Mode
4.   Go to the bottom line to be copied. The text to be copied will be hightlighted.
5. y Yank (y) the text.
6. :split second-file Open another window containing the second file. (This the file in which the text is to be inserted.)
7.   Go to the line where the insert is to occur. The text will be place after this line.
8. p Put the text after the cursor.

Sorting a section (Vi Style)

Frequently you will be editing a file with a list of names in it. For example, a list of object files that make up a program.

For example:

	version.o  	
	pch.o		
	getopt.o 	
	util.o		
	getopt1.o	
	inp.o		
	patch.o		
	backupfile.o

This list would be nice in alphabetical order. Or at least ASCII order. To alphabetize this list execute the commands:

Command Explaination
1.   Move the cursor to the first line to be sorted.
2. ma Mark the first line as mark a.
3.   Move to the bottom of the text to be sorted.
4. !'asort The ! command tells Vim to run the text through UNIX command. The 'a tell the editor that the text to be worked on starts at the current line and ends at mark a. The command that the text is to go through is sort.

The result looks like:

	backupfile.o
	getopt.o 	
	getopt1.o	
	inp.o	
	patch.o		
	pch.o		
	util.o		
	version.o  	

Warning

In actual practice what you in most Makefiles (file that are used by UNIX to control compilation) looks more like:

OBJS = \
        version.o       \
        pch.o           \
        getopt.o        \
        util.o          \
        getopt1.o       \
        inp.o           \
        patch.o         \
        backupfile.o

Notice that the backslash (\) is used to indicate a continuation line. After sorting this looks like:

OBJS = \
        backupfile.o
        getopt.o        \
        getopt1.o       \
        inp.o           \
        patch.o         \
        pch.o           \
        util.o          \
        version.o       \

The names are in order, but the backslashes are wrong. Don't forget to fix them using normal editing before continuing.

OBJS = \
        backupfile.o    \
        getopt.o        \
        getopt1.o       \
        inp.o           \
        patch.o         \
        pch.o           \
        util.o          \
        version.o

Sorting a section (Visual Method)

Frequently you will be editing a file with a list of names in it. For example, a list of object files that make up a program.

For example:

	version.o  	
	pch.o		
	getopt.o 	
	util.o		
	getopt1.o	
	inp.o		
	patch.o		
	backupfile.o

This list would be nice in alphabetical order. Or at least ASCII order. To alphabetize this list execute the commands:

Command Explaination
1. Move the cursor to the first line to be sorted.
2. V Enter visual line mode
3. Move to the bottom of the text to be sorted.
4. !sort The ! command tells Vim to run the hightlighted text through UNIX command. The command that the text is to go through is sort.

Warning

Check out the sort warning section for a short description of the problems that can result from using this command.

Dealing with Makefile and other SOB files

One problem with the file format used by the UNIX make command is that it's extremely fussy.

For example, the following is correct:

        prog: prog.c
                cc -g -o prog prog.c

The following is not:

        prog: prog.c
                cc -g -o prog prog.c

At first glance you might think that these two are exactly. But look closer. The "cc" line of the first one begins with a tab. The second one begins with eight spaces. (You can't tell the difference between a space and a tab when it's printed on the screen! You need a better video card.)

So how are you supposed to tell them apart especially when one the screen (or the printed page) they look exactly the same.

The answer is you can't. You might think that's a bit unfair. Especially when make works on the first one but not the second. But who every said UNIX was fair.

Fortunately Vim has a mode that tells you exactly what's in your file. Executing the command

	:set list
puts you into this mode. When the display is set into "list mode" all characters print. Tabs show up as "^I" and the end of line shows up as $. So in list mode, our two examples look like:
        prog: prog.c$
        ^Icc -g -o prog prog.c$

and

        prog: prog.c$
                cc -g -o prog prog.c$

From this it's easy to see which line has the tab.


Formatting a text paragraph

The Vim editor is not a word processor. Boy is it not a word processor. There are a couple of things you can do to make things better for you when editing text.

Word processors automatically wrap when you type a line that's longer than the margins. The Vim editor lets make a line as long as you want. By executing the command:

        :set wrapmargin=70

you can tell Vim to automatically break lines when the run longer than 70 characters. (You can adjust this number to whatever line length you want.)

This makes entering text much easier. It doesn't solve the problem of editing. If you enter a paragraph and then decide to delete half the words on the first line, Vim will not reformat the text.

You can force a reformat of a paragraph by executing the commands:

Command Explaination
1.   Move to the top of the paragraph.
2. gq} The "!" command tells Vim to pipe a section of text through a filter. The } tells Vim that the section of text for the pipe command is a single paragraph.
3. fmt -70 The UNIX command fmt is a primitive formatter. It performs word-wrapping well enough for text documentation. The -70 tells fmt to format lines for 70 characters per line.

Finding a procedure in a C program

The Vim program was designed by programmers for programmers. You can use it to locate procedures within a set of C or C++ program files.

But first you must generate a table of contest file called a "tags" file. (This file has been given the obvious name tags.) The ctags command generates this table of contents files.

To generate a table of contents of all the C program files in your current working directory, use the command:

        $ ctags *.c

For C++ use the command:

        $ ctags *.cpp

If you use an extension other than .cpp for your C++ files, use it instead of .cpp.

Once this file is generated, you tell Vim that you want edit a procedure, and it will find the file containing that procedure and position you there. For example if you want to edit the procedure write_file use the command:

        $ vim -t write_file

Now suppose as you are looking at the write_file procedure that it calls setup_data and you need to look at that procedure. To jump to that function, position the cursor at the beginning of the word setup_data and press Ctrl+]. This tells Vim to jump to the definition of this procedure. This repositioning will occur even if Vim has to change files to do so.

Note:

If you've edited the current file and not saved it, Vim will issue a warning and ignore the Ctrl+] command.

Drawing comment boxes

I like to put a big comment box at the top of each of my procedures. For example:

	/*******************************************************
	 * Program -- Solve it -- Solves the worlds problems.  *
	 *     All of them.  At once.  This will be a great    *
	 *   program when I finish it.                         *
	 *******************************************************/

Drawing these boxes like this is tedious at best. But Vim has a nice feature called abbreviations that makes things easier.

First, you need to create a Vim initialization file called ~/.vimrc. (At first this may look like a ex initialization file. It is. The Vim command is actually a mode of the ex editor.)

The ~/.vimrc file need to contain the lines:

        :ab #b /************************************************
        :ab #e ************************************************/

These command define a set of Vim abbreviations. What's a Vim abbreviation? Its a word that stands for another word. When Vim see the abbreviation, it will expand it to the full word. In this case we've defined an abbreviation called #b that expands to the beginning line of a comment box. The #e abbreviation does the same thing.

So to create a comment box enter #b<enter>. The screen looks like:

        /************************************************
Enter the comments, including the beginning and ending "*" characters. Finally end the comment by typing #e<enter>. This causes the ending comment to be entered.

Note:

This page was written in Vim. So how did we enter the #b and #e? Easy, we typed in #bb and the deleted a character. (We couldn't enter #b or it would have been expanded.)

Some other useful commands that programmer may want to put in their ~/.exrc include:

	:set autoindent
	:set autowrite
	:ab #d #define
	:ab #i #include
	:ab #b /************************************************
	:ab #e ************************************************/
	:ab #l /*----------------------------------------------*/
	:set sw=4

The autoindent setting causes Vim to indent new lines by a similar amount to the one next to them. This is very useful for entering programs. The autowrite setting tells Vim to write the old file out when switching from one file to another.

The abbreviations #d, #i, and #l, define useful terms for programmers.

Finally, the command set sw=4 sets the shift width (the number of characters text is moved sideways for the shift command (<< and >>)).

This is very useful if you use a 4 space indentation for your C or C++ programs. (Studies at Rice University have shown this to be the best indentation size.)


Reading a man page

You can use the Vim editor to browse through text files. One of the most useful set of files to browse through is the man pages. To do this we assemble a pipeline of three command.

The first is man which gets the page. The next one, ul turns the underline and bold escape codes into something readable, and finally we use Vim to broswe the file.

So our command is:

$ man subject | ul -i | vim -

The man page will be generated and then displayed in the Vim window. You can now use your normal editing commands to browse the files.


Removing carriage returns from MS-DOS file

If you ever try to edit a MS-DOS file, you'll notice that each line ends with a ^M character. This is caused by the funny way that MS-DOS treats the end-of-line. (For some background on this problem take a look at The EOL Story.

To remove the ^M characters from a MS-DOS file, enter the command:

	:1,$s/{Ctrl+V}{Ctrl+M}//{Enter}
This command starts with a colon (:) to tell Vim to enter ex mode. All ex start with a line number range, in this case its from the first line (1) to the last ($). The slash indicates the start of the "from text". The {Ctrl+V} tells Vim to treat the next character as a regular character even if it's a special one. The next character is {Ctrl+M}. (This would be treated as {Enter} without the {Ctrl+V}.) The next slash ends the "from text". What follows is the "to text" enclosed by slashes. In this case it's nothing (//).

Trimming the blanks off an end of line

Some people find spaces and tabs at the end of a line useless, wasteful, and ugly. To remove whitespace at the end of every line, execute the command:

	:1,$s/[ <tab>]*$//

The colon (:) tells Vim to enter ex command mode. All ex commands start with a line range, in this case, the entire file (line 1 to the last line: $).

The first set of slashes enclose the "from text". The square brackets indicate that either character can be a match. So [ <tab>] matches either space or tab. The star (*) means that the previous character specification (space or tab) can be repeated any of number times. The dollar ($ indicates an end of line.

So [ <tab>]*$ tells Vim to look for any number of spaces or tabs followed by an end of line.

These are then replaced by the text in the next set of slashes. This text is nothing, so the spaces and tabs are effectively removed.


Oops, I left the file write protected

Say your editing a file and you've made a lot of changes. This is a very important file and to preserve it from any casual changes, you've write protected it, even against yourself.

The Vim editor allows you to edit a write protected file with little or no warning. The only trouble is that when you try to exit using "ZZ" you get the error:

    file.txt	File is read only

and Vim doesn't exit.

So what can you do? You don't want to throw away all those changes, but you need to get out of Vim so you can turn on write permission.

The trick is to execute the :shell command. This command takes you out of Vim by starting a command processor (shell) running under Vim

You can then write enable the file:

 
	$ chmod u+w file.txt
and get out of the shell, returning to Vim
	$ exit

Finally you need to force Vim to write the file using the command:

	:w!
(It still thinks the file is write protected so we need to use the force option (!) to convince it to try writing.)

Note:

It is a good idea to only spend as short a time as possible in a command processor started by the :shell command. That's because it's easy to forget that you're running under Vim. It's possible to start a shell, that starts Vim, that starts a shell, that starts Vim, that .... Using this method you can easily consume a lot of resources and generate a lot of confusion.

By keeping your :shell sessions short you can avoid lots of trouble.


Changing "Last, First" to "First Last"

You have a list of names in the form:

	Last, First

How to you change them to:

	First Last
It can be done with one command:
    :1,$s/\([^,]*\), \(.*$\)/\2 \1/
The colon (:) tells Vim that this is an ex style command.

The line range for this command is the whole file as indicated by the range 1,$.

The s (substitute) tells Vim to do a string substitution.

The old text is a complex regular expression. The \( ... \) delimiters are used to inform the editor that the text that matches the regular expression side is to be treated special.

The text in the first \( ... \) is assigned to \1 in the replacement text. The second set of text inside \( ... \) is assigned \2 and so on.

In this case the first regular expression is any bunch of characters that does not include a comma. The [^,] means anything but a comma, the * means a bunch (zero or more characters).

The second expression matches anything: .* up to the end of line: $.

The result of this substitution is that the first word on the line is assigned to \1 and the second to \2. These values are used in the end of the command to reverse the word.

The figure below shows the relationship between the \( \) enclosed strings and the \1, \2 markers.

	:1,$s/\([^,]*\), \(.*$\)/\2 \1/
	      ^^     ^^  ^^   ^^^ ^  ^            
	      ||     ||  ||   ||| |  +-----  String matched by 
	      ||     ||  ||   ||| |          first \( \)
	      ||     ||  ||   ||| +--------- String matched by
	      ||     ||  ||   |||            second \( \)
	      ||     ||  ||   ||+----------- Slash separating 
	      ||     ||  ||   ||             old/new strings
	      ||     ||  ++---++------------ Second \( \) 
	      ++-----++--------------------- First \( \)

The next figure breaks out the various parts of the regular expressions used in this example.

	:1,$s/\([^,]*\), \(.*$\)/\2 \1/
		^^^^^  ^^  ^^^
		|||||  ||  ||+--- The end of the line
		|||||  ||  |+---- Repeated 0 or more time
		|||||  ||  +----- Any character
		|||||  ||  +++--- Any character, repeated,
		|||||  ||             followed by EOL
		|||||  |+-------- The character space
		|||||  +--------- The character comma
		||||+------------ Repeated 0 or more times
		|||+------------- Closes the [] expression
		||+-------------- The character comma
		|+--------------- Match anything except the
		|                 next character
		+---------------- Starts a set of matches
		++++------------- Match anything but comma
		    +------------ Repeated 0 or more times
		       +--------- Followed by comma

How to edit all the files containing a given word

This involves the fgrep as well as the special shell character backtick (`).

To edit all the C program files that contain the word indentation_level execute the command:

    $ vim `fgrep -l indentation_level *.c`

The fgrep -l indentation_level *.c searches all the files ending with .c for the word and lists them out.

Since this command is enclosed in backtick (`) characters the results of the command (a list of files) takes the place of the command on the command line.

The Vim editor is then run on these files. The commands :n{Enter} and :rew{Enter} can then be used to browse through the files.

How to edit all the files containing a given word using the built-in grep

Start Vim.

Execute the command:

    :grep >word< >file-list<

This finds the first location of word in the given files and positions the cursor on that line. You can use the command :cn to find the next occurance.