Project33.Learn Advanced vim


Project 33. Learn Advanced vim

"I like vim. What more can I do with it?"

This project covers some of the more advanced features of the vim text editor, such as global editing, bookmarks, compound commands, macros, and filtering text through external commands. Project 32 introduces vim, and Projects 34 and 35 cover vim windows, buffers, and advanced configuration.

Quick Matching

Project 32 showed you how to search a file for specific text. Sometimes, and especially when writing code, you may want to match the word under the cursor or to locate matching bracket pairs.

If the cursor is sitting on a function name, for example, type star (*) to move to the point in the file where that function is mentioned next. If you have enabled search highlighting (refer to Project 32), all occurrences are highlighted. To move to the next occurrence of the function name, type n. In fact, all the features and options applicable to searching apply to quick matching, too (again, refer to Project 32). To initiate a backward search, type hash (#) instead of star.

Match Bracket Pairs

Place the cursor on an open bracket, and type % to locate the corresponding close bracket and % again to move back to the open bracket. vim understands the (), [], and {} bracket pairs. Rather oddly, vim does not match <> bracket pairs, but this is easily corrected with the matchpairs option. Its default setting is

matchpairs=(:),{:},[:]


Add angle brackets to the list using the command

:set matchpairs+=<:>


Notice that we use += instead of = to add to the existing definition instead of overwriting it.

Learn More

See projects 77 and 78 to learn more about regular expressions.


Find a Character

Sometimes, it's handy to jump forward on a line to a particular character, such as a bracket or quote. To find the next quote, for example, simply type f' (f immediately followed by a single quote). To find subsequent occurrences of the quote, type ; (semicolon); to find previous occurrences, type, (comma).

Tip

When entering commands or filenames on the vim command line, you can use tabbed completion. Simply press Tab, and the command or filename is completed. If what you have typed so far is ambiguous, either type some more and press Tab again, or continue pressing Tab, and vim will cycle through all possible completions.


Perform Global Edits

Try this vim command.

:g/.*/m0


The command reverses the order of the lines in the file. Not in itself useful, it nevertheless illustrates the global command quite nicely. The global command (g) searches every line of the file for the pattern enclosed in //. In this example, we have specified a regular expression (.*) that matches everything. For each line that matches (every line in the file, in this example), the function immediately following the pattern is applied. In this example, m0 moves the current line to a position of line 0 (the top of the file). Each subsequent line becomes the top line, thereby reversing the order of the lines.

We can delete specific lines by using function d. To delete all lines starting with NOTE, for example, we use the regular expression ^NOTE followed by d. A caret at the start of a regular expression says "at the start of the line." The global command is

:g/^NOTE/d


Line Ranges

You are able to limit the scope of the global command by specifying a range of lines to consider, by using either line numbers or pattern matching, and separating the start and end of the range with a comma. If we wish to delete all lines starting with NOTE (using regular expression ^NOTE), but only within the range line 10 to line 100, we type

:10,100g/^NOTE/d


Alternatively, to consider a range of lines delimited by patterns, we type

/START/,/END/g/^NOTE/d


This example searches for a line that contains START and then a subsequent line that contains END. This defines the range of lines to which the global function is applied. Then the function further searches the range for lines that start with NOTE and deletes each one.

The special line range % means all lines in the file.

Use vim Commands as Functions

The global command has a limited number of functions of its own (called ex functions because they descend from the old ex editor upon which vi and vim are based). Standard vim functions and commands can also be used as functions to the global command if they are preceded with the special function normal. To insert -- at the start of each line beginning with NOTE, for example, we apply the vim command I-- to each matched line. Type

:g/^NOTE/normal I--


It may be easier to understand global commands by trying a few examples yourself on a test file. Also, have a look at the vim help pages for global by typing

:help :g


Set Bookmarks

The vim text editor lets you set up to 26 simultaneous bookmarks, labeled a to z. To assign bookmark a to the point under the cursor, type ma (mb for bookmark b, and so on). If you move elsewhere in the file and wish to return to a bookmarked line, simply type a single quote (') followed by the bookmark label ('a, for example).

An alternative method precedes the bookmark label with the back-quote character (`). This returns the cursor to the character that was bookmarked, whereas the single-quote method places the cursor at the start of the marked line. Try setting a few books marks and whizzing back and forth by using both quote and back-quote.

Tip

The most useful of vim's special bookmarks is quote. Typing quote-quote ('') flips you between the current cursor position and the last mark set. Check out the mark (m) command by typing

:help m



Jumping to a bookmark is classified as a motion command. You can use motion commands in combination with other commands, such as delete (d) to delete a marked block of text. See "Build Command Sequences" later in this project, which tells you how to use motion commands as part of a command sequence.

Another 26 vim bookmarks, labeled A to Z, work across files. Set a mark, for example, by typing mA and then quit vim. Restart vim, but editing a different file, and type 'A. You will be transported to the original file and placed right on the marked line (or the marked character, if you recalled the mark by typing 'A).

At this point, you get into the realm of multiple files and buffers. See Project 34 to learn more. If you wish to flip between two loaded files, the easiest method is to press Control-^. You may also type:

:ls!


to list the current files. To return to a particular file, note its buffer number in the listing, and type

:bu<buffer number>


Build Command Sequences

Many of vim's commands can be combined to build more complex command sequences, rather like you combine executables and shell statements to build more complex command lines. In the following sections, we'll take a look at a few useful techniques: repetition counts, motion commands, and macros.

Repetition Counts

Recall from Project 32 that dd deletes the current line. Preceding it with a repetition count lets us delete any number of lines. To delete four lines, type 4dd.

To insert 80 stars, we could type 80 stars, or we could use repetition and the i command, typing 80i* and then pressing Escape. Similarly, to move the cursor forward 20 characters, type 20 and then press the right arrow key, or type 20l. (Project 32 explains the cursor-movement keys, noting that h, j, k, and l are equivalent to the left, down, up, and right arrow keys.) Visit Project 32 if necessary, as it'll help later if you are familiar with the basic cursor-movement commands.

More Motion Commands

The concept of motion commands is fundamental to vim and can be used to great effect when combined with other commands. The command w, for example, is a motion command that moves the cursor forward one word. We can apply a repetition count to a motion command. To move the cursor forward by four words, use 4w.

A motion command can be given as the argument to a function, such as d for delete. So far, we have considered only dd, which is a special case of function d to perform a very common task: delete the current line. The d function usually takes as its argument a motion command that defines the region of text to delete. Motion commands use the current cursor position as the start point for defining a region and designate the end of the region as point to where the cursor would move if the motion command were applied. Hence, dw deletes the word following the cursor; d$ deletes from the cursor to the end of the line; and dG deletes from the cursor to the end of the document.

Combine Them All

Much of vim's power lies in the ability to combine repetition counts, motion commands, and functions. d4w, for example, means "Delete the next four words," and 4dw means "Repeat four times 'delete the next word'." The former applies a repetition count to the motion command, and the latter applies it to the delete function. As long as 2 x 2 = 4, of course, we could also write 2d2w.

Motion commands defined by bookmarks are especially useful. To delete a section of text, we mark one end of the section with ma and then move the cursor to the other end. The motion command 'a now defines a region of text from the cursor to the mark, so the command d'a deletes all lines from the cursor line to the bookmarked line.

To delete a specific portion of text, say from X to Y in the example below,

This will remain X and all of this text will be deleted Y and this will also remain.


we must use back-quote instead of quote in recalling the bookmark. You'll remember that back-quote honors the position within a line, whereas quote simply honors the line. Position the cursor on X and type ma; then move to just after Y and type d`a.

Cut, Copy, and Paste

Project 32 touched on cut, copy, and paste. Now it's time to revisit this subject and apply our new knowledge. Remember that vim uses d to cut (delete) text, y to copy (yank) text, and p to paste text.

Registers

First, let's discuss registers. When you cut text, vim places the text in a register, and when you paste text, it is copied from a register. (vim uses the term register in this context and buffer to denote the area of memory used to store the file currently being edited.) There are 26 registers for copy and paste in vim, labeled a to z. You can use them to store text for reuse. You may cut or copy selected text into a specific buffer by typing a double-quote character (") followed by the register label ("a, for example). To cut the next three lines of text into register a, we precede the cut (delete) command with the named register.

"a3dd


This translates as "Into register a, place the results of: 3 x delete the current line."

To copy text from the cursor to the end of the line into register b, we type

"by$


This translates as "Into register b, place the results of: copy (yank) from the cursor position to the end of the line."

To paste the contents of a register, precede the paste command (p) with a register name (a double quote followed by the label letter). The following pastes the contents of register b.

"bp


To copy (or cut) a specific region of text, we'll combine what we have learned about bookmarks, registers, and yanking (or deleting). Place the cursor at the start of the region to be copied and type ma; move the cursor to the end of the region and type

"ay`c


This translates as "Into register a, copy the results of: copy text from the current cursor position to bookmark c, honoring the position within the line."

At first glance, these commands look like hieroglyphics. But if you understand the concepts discussed in this project, it's easy to decipher them. Similarly, it's very easy to build such commands: A lot can be achieved with just a few keystrokes.

Tip

Type :registers to view the contents all the registers and :help registers to read the vim help pages on registers and black holes.


More Registers

The last copy or cut in vim is always placed in the special register named dot. Its contents can be recalled in the usual manner: by typing its name (the period character) after a double-quote character.

".


If you wish to append text to the contents of a register, rather than overwrite the contents, use a capital letter to name the register. To collect three dispersed lines into register a and paste them elsewhere, for example, we use (omitting the necessary cursor-movement commands)

"ayy "Ayy "Ayy "ap


Repeat Commands with Macros

Very often, you need to repeat the last command a number of times. Suppose that you wish to comment out a number of lines in your PHP code by preceding them with //. To do this, you insert the text // at the start of a line by typing I// followed by Escape. Now press Cursor Down and then dot (.). The previous insert sequence will be repeated. Dot repeats the last simple command, such as an insert or delete sequence.

Tip

Add new keystrokes to an existing macro by using a capital letter to name the macro. qA, for example, adds keystrokes to the existing macro a.


The dot command can save a lot of typing with repetitive tasks, but we can often reduce effort even more by using a macro, defined by recording a series of keystrokes. We might improve on the example above by recording the keystrokes

I// Escape Cursor-Down


You can store up to 36 macros in vim, named 0 to 9 and a to z. To record a macro, type q followed by the label you want to assign to the macro (qa, for example). Start typing, and when you're done recording, type q again. Replay the macro by typing @ followed by the macro label (@a, for example).

Comparing our macro a with the dot example above, the inclusion of a cursor-down keystroke makes the macro easier to use than the dot command, and the macro is also better suited to the use of a repeat count, as in 10@a.

If you find yourself using a macro frequently, you can assign it to a keystroke commanda technique termed key mapping. That's covered in Project 35.

Filter through External Commands

vim lets you pop into the shell temporarily to run a command without ever leaving the editor. Type

:!ls


to list the contents of the current directory using the Unix command ls ; then press Return to return control of the Terminal screen to vim. The pling (!) command says to interpret whatever follows as a shell command and pass it to the shell.

If you wish to capture the output from a command into the file you are editing, rather than have it written to the Terminal, type !! followed by that command. Try !!date. Neat!

The cursor should be positioned on a blank line to prevent the contents of that line from being replaced by the output of the external command. In fact, there's more happening than is at first apparent. The current line is being filtered through the external program. Here's how.

The pling (!) command can take a motion command as an argument, in much the same way as commands y and d (as you saw in "Cut, Copy, and Paste" earlier in this project). The lines encompassed by the motion command are cut from the file and presented to the external command as its standard input. The external command executes, and its output (standard out) is written back to the file.

This is best illustrated with an example. Type

!5j sort


You'll notice that after you type !5j, the cursor moves to the vim command line so you can see what you type next. Analyzing this command, 5j says to move the cursor down five lines, thereby defining six linesfrom the current cursor position downas the lines to filter. The Unix command sort sorts its input lines into order, so the six lines encompassed by the command are sorted in alphabetic order and written back to the file.

An alternative method of specifying the lines to filter uses a range of lines. In this case, start by typing a : to move to vim's command line and then type a range like 1,10 (for the first 10 lines of the file) or % for the entire file. (See "Line Ranges" earlier in this project.) Follow the range with the name of the command through which to filter the range of lines. The following example sorts the entire file.

:%!sort


Filtering can be used to great effect. Experiment with it, and you'll no doubt find your own favorite uses. I have a program called HTML Tidy that verifies and tidies HTML text. Running all lines through this program provides me a neat way to verify HTML code without leaving the vim text editor. HTML Tidy can be downloaded from SourceForge at http://sourceforge.net/projects/tidy/

Learn More

Filter commands can be bound to keystrokes; see Project 35 to learn how to define key mappings.





Mac OS X UNIX 101 Byte-Sized Projects
Mac OS X Unix 101 Byte-Sized Projects
ISBN: 0321374118
EAN: 2147483647
Year: 2003
Pages: 153
Authors: Adrian Mayo

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net