The vi map
command (Section 18.2)
lets you define keymaps: short names for a series of one or more commands. You
can enter :map
to define a keymap while
you're editing a file with vi. But if you
make a mistake, you usually have to re-enter the whole :map
command to correct the problem.
@
-functions (pronounced "at-functions")
give you another way to define complex commands. You can define 26 @
-functions named @a
through @z
. They're stored
in named buffers (Section 17.4). So if you're also using
named buffers for copying and pasting text, you'll need to share them with your
@
-functions.
Enter the command(s) you want to execute onto one or more lines of the file you're editing.
Yank or delete the line(s) into a named buffer with a command like
"ay$
or "bD
.
To use the function, type a command like @a
or @b
. You can
repeat the function by typing @@
or a dot (.). Use u
or U
to undo the effects of the @
-function.
Here's an example. You're editing a long HTML file with lines like these:
<STRONG>Some heading here
</STRONG> <STRONG>Another heading here
</STRONG>
When you see one of those lines, you need to change the STRONG
s to either H3
or H4
. A global
substitution with :%s
won't do the job
because some lines need H3
and others
need H4
; you have to decide line-by-line
as you work through the file. So you define the function @a
to change a line to H3
, and @b
to change to H4
.
To design an @
-function, start by
thinking how you'd make the changes by hand. You'd probably move to the
start of the line with 0
, move to the
right one character with l
, type cw
to change the word STRONG
, and type in H3
(or
H4
). Then you'd press ESC to return
to command mode. After going to the end of the line with $
, you'd move to the character after the slash
with T/
, then change the second STRONG
the way you fixed the first one.
To define the function, open a new empty line of your file (first go into
text-input mode). Then type the keystrokes that will make the H3
changes; type CTRL-v
before each ESC or RETURN (Section 18.6). When you're done, press ESC again to go to
command mode. Because the commands for the H4
change are similar, the easiest way to make them is by
copying and pasting the line for H3
(by
typing yy
and p
) and then editing the copy. The pair of command lines
should look like this (where ^[
stands
for the CTRL-v ESC keys):
0lcwH3^[$T/cwH3^[ 0lcwH4^[$T/cwH4^[
Move to the start of the first line, and delete it into the
a buffer by typing "aD
. Go to the next line, and type "bD
. (This will leave two empty lines; delete them with
dd
if you'd like.) Now, when you type
@a
, it will execute the commands to
change a line to H3
; typing @b
on a line will change it to have H4
. Move through your file (maybe with a
search: /STRONG
... n
...), typing @a
or @b
as you go. Or use
@@
to make the same change you made
on a previous line.
An @
-function
can execute other @
-functions. For
example, here are four lines ready for storing as @a
through @d
:
0l@c$T/@c ...becomes @a 0l@d$T/@d ...becomes @b cwH3^[ ...becomes @c cwH4^[ ...becomes @d
See that the definition of @a
has
@c
in it twice? When you execute
@a
, it will do 0l
to move to the second character on the
line, then do @c
to change the word to
H3
, move to the end of the line, and
use @c
again. Calling one @
-function from another can save you from
retyping repetitive commands.
A disadvantage is that @@
won't always
work as you might expect. If you type @a
to make a change in one place, then move somewhere else and type @@
, the @@
will do what @c
does (instead of what you
might have wanted, @a
). That's because
the @a
function finishes by doing
@c
.
You don't have to delete the definition
line into a buffer with dd
. If you think
you might need to fine-tune the command, you can yank (copy) it into a
buffer with a command like "ay$
. Then, if
you need to revise the command, re-edit the line and type "ay$
to put the revised version into the
buffer. Or use "by$
to copy the revised
line into another buffer.
Stored @
-functions can span multiple lines. For example, if you
delete the following four lines with "z4dd
, typing @z
will open
a newline below (o
) and insert four
newlines of text:
oThis is the newline one. This is the newline two. This is the third line. This is the fourth.^[
After you execute the function with @z
,
your cursor will move to the line below the new fourth line. Why? Because
you included the newlines (RETURNs) in the buffer; each RETURN moves down a
line — including the RETURN after the last ESC.
If you don't want that, there are two ways to fix it:
Delete the first three lines, including the newlines, into the
buffer by typing "z3dd
. Delete
the fourth line, without its newline, and
append it to the buffer by typing "ZD
. (An uppercase letter like
Z
appends to a named buffer.
D
deletes all of a line
except the newline.)
Some versions of vi will delete
four lines, without the last newline, when you use "z4D
.
Type all of the text onto a single line; embed the newlines in that line by typing CTRL-v RETURN between each finished line. It'll look like this:
oThis is the new line one.^MThis is the new line two.^MThis is the new...
Delete that long line into your buffer with "zD
. Because D
doesn't delete the final newline, your cursor will
stay at the end of the fourth newline after you execute the @z
.
— JP