[Quite a few vi
users understand how to build vi
commands with
the (number)(command)(text object)
model.
But not too many people understand the difference between line commands
and character commands.
This article explains that and gives some examples. -JP]
The _
(underscore) command is very similar to the
(caret)
command in that it moves
to the first non-blank character of the current line. The key
difference is that _
is a line
command while
is a character
command. This is important for all functions that read an "address,"
for example, d
, y
, and c
.
In fact, delete, yank, and so on all call a common internal
routine in vi
to get an "address." If the address is of a particular
character, vi
does a character-mode delete or yank or whatever. If
it is a line address, vi
does a line-mode operation. The
"address" command may be any of the regular positioning commands
(e.g., W
, b
, $
, or /pattern/
) or the original character repeated (as in
dd
or yy
).
Some examples are in
Table 30.1
.
Table 30.1: Examples of vi Character and Line Commands
Keystrokes |
Results |
dd |
Deletes the current line. |
d'a |
Deletes all lines between the current line and the line containing mark
a
, inclusive.
|
d`a |
Deletes all characters between the current character
and the character at mark a
. This works much
like an Emacs W
in that the two endpoints are
considered to be between two characters. Note that
a character-oriented delete may delete newlines.
|
c/accord/ |
Changes all characters (not
lines!) between the
current character up to but not including the a
in accord
. (However, see the following Note.)
|
c?accord? |
Changes all characters between the current character
and the accord
, including the word accord
.
|
yj |
Yanks two lines, the current line and the one below. |
yH |
Yanks all the lines from the top of the screen to the current line, inclusive.
|
<G |
Unindents or "dedents" the lines between the current line and the
last line, inclusive. (The variable shiftwidth
determines the amount of dedenting.) Note that
this command turns character addresses into line
addresses (so does >
).
|
!}fmt |
Runs the lines between the current line and the
end of the paragraph through the program
fmt
(30.37
)
.
|
NOTE:
If you have wrapscan
set, a
search like c?accord?
may wrap from the beginning of the file to
the end. This can cause unexpected results, and is one reason
why I have set nows
in my .exrc
.
Unfortunately, turning off wrapscan
breaks
tags
(30.28
)
in many versions of vi
.
vi
combines the repeat count, if any, on the command character with
the repeat count on the motion command, so that 2y2j
yanks five
lines. Interestingly, 2y2_
yanks 4 lines (so does 2y2y
) since
the _
command moves down (repeat count minus 1) lines. Beware,
however, of using repeat counts on all of the motion commands; they're
not all implemented in the same way. 4$
moves to the end of the third
line below the current; 4
merely moves to the first non-blank
character of the current line. |
(vertical bar) is a synonym for
0
(zero); given a repeat count it goes that many characters to the right
of the beginning of the line (as if you had typed |
(rept-1
)
l
). (Exercise for the reader: why can't you give a repeat count
to 0
?)
Uppercase letters do different things depending on the command. The
exact actions may not always seem sensible, but typically they affect
the "current line": D
acts like d$
; C
acts
like c$
; Y
acts like yy
. The list must merely
be memorized, or you can use
a good vi
reference guide.
- CT
in net.unix
on Usenet, 19 March 1984