Indepth

Getting Started with Vi

Even if your use a different editor for most of your work, it helps to know the basics of the ubiquitous vi.

by William Ward

Most people who are getting started with Linux or UNIX today already know how to use graphical WYSIWYG (what you see is what you get) editors, with heavy use of the mouse, icons and pull-down menus. When they first encounter the traditional UNIX/Linux editor, vi, it may seem awkward and not very powerful, but the opposite is true.

As with graphical editors, you can select a range of text and execute a command to make changes, move the cursor by indicating where you want it to be and insert text by typing at the keyboard. The difference is that vi doesn't use the mouse; you use the keyboard to specify changes or move the cursor. In order for the entire keyboard to be available for commands, vi has separate command and insert modes.

Modes can be confusing at first. With most editors, whatever you type always goes into the document, and editing is done using a mouse or perhaps keyboard shortcuts. With vi, command mode uses the whole keyboard to specify editing commands. Only when you issue an insert command does the keyboard add text to the document.

Most new vi users learn only a few basic commands: the arrow keys, i for insert, x to delete a character, dd to delete a line, :wq to save and exit and perhaps a few others. They quickly grow tired of leaning on the same keys over and over but are afraid of learning a huge list of commands.

Instead of merely providing a list to memorize, here we explore the structure behind them, which makes the commands easier to remember and allows you to become a vi power user quickly. There are several basic categories of commands, including inserting text, moving the cursor, block edit commands, colon (ex) commands, options and miscellaneous commands.

Inserting Text

The first command to learns in vi is i. Typing i puts the editor into insert mode, where everything you type is inserted into the document until you press the Esc key. But i is not the only way to insert text.

To add text after the cursor, such as at the end of the line, use a. Or jump to the end of the line and append text with A. Similarly, I inserts at the beginning of the line. With these and other insert commands, always press Esc to return to command mode.

Use o to open a new line after the current one and insert text there or O to open before the current line.

Replace the current character with s, or replace many characters using R, similar to overwrite mode in a graphical editor.

Nearly all vi commands allow a numeric prefix, which usually repeats the command a specified number of times. For example, type 3iHooray then press Enter and Esc. It inserts three lines of “Hooray” into your buffer. The s command is different; here, the number indicates how many characters are to be replaced: 5s replaces five characters with whatever you type.

A few control keys have special meaning in insert mode. You can use the arrow keys to move around, but don't forget you're still in insert mode. Also, Ctrl-T and Ctrl-D, at the start of a line, can be used to indent. Ctrl-T moves to the next level of indentation, and Ctrl-D moves back. Use these with the autoindent and shiftwidth options (described in the Options section below) for best results.

Moving the Cursor

Graphical editors move around mainly by clicking the mouse. Some vi clones offer mouse support, but vi and all its clones share movement commands that can move you around quickly. The simplest are the arrow keys or the equivalent letters: h (left), j (down), k (up) and l (right). If these are all you use, however, you are missing out on the full power of vi.

You can move forward and back on a line by holding down the right or left arrow key (or l or h), but there are easier ways. Go to the beginning of the line with ^ or the end with $. To jump one word at a time, use w or W to go forward or b or B to go back. You also can use e or E to jump to the end of the current word. For lowercase w, b and e, a word is a sequence of alphanumeric characters; the uppercase versions use spaces to separate words.

Another way to move around on the current line is to jump to a particular character. For example, to move the cursor to the next s on a line, type fs. Use F for the previous one: Fs. Or use ts to go right before the s and Ts to go the other way. Change s to search for any character. Type , (comma) to repeat any of these searches.

To move the cursor to the top, middle or bottom of the screen, use H, M or L (uppercase). For H or L, a numeric prefix indicates how many lines from the top or bottom of the screen you want to go; it has no effect on M.

To jump back and forth by sentences, type ( or ); for paragraphs, use { and }. If you're editing source code with a lot of brackets, try the % command: put the cursor on any of the following characters: (, ), [, ], { or }, and press %; you'll be taken to the matching bracket.

Often the best way to move around is by searching with the / command. For example, type /hello and press Enter to jump to the next “hello” in the document. Instead of “hello”, enter any regular expression. The n command repeats the search; N goes the other way. Or use ? to search backward in the file. Search is case-sensitive; I discuss the ignorecase option later in this article.

With most movement commands, a numeric prefix can be used to repeat. For example, 5w moves you forward five words, 2n jumps not to the next search match, but to the one after that, and 5fs jumps to the fifth s to the right of the cursor.

Block Edit Commands

In graphical editors, to change a block of text, click and drag the mouse to highlight the text, then click an icon or menu option or type a keyboard shortcut. Although vi does not utilize the mouse, the process is surprisingly similar.

As we have just seen, vi has a rich set of movement commands. Any of these will work as an argument to a block editing command (for example, dw to delete a word). In vi, instead of first highlighting with a mouse and choosing an action, type the block edit command (d) first, and then a movement command (w) to specify the block of text. As a shortcut, you can type the block edit command twice to affect only the current line, for example, dd deletes the current line.

As we've seen, d is for delete. Whenever you delete text, that text is remembered, much like the cut command in a graphical editor. To paste the text (“put” in vi parlance), type p to put it after the cursor's position (or uppercase P for before).

That takes care of cut and paste, but what about copy? In vi, it's called yank and is done with the y commands. These are exactly like the d commands, except they don't delete anything: yy yanks the current line, yw yanks a word and so on.

To replace a chunk of text, you could delete it first and use i to insert a replacement, or use c (change) instead, and you are placed into insert mode to type the replacement text; press Esc when done. Use with a movement command (such as, cw) or change the whole line with cc.

Programmers will love the > and < commands. These shift a range of text to the right or left. To shift a block of code, put the cursor on the { or } character at the beginning or end of the block and type >% to shift it to the right. Any other movement command can be used in place of %, or use >> to shift one line. Use < to shift left. See also Ctrl-T and Ctrl-D (while in insert mode) and the shiftwidth option below.

Lastly, use ! to filter text through an external program. Type the program to run, and the selected part of the file is passed as standard input; the output of the program is inserted into the document in its place. For example, !! filters the current line; !} filters a paragraph. One command that is particularly useful with this is the UNIX/Linux filter fmt, which reformats paragraphs. To run an external program without modifying the file, see the :! command in the “Colon (ex) Commands” section.

Any numeric prefix given is passed along to the movement portion of the command, whether it is given first or between the edit and movement command. For example, either 3dw or d3w deletes three words; 3yy or y3y yanks (copies) three lines.

Colon (ex) Commands

Vi inherits as class of commands from its predecessor ex, accessible through what is sometimes called colon mode. Common examples are :wq (write and quit) and :s/X/Y/ (substitute Y for X). Type : followed by an ex command, and press Enter. After the command is done, vi returns to command mode.

There are several variations on the :w and :q commands. To save the file and continue editing, use :w. You can quit vi with :q, but only if your work is saved; to quit no matter what, use :q! (dangerous). Try :w! to override read-only mode if :q gives an error. Many people use :wq! to write and exit. In vim or nvi, this is like typing :w! and then :q if there was no error while saving. But some other versions of vi treat it like :w and :q!, which means if there was any error saving the file, the work would be lost. Because of this, it is a better habit to use :wq.

The substitution command is extremely powerful. In its simplest form, :s/X/Y/ replaces one occurrence of X with Y on the current line. To replace all occurrences on a line, add g (global) to the end, for example, :s/foo/bar/g. Add c to the end to confirm each change, for example, :s/foo/bar/gc. To change a range of lines, put two line numbers separated by a comma in front, for example, :10,20s/foo/bar/g replaces all occurrences of “foo” with “bar” on lines 10 through 20. Use 1 for the first line of the file and $ for the last line; to replace on all lines, use :1,$s/foo/bar/g (instead of 1,$, you can use %, as in :%s/foo/bar/g).

Another useful command is :g/X/. It allows you to run any ex command for all lines matching the pattern X. For example, to print all lines that contain “hello” on the screen, use :g/hello/p (:p is an ex command for printing lines to the screen). You even can combine it with the :s/// command. To change “foo” to “bar” on all lines that contain “hello”, use :g/hello/s/foo/bar/g.

In both :s/X/Y/ and :g/X/, the expression X is a regular expression, not only a static string. Set the nomagic option to disable this (see below). To learn about regular expressions, I recommend the book Mastering Regular Expressions by Jeoffrey Friedl (O'Reilly & Associates, 2nd ed., 2002).

Use :! to run an external program. :!ls prints the current directory listing. As a convenience, the percent character (%) in the command is replaced with the name of the file you are currently editing, so use :!chmod +x % to make the file executable. Typing :!! repeats the previous :! command. Unlike the command-mode ! commands, this does not modify the text; the output of the program, if any, is simply displayed.

Options

In vi you can set options to change the editor's behavior using the ex :set command. For example, the search commands are normally case-sensitive; to change this use the :set ignorecase or :set ic option. Most options have a two-letter abbreviated version.

There are two types of options, Boolean (true/false) options and those that take a value. To turn off a Boolean option, add “no” to the front; for example, :set noignorecase or :set noic turns off the ignorecase option.

For options that take a value, use the equal sign followed by the value to set. For example, the default spacing for the shift commands (>, <, ^T and ^D) is eight spaces (one tab character), but most programmers prefer two to four spaces. Use :set shiftwidth=4 (or :set sw=4) to make all indentation commands use a four-space indent.

Here are some other useful options:

  • wrapmargin=N turns on word wrapping; specify the number of characters before the end of the line at which to wrap, for example :set wm=8.

  • autoindent (Boolean) indents each line you type the same amount as the previous line, for example, :set ai.

  • magic (Boolean, default true, no abbreviation) controls regular expression behavior in the search commands, for example, :set nomagic.

To set several options at once, combine them into one set command like this: :set noic wm=8 sw=4 nomagic ai.

To save options for future editing sessions, put them in your .exrc file. When you run vi, it runs any ex (colon-mode) commands found in that file. Omit the : character, simply enter the set commands.

Miscellaneous Commands

A graphical editor's scrollbar tells you where you are, and you can click on it to view other parts of the file. Because vi has no scrollbar, it uses equivalent keyboard commands.

Ctrl-G displays the file status, including the current line number. Go to a particular line of the file with the XG command. G by itself jumps to the end of the file, or use :X as an alternate for XG.

Ctrl-F scrolls the screen one page forward, and Ctrl-B goes back one page. To move in half-page increments, use Ctrl-D (down) or Ctrl-U (up).

Some other miscellaneous commands:

  • The x command deletes the current character (uppercase X deletes to the left). A numeric prefix deletes several characters. Text deleted using this command is cut as with the d commands.

  • ~ changes the current letter from uppercase to lowercase or vice versa.

  • Undo a mistake with the u command. Vim has multiple levels of undo. Repeating the u command undoes each step in turn; the Ctrl-R keystroke puts them back (redo). Other versions of vi have only one level of undo; typing u again simply undoes the undo, restoring the change.

  • An uppercase U undoes all changes made so far on the current line; once you leave that line, however, it doesn't work anymore.

  • Type . (period) to repeat the last edit command.

  • To repeat the last :s/// command (but modifying only the current line), type &.

Read More

The vim editor comes with a handy tutorial to let you practice many of these commands. Type vimtutor from the shell prompt or :help tutor from within vim.

William R. Ward (wrw@bayview.com) has been using vi since 1987. He is a teacher, writer and programmer living in Mountain View, California with his wife, Holly. Their company, Bay View Consulting Services (www.bayview.com), offers training courses in Perl, Linux/UNIX and other related topics.