home | O'Reilly's CD bookshelfs | FreeBSD | Linux | Cisco | Cisco Exam  

UNIX Power Tools

UNIX Power ToolsSearch this book
Previous: 31.3 What You Lose When You Use map! Chapter 31
Creating Custom Commands in vi
Next: 31.5 Keymaps for Pasting into a Window Running vi

31.4 vi @-Functions

The vi map command ( 31.2 ) lets you define keymaps: short names for a series of one or more other 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 (say "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 ( 30.5 ) . So if you're also using named buffers for copying and pasting text, you'll need to share them with your @ -functions.

31.4.1 Defining and Using Simple @-Functions

To define an @ -function:

  1. Enter the command(s) you want to execute onto one or more lines of the file you're editing.

  2. Yank or delete the line(s) into a named buffer with a command like "ay$ or "bD .

  3. 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:


Some heading here


Another heading here


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 press ESC to return to command mode. Go to the end of the line with $ , 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 (go into text-input mode). Then type the keystrokes that will make the H3 changes; type CTRL-v before each ESC or RETURN ( 31.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 )-then edit the copy. The pair of command lines should look like this (where ^[ stands for the [CTRL-v] [ESC] keys):


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.

31.4.2 Combining @-Functions

An @ -function can execute other @ -functions. For example, here are four lines ready for storing as @a through @d :

...becomes @a

...becomes @b

...becomes @c

...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 re-typing 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 a @c .

31.4.3 Reusing a Definition

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.

31.4.4 Newlines in an @-Function

Stored @ -functions can span multiple lines. For example, if you delete the following four lines with "z4dd , typing @z will open a new line below ( o ) and insert four new lines of text:

oThis is the new line one.
This is the new line 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 new line after you execute the @z .

- JP

Previous: 31.3 What You Lose When You Use map! UNIX Power Tools Next: 31.5 Keymaps for Pasting into a Window Running vi
31.3 What You Lose When You Use map! Book Index 31.5 Keymaps for Pasting into a Window Running vi

The UNIX CD Bookshelf Navigation The UNIX CD BookshelfUNIX Power ToolsUNIX in a NutshellLearning the vi Editorsed & awkLearning the Korn ShellLearning the UNIX Operating System