All of the features discussed so far in this book are of interest
whether you are editing English text or program source code. However,
there are a number of additional features that are of interest chiefly
to programmers. These include indentation control, searching for the
beginning and end of procedures, and using ctags
.
The following discussion is adapted from documentation provided by Mortice Kern Systems with their excellent implementation of vi for DOS-based systems, available as a part of the MKS Toolkit or separately as MKS Vi. It is reprinted by permission of Mortice Kern Systems.
The source code for a program differs from ordinary text in a number of ways. One of the most important of these is the way in which source code uses indentation. Indentation shows the logical structure of the program: the way in which statements are grouped into blocks.
vi provides automatic indentation control. To use it, issue the command:
:set autoindent
Now, when you indent a line with spaces or tabs, the following lines will automatically be indented by the same amount. When you press [RETURN] after typing the first indented line, the cursor goes to the next line and automatically indents the same distance as the previous line.
As a programmer, you will find this saves you quite a bit of work getting the indentation right, especially when you have several levels of indentation.
When you are entering code with autoindent enabled, typing [CTRL-T] at the start of a line gives you another level of indentation and typing [CTRL-D] takes one away.
We should point out that [CTRL-T] and [CTRL-D] are typed while you are in insert mode, unlike most other commands, which are typed in command mode.
The amount of indentation provided by
[CTRL-T]
or >>
is one tab
character. Tab stops are set every eight
spaces by default. A command like:
:set tabstop=4
will change the tab settings for a file.
Try using the autoindent option when you are entering source code. It simplifies the job of getting indentation correct. It can even sometimes help you avoid bugs (e.g., in C source code, where you usually need one closing curly brace (}) for every level of indentation you go backwards).
The <<
and >>
commands are also helpful when indenting
source code.
By default, >>
shifts a line right eight spaces
(i.e., adds eight spaces of indentation)
and <<
shifts a line left eight spaces.
For example, move the cursor to the beginning of this line and
press the > key twice (>>
). You will see the line move right.
If you now press the < key twice (<<
), the line will move back again.
You can shift a number of lines by typing the number followed
by >>
or <<
. For example, move the cursor to the first line of
this paragraph and type 5>>
. You will shift all five lines in
the paragraph.
The default shift is eight spaces (right or left). This default can be changed with a command like:
:set shiftwidth=4
You will find it convenient to have a shiftwidth that is the same size as the width between tab stops.
Sometimes indentation won't work the way you expect, because what you believe to be a tab character is actually one or more spaces. Normally, your screen displays both a tab and a space as white space, making the two indistinguishable. You can, however, issue the command:
:set list
This alters your display so that a tab appears as the control
character ^I
and an end-of-line appears as a $
.
This way, you can spot a true space, and you can see extra spaces
at the end of a line. A temporary equivalent is the
:l
command.
For example, the command:
:5,20 l
displays lines 5 through 20, showing tab characters and end-of-line characters.
The characters (, [, {, and < can all be called
opening brackets. When the cursor is resting on one of these
characters, pressing the %
key moves the cursor from the opening
bracket forward to the corresponding closing
bracket - ), ], }, or > - keeping in mind the usual
rules for nesting brackets.
For example, if you were to move the cursor to the first ( in:
if ( cos(a[i]) > sin(b[i]+c[i]) ) { printf("cos and sin equal!"); }
and press %
, you would see that the cursor jumps to the
parenthesis at the end of the line. This is the closing
parenthesis that matches the opening one.
Similarly if the cursor is on one of the closing bracket
characters, pressing %
will move the cursor backwards to the
corresponding opening bracket character. For example, move the
cursor to the closing brace bracket after the printf
line above
and press %
.
Not only does this search character help you move forward and
backward through a program in long jumps, it lets you check the
nesting of brackets and parentheses in source code. For example, if you put
the cursor on the first { at the beginning of a C function,
pressing %
should move you to the } that (you think) ends the
function. If it doesn't, something has gone wrong somewhere.
Another technique for searching matching brackets is to turn on the following option:
:set showmatch
Unlike %
, setting showmatch
(or its abbreviation sm
) helps you
while you're in insert mode. When you type a )
or a
}
, the cursor will briefly move back to the matching (
or
{
before returning to your current position.
If the match is off-screen or doesn't exist, the terminal beeps.
The source code for a large C program will usually be spread
over several files. Sometimes, it is difficult to keep track of
which file contains which function definitions. To simplify
matters, a UNIX command called ctags
can be used together
with the :tag
command of vi.
NOTE: This section is of interest to C programmers, but not to those working in other languages.
The ctags
command is issued at the UNIX command line.
Its purpose is to create an information file
that vi can use later to determine which files define which
functions. By default, this file is called tags.
From within vi, a command of the form:
:!ctags file.c
will create a file named tags under your current directory that contains information on the functions defined in file.c. A command like:
:!ctags *.c
will create a tags file describing all the C source files under the directory.
Now suppose your tags file contains information on all the source files that make up a C program. Also suppose that you want to look at or edit a function in the program but do not know where the function is. From within vi, the command:
:tag name
will look at the tags file to find out which file contains the definition of the function name. It will then read in the file and position the cursor on the line where the name is defined. In this way, you don't have to know which file you have to edit; you only have to decide which function you want to edit.
NOTE: If you try to use the
:tag
command to read in a new file and you haven't saved your current text since the last time you changed it, vi will not let you go to the new file. You must either write out your current file with the:w
command and then issue:tag
, or else type::tag! nameto override vi's reluctance to discard edits.