This file is based on the original text version. It was first written for Beginning Linux, an online book written by members of KPLUG. Also, a version of this was published on snipe.net before I converted this primer to HTML.
This work is placed in the public domain, and I abandon all copyright interest in it. Do with it what you will.
vi (short for ‘visual’, and pronounced vee-eye) is a screen-oriented editing program used by many Unix users and, in particular, programmers. Regular users of vi find it a very convenient editing program, but it does take learning, and at first that will look unintuitive. Hopefully this guide is but one step towards hopping over that hurdle.
In a word, :q!
vi has possibly one of the most unintuitive interfaces, and for the user who's used to graphical editors, the first thing they want to do is to quit and return to safety. :-) I heard stories of users who quit vi by rebooting their system!
Of course, that doesn't help get your work done. The rest of this primer will, I hope, give you a slightly bigger picture. The sections below feature commands you will want to type—these I've marked with -> on the left hand side. I've also marked examples with *.
-> i
Most users want to, of course, be able to add stuff to the file they're editing (that being one of the main uses of an editor). You can't just type straight away—when you start vi, you're in what may be called ‘command mode’ where you enter commands.
Type the letter i (for insert), in lowercase. This tells the editor that you want to insert text into your file (more accurately the ‘editing buffer’ since changes are not written back to the file unless explicitly told to; see the section on dealing with files). Just start typing from here on.
-> <Esc>
When you're in insert mode, hitting the ‘escape’ key will get you back into command mode. Think of it as an escape from insert mode.
No, on some systems the arrow keys don't work. If you're currently in insert mode, get back into command mode (see above), then hit the keys corresponding to the direction you wish to move:
k Hit k to go up,
| h to go left,
h <-+-> l l to go right,
| and j to go down.
j
Remember to get back into insert mode before you start entering text again.
-> a
You'll probably realise that the direction keys will not bring the cursor beyond the last character in the line. Typing the letter a (for append) will put you in insert mode just to the right of the cursor.
If you don't want to have to move to the end of the line to add something to the end of the line, type A in capitals. This will get you to the end of the current line, no matter where in the line you were.
-> w -> b
Typing w in command mode moves you to the start of the next word, and b does the reverse.
-> ^ -> $
Typing ^ gets you to the beginning of the line, and $ to the end. If you are familiar with regular expressions (outside the scope of this document) you'll find them easy to remember.
-> <Ctrl>U -> <Ctrl>D
Ctrl-U and Ctrl-D move about half a screen up or down, respectively.
-> :1 -> :$
:1 gets you to the first line in the buffer. (It should be obvious by now that you can replace 1 with any line number you care to choose.) :$ gets you to the last line in the buffer.
-> I -> A
If you're inserting text at the beginning or end of lines, the command I is similar to ^i (insert at beginning of line), and A is similar to $a (append at end of line).
-> x -> X
In insert mode, you can only delete text that you've typed in the current line, in the current insertion. That is, if you hit the escape key and re-enter insert mode, you can't delete what you've typed previously by hitting the backspace key.
One way to delete text, a character at a time, is to get into command mode and type either x or X—the lower case version deletes the character at the cursor (and behaves similarly to the ‘delete’ key in graphical editors) and the upper case one deletes the character just before the cursor (and behaves similarly to the ‘backspace’ key in graphical editors).
-> dmotion
Typing the letter d, followed by a motion command (like h or l, or more usefully w) deletes text from the cursor to the target of the motion command. For example, dw deletes from the cursor to the start of the next word.
-> D
This command deletes to the end of the line, and is similar to d$.
-> dd -> :d
Both of these commands delete the whole line. To delete a whole bunch of text I just hold down the d key until I'm satisfied. :-)
-> :j
The :j command joins the current line with the next. A single space is added to the end of the first line, unless the first line ended with a full-stop, in which case two spaces are added.
You split a line the conventional way—go into insert mode, and hit the return key.
Yeah, to replace text you can just remove and then insert, but there are faster ways to do things.
-> s
Replaces the character under the cursor. More useful than it looks, when you read two sections down. :-)
-> S
Replaces the whole line.
-> cmotion
Replaces text from the current point to the target of a motion, similar to the d command, but replacing instead of deleting.
-> C
Replaces from the current point to the end of the line, similar to c$.
-> :s/from/to/
Replaces the first instance of from in the line to to. from and to can both be normal plain text (e.g., :s/1998/1999/ replaces the first 1998 in the line to 1999) but from is more accurately described as a regular expression (which once again is outside the scope of the document).
-> :s/from/to/g
As above, but replaces all instances and not just the first.
-> /pattern
This will search from the current cursor position, through to the end of the buffer, for pattern which is a regular expression (again, in most cases you can just type in plain text).
-> ?pattern
Searches backwards from the cursor position to the beginning of the buffer for the pattern.
-> n
Repeats the last search command, with the same pattern. If you last used a /, the search will continue forward; if you last used a ?, then it proceeds backwards.
This command will not work if you have not used / or ? in the current session yet.
-> N
Similar to n, but reverses the direction of the search.
The commands mentioned in this section are all motion commands, and may be used wherever motion is called for.
Most of the commands above that have no colons can have a number typed before it for repeating the action. Examples:
Remember—the commands with colons don't behave that way.
(This section is slightly more technical—you may wish to skip it.)
The colon commands (or more precisely called ‘ex commands’, because they are used in the ex(1) editor) work with the notion of ‘ranges’, which come just after the colon. Ranges are best described by examples.
The :1 and :$ commands mentioned earlier are not really commands, but line specifications, which stand for the first line and the last line respectively.
In addition, the dot, ., stands for the current line. You can offset this by a certain number of lines by using + or - followed by a number. For example, $-3 refers to three lines up from the end, and .+5 refers to the fifth line down from the current one.
A range is specified by two line specifications separated by a comma. For example, 2,5 means between lines 2 and 5, including lines 2 and 5.
The percent symbol, %, is a shortcut for 1,$.
And now, some real-life examples. :-)
-> .
The dot command, ., repeats the last command you did that actually changed the buffer. Movement commands don't count.
-> u
The standard way to undo the last action. Note that many implementations of vi only has a single level of undo, so hitting u twice is the same as doing nothing at all (it just undid your undo).
The Berkeley vi implementation, nvi, allows multiple level undo by typing dots (it repeats your undo). Most cabbage vi implementations, though, repeat your last command (before your undo) if you type dots.
-> :w -> :w filename
The :w command saves the current buffer (analogous to ‘save’ in a graphical editor). If you specify filename, the contents of the buffer is written to a different file.
If you specify a filename, you normally won't be able to specify an already-existing file. If you must overwrite that file anyway, then add a ! after the :w.
-> :e filename -> :e!
The :e command either reloads the current file, or the file specified if filename is given. If your buffer has been modified and not yet saved, you won't be able to reload the buffer unless you add a ! after the e.
-> :r filename
Reads the contents of filename and embeds it into the current buffer.
-> :r !command
Executes command and embeds into the buffer the output generated by the command.
-> :wq -> ZZ
Both of these do pretty much the same thing—save changes made to the buffer and exit vi.
-> :q!
Quits vi, discarding all changes made to the editing buffer.