About this Tutorial

Based on "An Introduction to Display Editing with Vi" by William Joy and Mark Horton of UC Berkeley.

Created: 30 Aug 2012

Last updated: 31 Aug 2012

Demonstration of vi syntax: More editing commands

Table 4-1 from "Learning vi and vim editors" book: More editing commands




From cursor to…




Top of screen




Bottom of screen




Next line




Column 5 of current line




Second sentence following




Previous paragraph








Next pattern




End of file




Line number 13

[Special Topics] Editing on a slow terminal: setting window size

If you are using a slow terminal, are on a slow connection or on a heavily loaded host, you can speed up editing by reducing your display window size so vi can redraw it faster.

Changing window size

zxCR will set window size to x lines and redraw the screen.

Default window size in original vi

Terminal speed

Default window size

< 1200 baud

8 lines

1200 baud

16 lines

> 1200 baud

full screen (24 lines)

[Special Topics] Editing on a slow terminal: redrawing the window to reposition a line

zCR Place line on the 1st line of the display.

z. Place line in the center of the display.

z- Place line in the last line of the display.

[Special Topics] Editing on a slow terminal: redrawing the window to reposition a line

xzCR Place line x on the 1st line of the display.

xz. Place line x in the center of the display.

xz- Place line x in the last line of the display.

[Special Topics] Editing on a slow terminal: resizing and redrawing the window

Current POSIX spec (2008) allows to resize window and reposition text all in one command but vim 7.3 does not suppport that yet.




vim 7.3 was tested against the POSIX spec in 2005, so presumably was tested against the 2004 edition of POSIX.

[Special Topics] Setting Options

The options are of three kinds:

You can set numeric and string options by

set opt=val

You can set or unset toggle options by

set opt

set noopt

[Special Topics] Useful Options






Supply indentation automatically



Automatic write before :n, :tag, etc.



Ignore case in searching



Tabs print as ^I; end of lines marked with $



Lines are displayed prefixed with line numbers



Shift distance for <, > and input D and T



Show matching ( or { as ) or } is typed

[Special Topics] Setting Options: in vi

Set options while you are running vi:

:set optCR

:set opt=valCR

[Special Topics] Setting Options: in shell

Options set by the set command only last while you stay in the editor.

To make these options persist, add them to your shell start file into the EXINIT variable:

EXINIT=set nu

export EXINIT

[Special Topics] Getting Options

Get a list of all options which you have changed:


Get the value of a single option:

:set opt?CR.

Get the list of all possible options and their values:

:set allCR

[Special Topics] Setting Options

Set can be abbreviated se.

Multiple options can be placed on one line, e.g.:

se ai aw nuCR

[Special Topics] Setting Options in EXINIT

A typical startup list includes a set command, and possibly a few map commands.

Since it is advisable to get these commands on one line, they can be separated with the | character, for example:

set ai aw terse|map @ dd|map # x

which sets the options autoindent, autowrite, terse, (the set command), makes @ delete a line, (the first map), and makes # delete a character, (the second map).

Put in your .profile file in your home directory:

EXINIT=set ai aw terse|map @ dd|map # x

export EXINIT

[Special Topics] Recovering lost lines

You might have a serious problem if you delete a number of lines and then regret that they were deleted AND your editor does not have multi-level undo.

Despair not, the editor saves the last 9 deleted blocks of text in a set of numbered registers 1-9. You can get the n’th previous deleted text back in your file by the command


The " here says that a buffer name is to follow,

n is the number of the buffer you wish to try (use 1 for now),

and p is the put command, which puts text in the buffer after the cursor.

If this doesn’t bring back the text you wanted, hit u to undo this and then . (period) to repeat the put command.

In general the . command will repeat the last change you made. As a special case, when the last command refers to a numbered text buffer, the . command increments the number of the buffer before repeating the command.



to show you all the deleted text which has been saved for you.

[Special Topics] Recovering lost files

If the system crashes, you can recover the work you were doing to within a few changes.

% vi -r name

replacing name with the name of the file which you were editing. This will recover your work to a point near where you left off.

You can get a listing of the files which are saved for you by giving the command:

% vi -r

If there is more than one instance of a particular file saved, the editor gives you the newest instance each time you recover it. You can thus get an older saved copy back by first recovering the newer copies.

[Special Topics] Continuous text input: wrap margin

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=10CR.

This causes all lines to be broken at a space at least 10 columns from the right hand edge of the screen.

[Special Topics] Continuous text input: re-joining lines

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.

[Special Topics] Features for editing programs: auto indentation

When editing programs, you often want to maintain an 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 aiCR

Now try opening a new line with o, enter a few tabs, and type some characters. 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.

[Special Topics] Features for editing programs: auto indentation

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=4CR

and then experimenting with autoindent again.

[Special Topics] Features for editing programs: auto indentation

^^D kills autoindent for the current line only

0^D kills all the autoindent

[Special Topics] Features for editing programs: shifting lines

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 right or left.

Try >L and <L shifting the rest of the display right and left.

[Special Topics] Features for editing programs: show match

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 ].

[Special Topics] Features for editing programs: sections

If you are editing C programs, you can use the [[ and ]] keys to advance or retreat to a line starting with a {, (in the first column), 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]].

[Special Topics] Filtering portions of the buffer with !

You can run system commands over portions of the buffer using the operator !.

You can use this to sort lines in the buffer, or to reformat portions of the buffer with a pretty-printer.

Try typing in a list of random words, one per line and ending them with a blank line. Back up to the beginning of the list, and then give the command


This says to sort the next paragraph of material, and the blank line ends a paragraph.

[Special Topics] Commands for editing LISP

If you are editing a LISP program you should set the option lisp by doing :se lispCR. 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 which is useful for typing in LISP, the showmatch option. Try setting it with :se smCR 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.

[Special Topics] Macros: Introduction

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.

[Special Topics] Macros: executable buffers

Put the macro body in a buffer register, say x. You can then type @x to invoke the macro.

@@ will repeat the last macro.

[Special Topics] Macros: map command

:map lhs rhsCR

will map lhs into rhs.


  1. lhs must be 1-10 characters long and 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). Usually macro lhs should be 1 character.
  2. the rhs has to be 1-100 characters long.

[Special Topics] Macros: map command

To get a space, tab or newline into lhs or rhs you should escape them with a ^V.

[Special Topics] Macros: map command

To make the q key write and exit the editor, you can give the command

:map q :wq^V^VCR CR

which means that whenever you type q, it will be as though you had typed the four characters :wqCR.

In vim, this would be:

:nmap q :wq^VCR CR

to setup a map for normal mode (command mode).


  1. Make a macro that inserts a line that says "hello world".
  2. Make a macro that runs /usr/bin/clear and then /usr/bin/date to display the current time.
  3. Make a multi-character macro and notice the 1-second delay in advancing the cursor after you type the first character of the macro. The editor is waiting to see if you’re going to enter the rest of the macro or keep typing.

[Special Topics] Macros: deleting macros

Macros can be deleted with

unmap lhs

[Special Topics] Macros: undoing macros

The undo command reverses an entire macro call as a unit, if it made any changes.

[Special Topics] Macros: undoing macros

map! makes the mapping apply to input mode, rather than command mode.

Exercise: Map "yt" to "Yours Truly,CR" Enter some text in input mode starting with y and observe the 1 second wait for the second macro character.

In vim, !map applies to Insert mode and Command-line mode, and imap applies to Insert mode only.

[Word Abbreviations] User-Defined

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 Sciences

causes the word ‘eecs’ to always be changed into the phrase ‘Electrical Engineering and Computer Sciences’.

[Word Abbreviations] Abbreviations vs Macros

Word abbreviation is different from macros in that only whole words are affected. You could say macros force the editor to be more sensitive to your input than to abbreviations.

There is no need for an abbreviation to be a single keystroke, as it should be with a macro.

Exercise: Set up an abbreviation from your Linux login name to your full real name. Go into input mode, and type your login name and then another word and watch when the abbreviation is expanded.

[Word Abbreviations] Built-in

The editor has a number of short commands which abbreviate longer commands which we have introduced here.

They often save a bit of typing and you can learn them as convenient.

For example:

A - $a

I - ^i

D - d$

C - c$

S - cc

[Nitty-grity details] Line representation in the display: logical vs physical

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.

[Nitty-grity details] Line representation in the display: |

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.

Tip: Try 80| on a line which is more than 80 columns long.

[Nitty-grity details] Line representation in the display: @

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.)


  1. Shrink your edit window to three lines: z3CR
  2. Enter a looong line of text that spans several physical lines.
  3. Scroll up and down through your buffer and observe how vi uses the @ placeholder.

[Nitty-grity details] Line representation in the display: Line numbering

If you wish, you can have the editor place line numbers before each line on the display.

:se nuCR - enable line numbering

:se nonuCR - disable line numbering

[Nitty-grity details] Line representation in the display: List special characters

:se listCR - have tabs represented as ^I and the ends of lines indicated with ‘$’

:se nolistCR - turn this off

[Nitty-grity details] Line representation in the display: List special characters

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 which are past the logical end of file.

[Nitty-gritty details] Counts

Most vi commands will use a preceding count to affect their behavior in some way. The following table gives the common ways in which the counts are used:

new window size

: / ? [[ ]] ` ´

(does not work in vim)

scroll amount

^D ^U

(does not work in vim)

line/column number

z G |

repeat effect

most of the rest

[Nitty-gritty details] More on counts

10a+----ESC will insert a grid-like string of text.

Except for a few commands which ignore any counts (such as ^L), the rest of the editor commands use a count to indicate a simple repetition of their effect. Thus 5w advances five words on the current line, while 5RETURN advances five lines.

A very useful instance of a count as a repetition is a count given to the . command, which repeats the last changing command. If you do dw and then 3., you will delete first one and then three words. You can then delete two more words with 2..

[Nitty-gritty details] More file manipulation commands

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.

[Nitty-gritty details] More file manipulation commands

The following table lists the file manipulation commands which you can use in vi.


write back changes


write and quit


write (if necessary) and quit (same as ZZ).

:w name

write buffer to file name

:w %.bak

make a backup of the current file. % is replaced with current file name.

:w! name

overwrite file name

:x,yw name

write lines x through y to name.

:'x,'yw name

write mark x to y to name.

[Nitty-gritty details] More file manipulation commands

:e name

edit file name


reedit current file, discarding changes

:e name +

edit file name, starting at end

:e name +n

edit name, but run command n first (e.g.: +4 or +/pattern or r !/bin/echo Updated on: `date`). Same argument can be given to vi when first loading the file.

:e #

edit alternate file (the alternate file name is usually the previously edited file)

[Nitty-gritty details] More file manipulation commands

:r name

read file name into buffer

:r !cmd

read output of cmd into buffer


edit next file in argument list


edit next file, discarding changes to current

:n args

specify new argument list (can use wildcards)

:ta tag

edit file containing tag tag, at tag

[Nitty-gritty details] More file manipulation commands: tag command

If you are editing large programs, you will find the :ta command very useful.

/usr/bin/ctags can create a data base of function names and their locations

vi can use this database to quickly find a function whose name you give.

If the :ta command will require the editor to switch files, then you must :w or abandon any changes by switching with :ta!.

You can repeat the :ta command without any arguments to look for the same tag again.

[Nitty-gritty details] More about searching for strings: line offset

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 /pattern/-n to refer to the n'th line before the next line containing pattern, or you can use + instead of - to refer to the lines after the one containing pattern.

If you don’t give a line offset, then the editor will affect characters up to the match place, rather than whole lines; thus use “+0” to affect to the line which matches.

[Nitty-gritty details] More about searching for strings: case insenstive search

You can have the editor ignore the case of words in the searches it does by giving the command :se icCR. The command :se noicCR turns this off.

[Nitty-gritty details] More about searching for strings: disable regex

Strings given to searches may actually be regular expressions. If you do not want or need this facility, you should

set nomagic

in 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. (see next slide)

Note: It is necessary to use a \ before a / in a forward scan or a ? in a backward scan.

[Nitty-gritty details] More about searching for strings: metacharacters

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 \.

[Nitty-gritty details] 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, erase

deletes the last input character


deletes the last input word


your kill character, deletes the input on this line


ends an insertion


starts a new line


backtabs over autoindent


kills all the autoindent


same as 0^D, but restores indent next line


quotes the next non-printing character into the file

[Nitty-gritty details] More about input mode: kill character

Your system kill character (such as ^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.

[Nitty-gritty details] More about input mode: entering non-printing characters

A 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.

[Nitty-gritty details] 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.

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.

Global Search and Replace

Example of global (and partial) search and replace

Searching: backreferences

Backreferences \1 through \9 using \( \) Backreference &

Feedback Please

  1. What did you get out of this training?
  2. What was best about it?
  3. What should be improved?