Updated: 03/13/2021 by
On Unix-like operating systems, vi (pronounced "vee-eye") is a text editor.
Description
The vi command starts the visual mode of ex, the landmark editing program developed by William Joy in the late 1970s. As ex gained popularity, Joy noticed that most users were exclusively using its visual mode, so to make things more convenient for his users, he added a link to ex which started it in visual mode automatically. Today vi is the most popular text editor among Linux users.
A more feature-rich implementation of vi named vim (which stands for "vi improved") is also available. For more information, please see our vim documentation.
Syntax
vi [ -| -s ] [-l] [-L] [-R] [ -r [ filename ] ] [-S] [-t tag] [-v] [-V] [-x] [-w] [-n ] [-C] [+command | -c command ] filenameOptions
- | -s | Suppress all interactive user feedback. This is useful when processing editor scripts. |
-l | Set up for editing LISP programs. |
-r | List the name of all files saved as the result of an editor or system crash. |
-r filename | Edit filename after an editor or system crash. Recovers the version of filename that was in the buffer when the crash occurred. |
-L | Same as -r |
-R | Readonly mode; the readonly flag is set, preventing accidental overwriting of the file. |
-S | This option is used in conjunction with the -t tag option to tell vi that the tags file may not be sorted and that, if the binary search (which relies on a sorted tags file) for tag fails to find it, the much slower linear search should also be done. Since the linear search is slow, users of large tags files should ensure that the tags files are sorted rather than use this flag. Creation of tags files normally produces sorted tags files. See ctags for more information on tags files. |
-t tag | Edit the file containing the tag tag, and position the editor at its definition. |
-V | Verbose mode. When ex commands are read by means of standard input, the input will be echoed to standard error. This may be useful when processing ex commands within shell scripts. |
-x | Encryption option; when used, vi simulates the X command of ex and prompts the user for a key. This key is used to encrypt and decrypt text using the algorithm of the crypt function. The X command makes an educated guess to determine whether text read in is encrypted or not. The temporary buffer file is encrypted also, using a transformed version of the key typed in for the -x option. If an empty encryption key is entered (that is, if the return key is pressed right after the prompt), the file will not be encrypted. This is a good way to decrypt a file erroneously encrypted with a mistyped encryption key, such as a backspace or undo key. |
-wn | Set the default window size to n. This is useful when using the editor over a slow speed line. |
-C | Encryption option; same as the -x option, except that vi simulates the C command of ex. The C command is like the X command of ex, except that all text read in is assumed to have been encrypted. |
+command | -c command | Begin editing by executing the specified editor command (usually a search or positioning command). |
filename | The file to be edited. |
Using Vi
vi is an interactive text editor that is display-oriented: the screen of your terminal acts as a window into the file you are editing. Changes you make to the file are reflected in what you see.
Using vi you can insert text anywhere in the file very easily. Most of the vi commands move the cursor around in the file. You can move the cursor forward and backward in units of characters, words, sentences, and paragraphs. Some of the operators, like d for delete and c for change, can be combined with the motion commands to make them operate on entire words, paragraphs, etc., in a natural way.
Editing a file
The most common way to start a vi session is to tell it which file to edit. To edit a file named filename, use the command:
vi filenameThe screen will clear and the text of your file will appear on the screen. If filename doesn't exist yet, vi will start you in a new file, and when you tell it to save your work, it will use the filename that you specified.
The editor's copy: the "buffer"
The editor does not directly modify the file you are editing. Instead, it makes a copy of this file in memory called the buffer. You do not actually affect the contents of the file until you write the changes you've made back into the original file.
Arrow keys
On most terminals, you can use the arrow keys to move the cursor around. Left and right moves the cursor left or right one character, and up and down move the cursor up or down one line. The other way to move the cursor is with the h, j, k, and l keys:
h | left |
j | down |
k | up |
l | right |
A bit of historical trivia: the hjkl keys are used because the original computer system Bill Joy developed with did not have separate arrow keys. Instead, the keyboard used hjkl keys as the arrow keys.
Hardcore vi users will tell you that the hjkl keys are the only "true" way to move the cursor because you can keep your hands in the typing position, but you should use whatever works best for you.
Special Keys: Esc, Return, and Delete
The Escape key is important in vi: it is used to cancel any command you've started typing, and to return to command-mode after you've been inserting or adding text. Escape is a safe key to hit if you've lost track of what mode you're in or what you're doing. You can hit it several times to return to command mode and cancel anything that you've been doing.
The Return (or "Enter") key is used to complete certain commands and execute them.
The Delete key is another "safe" key to press. It interrupts anything that the editor has been doing and brings you back to the default state of the editor, sometimes also called the "quiescent" state.
Exiting vi
The command ZZ will write the contents of the buffer into the file you are editing, and quit vi.
If there are no changes to be saved, you can also quit the editor with the command :q. If you have made changes that haven't been saved yet, the editor won't let you exit this way.
If you want to quit and discard the changes you've made, you can tell the editor you're sure you know what you're doing by quitting with the command :q!. This will exit vi immediately, and any unsaved changes will be lost.
Moving around in your file
Scrolling and paging
The editor has several commands for moving around within your file. One of the most useful of these is Control-D (also represented as ^D). This command "scrolls" down in the file (the D stands for "down"). ^U ("up") is similar: it scrolls up one page in the file. Both of these commands will also move the cursor to the new location.
If you just want to see more of the file, but leave the cursor where it is, you can use ^E to "expose" one more line at the bottom of the screen. ^Y (which doesn't stand for anything, but it's next to the U on the keyboard) exposes one line at the top of the screen.
There are other ways to move around in the file. The keys ^F and ^B move forward and backward one page (this is called "paging"), keeping a couple of lines of continuity between screens so that it is possible to read through a file using these rather than ^D and ^U if you wish.
Notice the difference between "scrolling" (^U, ^D) and "paging" (^B, ^F). Scrolling leaves more context, but paging only leaves you a couple of lines. It's up to you which one is easier for moving around and reading your file.
Searching
Another way to position yourself in the file is by giving the editor a string to search for. If you type "/" followed by a string of characters and press Enter, the editor will search for the next occurrence of this string in your file, and place the cursor there. Pressing n will go to the next occurrence after that.
If instead of forward, you want to search backward for a string, use ? instead of /. In a ? string search, pressing n will take you to successive occurrences in the same (backward) direction.
If the search string you give the editor is not present in the file, the editor will print a message letting you know it couldn't find it, and your cursor will not be moved.
If you want your search string only to match if it's at the beginning of a line, you should begin the search string with a caret ("^"). To match only at the end of a line, end the search string with a dollar sign ("$"). So using the command
/^mystringwill only find a match if "mystring" is at the very begining of a line. Similarly, the command
/mystring$will only match any occurrences of "mystring" that are at the very end of a line.
"Goto"-ing
The command G, when preceded by a number, will "goto" a line: it will go to that line number and position the cursor there. If you use G with no number, it moves the cursor to the last line of the file.
So, using the command
1GMoves your cursor to the first line in the file;
30GMoves your cursor to line 30, and
GMoves your cursor to the last line, whatever number that may be.
Finding out where you are in the file
You can find out where you're at in the file by pressing ^G. This sill show you the name of the file you are editing, the number of the current line, the number of lines in the buffer, and the percentage of the way through the buffer your cursor is currently at.
Getting back to where you just were
Any time you move the cursor in any of these ways, you can move the cursor back to where it just was by typing `` (two back quotes). So, if you type
Gto move to the end of the file, but then you realize you need to get back to where you were (whether you remember where that is or not), you can type
``To get back to your original location. This also works after performing a search. Remember this command, because it's very useful!
Lines past the end of your file
If you're near the end of your file, and the last line is not at the bottom of the screen, vi will print a tilde ("~") on any lines after the end of your actual file. This indicates that the last line of your file is on the screen; that is, any lines showing "~" are past the end of your file. You'll notice this, for instance, when you start editing a new file: every line will begin with a tilde.
Moving around on the screen
As we've already mentioned, you can use the arrow keys or h, j, k, and l to move the cursor left and right one cursor, or up and down one line.
You can also use + to move to the next line or - to move to the previous line. This is similar to using up and down (or j and k), except that your cursor will automatically be placed at the first non-whitespace character on the line.
Any of these keys, if they would take you before the first line on the screen or after the last line, will scroll the display one line in the correct direction. Pressing the Return key is the same as pressing +. You can also position the cursor at the top, middle, or bottom of the currently-displayed screen of text:
H will take you to the top ("home") line on the screen. Preceding H with a number will take you to the home line plus that number of lines. For instance, 3H moves your cursor to the third line of text displayed on the screen.
M is a similar command: it moves your cursor to the middle of the screen.
L moves your cursor to the last line of the screen. If you precede it with a number, it moves your cursor to that number of lines before the last line displayed. So 5L moves your cursor to the fifth-to-last line currently displayed.
Moving within a line
w will advance the cursor to the next word on the line, and b will back up the cursor to the previous word.
e advances you to the end of the current word rather than the beginning of the next word.
If words are punctuated, for instance with an apostrophe or a comma, w and b will stop at the punctuation. If you use W and B instead, they move the cursor while ignoring punctuation.
These commands all wrap at the end (or beginning) of a line, moving to the previous or next line if their search for the next or previous word goes that far.
Summary: movement keys
Here's a recap of the movement keys we just discussed, and a few extras.
Spacebar | advance the cursor one position |
^B | page backward |
^D | scroll down |
^E | expose a line at the bottom of the screen |
^F | page forward |
^G | Positional status check |
^N | next line, same column |
^P | previous line, same column |
^U | scroll up |
^Y | expose a line at the top of the screen |
+ | next line, at the first non-whitespace character |
- | previous line, at the first non-whitespace character |
/string | Scan forward for string. If no string is specified, scans for the last string scanned for. |
? | Scan backwards for string. If no string is specified, scans for the last string scanned for. |
B | backwards one word, ignoring punctuation |
linenumberG | Go to specified linenumber (an integer). Defaults to the last line. |
H | move cursor to first line of screen |
M | middle line of screen |
L | last line of screen |
W | forward a word, ignoring punctuation |
b | backwards a word |
e | end of current word |
n | next instance of / or ? search pattern |
w | next word |
Making simple changes
The most basic command for making changes to your file is the i (insert) command. After you type i, everything you type until you hit Esc is inserted at your cursor position into the buffer.
The companion to the i command is the a ("append") command. This works exactly like i, except it starts inserting the text after the cursor location, not at the cursor location.
Sometimes, you want to start editing on a new line right after the line your cursor is at. To do this, use the o command. To start a new line before the line your cursor is at, use the O command. Just like with i and a, any text you type will be inserted into the buffer until you press Esc.
While you are inserting text with any of these commands, you can use ^W to erase a whole word and leave your cursor one space after the previous word
One thing to note is that when you backspace, you will not erase any characters that you haven't inserted. Also, you can't backspace to the previous line; backspacing will stop when you get to the beginning of the current line.
Making small corrections
It's easy to make small corrections in vi. If you need to remove a character that shouldn't be there, move the cursor over it and press x to delete it. You can also supply a number before pressing x, and it will delete that many characters. So if you have the word "discovery", and you move the cursor over the v and type
4x...you will be left with the word "disco".
If you want to replace a single character with another character, move the cursor over it and press r and then the character that should replace it. So, if you type "mistoke", and move the cursor over the "o" and type
ra...the o will be replaced with an a, leaving you with the word "mistake."
The R command is similar, but you can use it to replace more than one character; if you press R and start typing, every character you type will replace every character that was already there. So, if you have the word "mistake", and you move the cursor over the letter t and type
Rsile...you will see that the word "mistake" has turned into the word "missile". You might also notice that if you backspace in this mode, your original text will be restored, letter by letter. When you're done, press Esc to stop replacing characters.
Operators
The command d acts as a delete operator: pressing d and then a movement key will delete wherever the cursor would have moved. For instance, typing dw will delete the next word, and typing db will delete backwards to the previous word. Typing dSPACE will delete one character; this is the same as typing x.
Another useful operator is c, which stands for change. The command cw will change a single word: it will delete everything to the end of a word, and place you into insert mode to type the text that should replace it.
Repeating a change
Any time you make a change with a command, you can type "." to repeat the change. So if you delete a word with dw, typing . will delete the next word as well. You can repeat this over and over by typing . several times, like an ellipsis ("...").
Operating on lines
Typing dd will delete an entire line.
Typing cc will change an entire line, deleting it and placing you in insert mode.
You can delete or change more than one line at a time by preceding dd or cc with a number. For instance, 5dd will delete 5 lines. You can also give a command like dL which will delete every line from the cursor up to and including the last line on the screen, or d3L which will delete every line from the cursor to the third-to-last line. When you make big changes like this, especially if you make changes that go beyond what you can see in one screen, the editor gives you a message telling you what's been done.
Undoing
To undo the last change, type u. To re-do (to undo an undo), type u again.
Unlike vim, vi only offers one level of undo. However, you can use U (capital U) to undo any changes that were made to the current line; pressing U restores the current line to the way it was before you started changing it.
Summary: making changes
SPACE | Advance the cursor one position. |
^W | Erase a word during insert. |
. | Repeats the last change command. |
O | Opens and inputs a new line, above the current line. |
U | Undoes the changes you made to the current line. |
a | Appends text after the cursor. |
c | Changes the object you specify to the text you type in after. |
d | Deletes the object that you specify. |
i | Inserts text before the cursor. |
o | Opens and inputs new lines, below the current line. |
u | Undoes the last change. |
Rearranging and duplicating text
Low-level character motions
fx moves the cursor finds the next x character on the current line. After that, if you press ; your cursor moves to the next occurrence of the same character. F is a similar command, but searches backwards in the same line, rather than forwards.
The f and F commands can be combined, for example, with the d command. Typing dfx will delete everything from the cursor through the next occurrence of x in the line. Sometimes you want to delete up to, but not including, the next occurrence of character x. In this case, use the command dtx. t stands for "to".
The beginning of the line is represented by zero ("0"), the caret ("^") represents the first non-whitespace character on the line, and the end of the line is represented by the dollar sign ("$"). If you press ^, the cursor will be placed at the first non-whitespace character of the line; if you press 0, the cursor will be placed at the beginning of the line; and if you press $, the cursor will be placed at the end of the line.
To delete everything from the cursor to the end of the line, type d$. To delete everything from the cursor to the beginning of the line, type d0... and so on.
Higher-level text objects
Sometimes it's helpful to move around in units of entire sentences. The ( and ) commands move to the beginning of the previous and next sentences, respectively. So the command d) deletes everything through the end of the current sentence; and d( deletes everything through the beginning of the current sentence, or the entire previous sentence if you're already at the beginning of a sentence.
A sentence is defined as ending at a period ("."), exclamation point ("!"), or question mark ("?") which is followed either by the end of the line or a space. Any number of closing ), ], ", and ' characters may appear after the ., ?, or ! before the space or the end of the line.
The { and } commands move over paragraphs, and the operations [[ and ]] move over sections. A "section" can be defined by a special macro, or by a formfeed at the beginning of a line.
Rearranging and duplicating text
The editor has a special unnamed buffer where the last deleted or changed-away text is saved, and a set of named buffers a through z which you can use to save copies of text and to move text around in your file (or files).
The y command "yanks" a copy of an object into the unnamed buffer. If preceded by a buffer name, it places this object into the named buffer. The way to specify the buffer is double quotes ("), then a letter a-z, then the y command. So "ay will yank an object into the buffer named a.
Text in a buffer (either the unnamed buffer or one of your named buffers) can be pasted into your document with the commands p or P. p will paste the buffer contents after the cursor location (much like an append), and P will paste the buffer contents at the cursor location (much like an insert).
If the text which you yank forms part of a line, or is an object such as a sentence which partially spans more than one line, then when you put the text back, it will be placed after the cursor (or before it if you used P). If the yanked text forms whole lines, they will be put back as whole lines, without changing the current line. In this case, the paste acts much more like an o or O command. So, the command YP will make a copy of the current line and place you at the location of the copy, which is placed before the current line. Y is a convenient abbreviation for yy.
The command Yp will also make a copy of the current line, and place it after the current line. You can give Y a number of lines to yank, and thus duplicate several lines; for instance, 3YP will duplicate three lines, and place them before the current line.
To move text within the buffer, you need to delete it in one place, and put it back in another. You can precede a delete operation by the name of a buffer in which the text is to be stored, as in "a5dd, which deletes 5 lines into the named buffer a. You can then move the cursor to the eventual resting place of these lines and do a "ap or "aP to put them back. In fact, you can switch and edit another file before you put the lines back, by giving a command of the form :e name, where name is the name of the other file you want to edit. You will have to write the contents of the current editor buffer (or discard them) if you have made changes, before the editor will allow you to edit a new file.
An ordinary delete command saves the text in the unnamed buffer, so that an ordinary paste will place it back in the file. However, the unnamed buffer is lost when you change files, so to move text from one file to another you should use a named buffer.
Summary of moving and rearranging text
^ | First non-whitespace character on line. |
0 | Beginning of the line. |
$ | End of the line. |
) | Forward to next sentence break. |
( | Backward to previous sentence break. |
} | Forward to next paragraph break. |
{ | Backward to previous paragraph break. |
]] | Forward to next section break. |
[[ | Backward to previous section break. |
fx | Find character x forward in the line. |
Fx | Find character x backward in the line. |
p | Paste text after cursor. |
P | Paste text before cursor. |
y | Yank. |
Y | Yank a whole line. |
t | Forward to character x, for operations. |
Tx | Back to character x, for operations. |
High level commands
Writing, quitting, and editing new files
So far we have seen how to write our file to disk and quit (ZZ), or simply write our file and continue editing(:w).
If you have changed your file but you want to quit without saving, use the command :q!. The command :q quits the editor, but it will only let you do this if you haven't made any changes since your last write (your last save). The exclamation point, however, tells the editor "yes, I really want to do this."
Similarly, you can edit another file with the :e name command, where name is the name of the file you want to edit. But the editor won't let you do this if you have unsaved changes. However, if you use the exclamation mark again (:e! name), the editor will do as you ask: it will discard your changes and open file name for editing.
If you don't specify a file name, and just use the command :e!, the editor will re-load your saved version of the file you're working on. This is like the "revert" command in other file editors. It will discard your changes, and revert to the last-saved version of the file.
Escaping to the shell
If you want run a shell command without exiting the editor, you can use the command :!command. The system will run the command command, and when the command finishes, the editor will ask you to press Enter before returning you to the editing screen. You can also give another : command when it asks you to press Enter; this will run the next command without redrawing the screen.
If you want to drop entirely to your shell's command prompt, use the command :sh. This will drop you into your shell, where you can use it as you normally would; when you're done, type Control-D (^D), and you will be returned to vi.
On many systems, you can also simply type ^Z from within the editor at any time to drop into your shell. This technically puts vi in the background. To return to vi, type fg ("foreground") at your shell command prompt, and vi will become your foreground process again.
Marking and returning
As already mentioned, the command `` (two back quotes) returns you to the previous place after a motion of the cursor by a command such as /, /, or G. You can also mark your position in the file with single-letter tags and return to these marks later. The marking is done with the command mx, where x is the letter you want to assign to the mark. To return to the place that you marked, you can use the command `x
For example, if you type ma, you will mark the current cursor position with the letter a. Then, if you move the cursor anywhere else in the file, you can always return to that line with the command `a. Marks last until you start editing another file, or until you overwrite the mark by setting it somewhere else.
When using operators such as d and referring to marked lines, sometimes you'll want to refer to the line that you marked, and not the actual cursor position within the line. At any time, you can use 'x (as opposed to `x) to refer to the line itself. So, the command d`a will delete everything from the current cursor position up to the exact position at mark a, whereas the command d'a will delete everything up to (and including) the entire line where mark a resides.
Used without an operator, 'x moves you to the first non-whitespace character in the line where mark x resides.
Adjusting the screen
If the screen image is messed up for any reason, you can refresh the screen with Control-L (^L).
If you want to center the screen on your cursor at any time, type z-. To adjust the screen so that the line with your cursor is at the top of the screen, type z and press Enter. To adjust the screen so that the line with your cursor is at the bottom of the screen, type z..
zz is the same as z-, and will center the screen so that the line with your cursor is at the center of the screen.
Special topics
Setting options, and using editor startup files
The editor has a set of options, which you can set with the :set command. To set option opt to value val, use the command :set opt=val.
Toggle options can be set with the commands set opt, and unset with the command set noopt.
Here are some of the most useful options you can set:
autoindent | noai | Supply indentation automatically |
autowrite | noaw | Automatically write to file while editing |
ignorecase | noic | Ignore case when searching |
lisp | nolisp | (, {, ), and } commands deal with S-expressions |
list | nolist | Tabs print as ^I; end of lines marked with $ |
magic | nomagic | The characters ., [, and * are special ("magical") in scans |
number | nonu | Lines are displayed prefixed with their line numbers |
paragraphs | para=IPLPPPQPbpP | LI Macro names which start paragraphs |
redraw | nore | Simulate a smart terminal on a dumb terminal |
sections | sect=NHSHH | HU Macro names which start new sections |
shiftwidth | sw=8 | Shift distance for <, >, and other "shift" commands |
showmatch | nosm | Show matching ( or { locations as ) or } is typed, for example |
showmode | nosmd | Show input mode description |
slowopen | slow | Postpone display updates during inserts |
term | dumb | The kind of terminal you are using |
These statements can be placed in the environment variable EXINIT, or can be given while you are running vi by preceding them with a :, as described above.
You can view a list of all options and their settings by typing :set within vi at any time. To view the current setting of a particular option, use the command :set opt?.
set can be abbreviated as se. Multiple options can be set on one line, for instance :se ai aw nu.
Options set with :set only last for your current editor session.
If you want to place your default settings into the environment variable EXINIT so that they are loaded every time you run vi, you can specify multiple commands on a single line by separating them with the vertical bar ("|"). For instance, if your shell is csh, you could set EXINIT with the following shell command:
setenv EXINIT 'set ai aw terse|map @ dd|map # x'Recovering lost lines
You might have a problem if you delete several lines and then want them back. However, the editor saves the last 9 deleted blocks of text in a set of registers numbered 1 through 9. You can get the nth previous deleted text back in your file by the command "np. These are similar to your named buffers, except they refer to the number of the previous block of text that was deleted.
Usually, when you type a single period ("."), it repeats the last change you've made. As a special case, when this period repeats a change that refers to a numbered buffer, the number is incremented before the command is repeated. Let's see how this works, and why it's useful:
Let's say you deleted something important, and you know it's in one of your nine previous block-deletes, but you're not sure which one. If you want to go back and look at all nine previously deleted blocks, here's how you could do it: you could use the command
"1pTo paste the contents of the most recently-deleted text (buffer number 1). If that's not the text you wanted, you could then undo (u) and repeat the command with ., pasting the command of buffer 2. In other words, typing the command
"1pu.u.u.u.is the same as typing
"1pu"2pu"3pu"4pu"5pand you can go back in the numbered buffers easily until you find the text you want to have back.
The command P can, of course, be used instead of p in the above example, to place the text before the cursor instead of after it.
Recovering lost files
If the system crashes, you can recover the work you were doing to within a few changes. When you get back into your system, use this command to start vi:
vi -r nameWhere name is the name of the file you were editing. This will recover your work to a point as close as possible to where you left off.
If you don't specify a file with name and instead just type
vi -rthen you will receive a list of files which can be recovered.
Continuous text input
When you are typing in large amounts of text it is convenient to have lines broken near the right margin automatically. You can cause this to happen by giving the command :se wm=10. This causes all lines to be broken at a space at least 10 columns from the right hand edge of the screen.
If the editor breaks an input line and you wish to put it back together you can tell it to join the lines with J. You can give J a count of the number of lines to be joined as in 3J to join 3 lines. The editor supplies white space, if appropriate, at the juncture of the joined lines, and leaves the cursor at this white space. You can kill the white space with x if you don't want it.
Features for editing programs
The editor has a number of commands for editing programs. The thing that most distinguishes editing of programs from editing of text is the indented structure to the body of the program. The editor has an autoindent facility for helping you generate correctly indented programs.
To enable this facility you can give the command :se ai. Now try opening a new line with o and type some characters on the line after a few tabs. If you now start another line, notice that the editor supplies white space at the beginning of the line to line it up with the previous line. You cannot backspace over this indentation, but you can use ^D key to backtab over the supplied indentation.
Each time you type ^D you back up one position, normally to an 8 column boundary. This amount is settable; the editor has an option called shiftwidth which you can set to change this value. Try giving the command :se sw=4 and then experimenting with autoindent again.
For shifting lines in the program left and right, there are operators < and >. These shift the lines you specify right or left by one shiftwidth. Try << and >> which shift one line left or right, and <L and >L shifting the rest of the display left and right.
If you have a complicated expression and wish to see how the parentheses match, put the cursor at a left or right parenthesis and hit %. This will show you the matching parenthesis. This works also for braces { and }, and brackets [ and ].
If you are editing C programs, you can use the [[ and ]] keys to advance or retreat to a line starting with a {, i.e. a function declaration at a time. When ]] is used with an operator it stops after a line which starts with }; this is sometimes useful with y]].
Filtering portions of the buffer
You can run system commands over portions of the buffer using the operator ! (the exclamation point). Essentially, it sends a section of your file as standard input to a shell command, then replaces that portion of your text with the standard output of the command.
All together, the way to specify what text to send and what command to send it to, is !(movement-specifier) command-name. The movement-specifier could be w for operating on the next word, for instance, or } for the next paragraph, etc. The command-name is the shell command, and any arguments it may take.
This is especially useful for sorting using the sort command. You can use this to sort lines in your file. For instance, if you were to type in a list of random words, one per line, and end them with a blank line, then you backed up to the beginning of the list and gave the command !}sort, this would sort the data you just typed in, right before your eyes. This is a very powerful function! Try it for yourself.
Commands for editing LISP code
If you are editing a LISP program you should set the option lisp by doing :se lisp. This changes the ( and ) commands to move backward and forward over s-expressions. The { and } commands are like ( and ) but don't stop at atoms. These can be used to skip to the next list, or through a comment quickly.
The autoindent option works differently for LISP, supplying indent to align at the first argument to the last open list. If there is no such argument then the indent is two spaces more than the last level.
There is another option that is useful for typing in LISP, the showmatch option. Try setting it with :se sm and then try typing a "(", some words, and then a ")". Notice that the cursor shows the position of the "(" which matches the ")" briefly. This happens only if the matching "(" is on the screen, and the cursor stays there for at most one second.
The editor also has an operator to realign existing lines as though they had been typed in with lisp and autoindent set. This is the = operator. Try the command =% at the beginning of a function. This will realign all the lines of the function declaration.
When you are editing LISP, the [[ and ]] advance and retreat to lines beginning with a (, and are useful for dealing with entire function definitions.
Macros
vi has a parameterless macro facility, which lets you set it up so that when you hit a single keystroke, the editor will act as though you had hit some longer sequence of keys. You can set this up if you find yourself typing the same sequence of commands repeatedly.
There are two general kinds of macros:
- Ones where you put the macro body in a named macro buffer x. You can then type @x to invoke the macro. The @ may be followed by another @ to repeat the last macro.
- You can use the map command from vi (typically in your EXINIT environment variable) with a command of the form::map lhs rhsCR mapping lhs into rhs. There are restrictions: lhs should be one keystroke (either 1 character or one function key) since it must be entered within one second (unless notimeout is set, in which case you can type it as slowly as you wish, and vi will wait for you to finish it before it echoes anything). The lhs can be no longer than 10 characters, the rhs no longer than 100. To get a space, tab or newline into lhs or rhs you should escape them with a ^V. It may be necessary to double the ^V if the map command is given inside vi, rather than in ex. Spaces and tabs inside the rhs need not be escaped.
Thus to make the q key write and exit the editor, you can give the command
:map q :wq^V^VCR CRwhich means that whenever you type q, it will be as though you had typed the four characters :wqCR. A ^V's is needed because without it the carriage return would end the : command, rather than becoming part of the map definition. There are two ^V's because from within vi, two ^V's must be typed to get one. The first CR is part of the rhs, the second terminates the : command.
Macros can be deleted with
unmap lhsIf the lhs of a macro is "#0" through "#9", this maps the particular function key instead of the 2 character "#" sequence. So that terminals without function keys can access such definitions, the form "#x" means function key x on all terminals (and need not be typed within one second). The character "#" can be changed using a macro in the usual way:
:map ^V^V^I #to use tab, for example. This won't affect the map command, which still uses #, but just the invocation from visual mode.
The undo command reverses an entire macro call as a unit, if it made any changes.
Placing a "!" after the word map causes the mapping to apply to input mode, rather than command mode. Thus, to arrange for ^T to be the same as 4 spaces in input mode, you can type:
:map! ^T ^Vb/b/b/b/where b/ is a blank. The ^V is necessary to prevent the blanks from being taken as white space between the lhs and rhs.
Word abbreviations
A feature similar to macros in input mode is word abbreviation. This allows you to type a short word and have it expanded into a longer word or words. The commands are :abbreviate and :unabbreviate (:ab and :una) and have the same syntax as :map. For example:
:ab eecs Electrical Engineering and Computer Sciencescauses the word "eecs" to always be changed into the phrase "Electrical Engineering and Computer Sciences". Word abbreviation is different from macros in that only whole words are affected. If "eecs" were typed as part of a larger word, it would be left alone. Also, the partial word is echoed as it is typed. There is no need for an abbreviation to be a single keystroke, as it should be with a macro.
Technical details
Line representation in the display
The editor folds long logical lines onto many physical lines in the display. Commands which advance lines advance logical lines and will skip over all the segments of a line in one motion. The command | moves the cursor to a specific column, and may be useful for getting near the middle of a long line to split it in half.
The editor only puts full lines on the display; if there is not enough room on the display to fit a logical line, the editor leaves the physical line empty, placing only an @ on the line as a place holder. When you delete lines on a dumb terminal, the editor will often just clear the lines to @ to save time (rather than rewriting the rest of the screen). You can always maximize the information on the screen by giving the ^R command.
If you wish, you can have the editor place line numbers before each line on the display. Give the command :se nu to enable this, and the command :se nonu to turn it off. You can have tabs represented as ^I and the ends of lines indicated with "$" by giving the command :se list; :se nolist turns this off.
Finally, lines consisting of only the character "~" are displayed when the last line in the file is in the middle of the screen. These represent physical lines that are past the logical end of file.
More file manipulation commands
The following table lists the file manipulation commands which you can use when you are in vi.
:w | Write back changes. |
:wq | Write and quit. |
:x | Write (if necessary) and quit (same as ZZ). |
:e name | Edit file name. |
:e! | Reedit, discarding changes. |
:e + name | Edit, starting at end. |
:e +n | Edit, starting at line n. |
:e # | Edit alternate file. |
:w name | Write file name. |
:w! name | Overwrite file name. |
:x,yw name | Write lines x through y to name. |
:r name | Read file name into . |
:r !cmd | Read output of cmd into buffer |
:n | Edit next file in argument list. |
:n! | Edit next file, discarding changes to current. |
:n args | Specify new argument list. |
:ta tag | Edit file containing tag tag, at tag. |
All of these commands are followed by a CR or Esc. The most basic commands are :w and :e. A normal editing session on a single file will end with a ZZ command. If you are editing for a long period of time you can give :w commands occasionally after major amounts of editing, and then finish with a ZZ. When you edit more than one file, you can finish with one with a :w and start editing a new file by giving a :e command, or set autowrite and use :n file.
If you make changes to the editor's copy of a file, but do not wish to write them back, then you must give an ! after the command you would otherwise use; this forces the editor to discard any changes you have made. Use this carefully.
The :e command can be given a + argument to start at the end of the file, or a +n argument to start at line n. In actuality, n may be any editor command not containing a space, usefully a scan like +/pat or +?pat. In forming new names to the e command, you can use the character % which is replaced by the current file name, or the character # which is replaced by the alternate file name. The alternate file name is generally the last name you typed other than the current file. Thus if you try to do a :e and get a diagnostic that you haven't written the file, you can give a :w command and then a :e # command to redo the previous :e.
You can write part of the buffer to a file by finding out the lines that bound the range to be written using ^G, and giving these numbers after the : and before the w, separated by ,'s. You can also mark these lines with m and then use an address of the form 'x,'y on the w command here.
You can read another file into the buffer after the current line using the :r command. You can similarly read in the output from a command, just use !cmd instead of a file name.
If you wish to edit a set of files in succession, you can give all the names on the command line, and then edit each one in turn using the command :n. It is also possible to respecify the list of files to be edited by giving the :n command a list of file names, or a pattern to be expanded as you would have given it on the initial vi command.
If you are editing large programs, the :ta command is very useful. It utilizes a data base of function names and their locations, which can be created by programs such as ctags, to quickly find a function whose name you give. If the :ta command requires the editor to switch files, then you must :w or abandon any changes before switching. You can repeat the :ta command without any arguments to look for the same tag again.
More about searching for strings
When you are searching for strings in the file with / and ?, the editor normally places you at the next or previous occurrence of the string. If you are using an operator such as d, c or y, then you may well wish to affect lines up to the line before the line containing the pattern. You can give a search of the form /pat/-n to refer to the n'th line before the next line containing pat, or you can use + instead of - to refer to the lines after the one containing pat. If you don't give a line offset, then the editor affects characters up to the match place, rather than whole lines; thus use "+0" to affect to the line which matches.
You can have the editor ignore the case of words in the searches it does by giving the command :se ic. The command :se noic turns this off.
Strings given to searches may actually be regular expressions. If you do not want or need this facility, you should
set nomagicin your EXINIT. In this case, only the characters ^ and $ are special in patterns. The character \ is also then special (as it is most everywhere in the system), and may be used to get at the an extended pattern matching facility. It is also necessary to use a \ before a / in a forward scan or a ? in a backward scan, in any case. The following table gives the extended forms when magic is set.
^ | At beginning of pattern, matches beginning of line. |
$ | At end of pattern, matches end of line. |
. | Matches any character. |
\< | Matches the beginning of a word. |
\> | Matches the end of a word. |
[str] | Matches any single character in str. |
[str] | Matches any single character not in str. |
[x-y] | Matches any character between x and y. |
* | Matches any number of the preceding pattern. |
If you use nomagic mode, then the . [ and * primitives are given with a preceding \.
More about input mode
There are a number of characters which you can use to make corrections during input mode. These are summarized in the following table.
^H | Deletes the last input character. |
^W | Deletes the last input word, defined as by b. |
erase | Your erase character, same as ^H. |
kill | Your kill character, deletes the input on this line. |
\ | Escapes a following ^H and your erase and kill. |
Esc | Ends an insertion. |
Del | Interrupts an insertion, terminating it abnormally. |
CR | Starts a new line. |
^D | Backtabs over autoindent. |
0^D | Kills all the autoindent. |
^^D | (Caret-control-D) same as 0^D, but restores indent next line. |
^V | Quotes the next non-printing character into the file. |
The most usual way of making corrections to input is by typing ^H to correct a single character, or by typing one or more ^W's to back over incorrect words. If you use # as your erase character in the normal system, it will work like ^H.
Your system kill character, normally @, ^X or ^U, will erase all the input you have given on the current line. In general, you can neither erase input back around a line boundary nor can you erase characters which you did not insert with this insertion command. To make corrections on the previous line after a new line has been started you can hit Esc to end the insertion, move over and make the correction, and then return to where you were to continue. The command A which appends at the end of the current line is often useful for continuing.
If you wish to type in your erase or kill character (say # or @) then you must precede it with a \, just as you would do at the normal system command level. A more general way of typing non-printing characters into the file is to precede them with a ^V. The ^V echoes as a ^ character on which the cursor rests. This indicates that the editor expects you to type a control character. In fact, you may type any character and it will be inserted into the file at that point.
If you are using autoindent you can backtab over the indent which it supplies by typing a ^D. This backs up to a shiftwidth boundary. This only works immediately after the supplied autoindent.
When you are using autoindent you may wish to place a label at the left margin of a line. The way to do this easily is to type ^ and then ^D. The editor moves the cursor to the left margin for one line, and restore the previous indent on the next. You can also type a 0 followed immediately by a ^D if you wish to kill all the indent and not have it come back on the next line.
Uppercase-only terminals
If your terminal has only upper case, you can still use vi using the normal system convention for typing on such a terminal. Characters which you normally type are converted to lower case, and you can type upper case letters by preceding them with a \. The characters { ~ } | ` are not available on such terminals, but you can escape them as \( \^ \) \! \'. These characters are represented on the display in the same way they are typed.
Vi and ex
vi is actually one mode of editing within the editor ex. When you are running vi you can escape to the line oriented editor of ex by giving the command Q. All the : commands which were introduced above are available in ex. Likewise, most ex commands can be invoked from vi using :. Just give them without the : and follow them with a CR.
In rare instances, an internal error may occur in vi. In this case, you get a diagnostic and be left in the command mode of ex. You can then save your work and quit if you wish by giving a command x after the : which ex prompts you with, or you can reenter vi by giving ex a vi command.
There are a number of things which you can do more easily in ex than in vi. Systematic changes in line-oriented material are particularly easy. You can read the advanced editing documents for the editor ed to find out a lot more about this style of editing. Experienced users often mix their use of ex command mode and vi command mode to speed the work they are doing.
Quick reference
This is a summary of all the most useful vi commands. Refer to it any time you need to remember any of vi's functions quickly, and at a glance.
Entering/leaving the editor
From the command line:
vi name | Launch vi, and load the file name. |
vi + n name | Launch vi, and load file name, placing the cursor at line n. |
vi -t tag | Launch vi, and start editing at tag. |
vi -r | List files that can be recovered. |
vi -r name | Launch vi, and recover previously-edited file name. |
vi name1 name2 ... | Launch vi, loading file name1 for editing; any other files named are loaded with the :n command. |
vi -R name | Launch vi, and load file name in read-only mode. |
From within vi:
ZZ | Exit from vi, saving changes. |
^Z | Background vi and return to the command shell. Resume foreground vi operation with the fg shell builtin command. |
File manipulation
:w | Write changes (save the file). |
:wq | Write changes (save) and quit. |
:q | Quit immediately, if there are no unsaved changes. |
:q! | Quit immediately, discarding any unsaved changes. |
:e name | Edit file name. |
:e! | Revert to the last-saved version of the current file. |
:e + name | Load file name for editing, placing the cursor at the end of the file. |
:e +n name | Load file name for editing, starting at line n. |
:e # | Edit alternate file. |
^^ | (Control-caret). synonym for :e #. |
:w name | Write to file name (save as...). |
:w! name | Overwrite file name. |
:sh | Drop to command line shell; ^D to return. |
:!cmd | Run shell command cmd, then return to vi. |
:n | Edit next file that was specified as an argument to vi. |
:n args | Specify new argument list of files for vi to edit. |
:f | Show current file being edited, and current line count. |
^G | Synonym for :f. |
:ta tag | To tag file entry tag. |
^] | Same as :ta, and the following word is the tag. |
Positioning within file
^F | Position forward one screenful. |
^B | Position backward one screenful. |
^D | Scroll down one half-screenful. |
^U | Scroll up one half-screenful. |
numG | Goto line num (the last line if num not specified). |
/pat | Search for next occurrence of pattern pat. |
?pat | Search for previous occurrence of pattern pat. |
n | Repeat last search, in last search direction. |
N | Repeat last search, in the opposite of last search direction. |
/pat/+n | Search to the nth line after next occurrence of pattern pat. |
?pat?-n | Search to the nth line before the previous occurrence of pattern pat. |
]] | Move to next section/function. |
[[ | Move to previous section/function. |
% | Find matching (, ), {, or }. |
Insert and replace
The Esc key exits each of the following text-entry modes, except for r, which is only used to enter a single character.
i | Insert mode: text is inserted before the cursor. |
a | Append mode: text is appended after the cursor. |
A | Text is appended at the end of the line. |
I | Text is inserted at the beginning of the line. |
o | Open a new line, after the current line, for text entry. |
O | Open a new line, before the current line, for text entry. |
rx | Replace a the character under the cursor with character x. |
R | Replace multiple characters. |
Line positioning
H | Move cursor to the first ("home") line of the window. |
L | Move cursor to the last line of the window. |
M | Move cursor to the middle line of the window. |
+ | Move cursor to the first non-whitespace character of the next line. |
- | Move cursor to the first non-whitespace character of the previous line. |
CR | (Carriage return/the Enter key.) same as +. |
down or j | Next line, same column. |
up or k | Previous line, same column. |
Character positioning
^ | Move cursor to first non-whitespace character on the line. |
0 | Move cursor to beginning of line. |
$ | Move cursor to end of line. |
right or l or SPACE | Move cursor forward one character. |
left or h or ^H | Move cursor back one character. |
fx | Find the next occurrence of character x in the line. |
Fx | Find the previous occurrence of character x in the line. |
tx | Move up to x forward. |
Tx | Move back to x backward. |
; | Repeat last f, F, t, or T. |
, | Inverse of ;. |
num| | Move to column num. |
Operators
(Each of these commands can be used twice to affect entire lines):
d | Delete. |
c | Change (like delete, but places you in insert mode to enter the text it should change to). |
< | Shift line left shiftwidth number of spaces. |
> | Shift line right shiftwidth number of spaces. |
!(movement-command)shell-command | Filter text through a shell command. |
= | Indent for LISP. |
y | Yank lines into buffer. |
Words, sentences, paragraphs
w | Word forward. |
b | Word backward. |
e | End of word. |
) | To next sentence break. |
} | To next paragraph break. |
( | To previous sentence break. |
{ | To previous paragraph break. |
W | To next blank-delimited word. |
B | To previous blank-delimited word. |
E | To end of blank-delimited word. |
Yank to buffer, and paste from buffer
p | Paste after cursor. |
P | Paste before cursor. |
"xp | Paste from buffer x. |
"xy | Yank into buffer x. |
"xd | Delete into buffer x. |
Undo, redo, retrieve
u | Undo last change. |
U | Restore current line. |
. | Repeat last change. |
"dp | Retrieve dth last delete. |
Marking and returning
`` | Go to previous location. |
'' | Go to previous location, at first non-whitespace in line. |
mx | Mark position with letter x. |
`x | Move to the position marked x. |
'x | Move to the position marked x, at the first non-whitespace character in the line. |
Miscellaneous operations
C | Change rest of line. |
D | Delete rest of line. |
s | Substitute characters. |
S | Substitute lines. |
J | Join lines. |
x | Delete a single character. |
X | Delete a single character before the cursor. |
Y | Yank a line; same as yy. |
Adjusting the screen
^L | Clear and redraw. |
z(Enter) | Redraw screen with current line at top. |
z- | Redraw screen with current line at bottom. |
z. | Redraw screen with current line at center. |
zz | Same as z.. |
^E | Scroll window down one line (but don't move cursor). |
^Y | Scroll window up one line (but don't move cursor). |
Useful command combinations
dw | Delete a word. |
de | Delete a word, leaving any of its punctuation intact. |
dd | Delete a line. |
3dd | Delete 3 lines (for example). |
cwnew | Change word to new. |
eas | Pluralize a word (stick an s at the end of it). |
xp | Transpose two characters. |
Examples
vi myfile.txtEdits the file myfile.txt.
- How to save a file in Linux after using the vi command.
ctags — Create tag files for source code.
ed — A simple text
editor.
edit — A text editor.
ex — Line-editor mode of the vi text editor.
pico — A simple text editor.
vim — An advanced version of
vi.
vipw — Safely edit the password file.