Book HomeLearning the vi EditorSearch this book

11.10. Interesting Features

vim is a very featureful editor. We cannot describe everything in full detail here. Instead, we've chosen to discuss several of the most important and unique features that it has.

Automatic file type detection
vim will notice how the lines of a text file end. It sets the fileformat variable to one of dos (CR-LF), unix (LF), or mac (CR) to indicate the file's current mode. By default, vim will write the file back out in the same format, but if you change the value of fileformat, vim will use that convention. This is an easy way to convert between Linux (or UNIX) and MS-DOS files, and makes editing DOS files under UNIX or Linux very easy. (In contrast, the other clones all display a ^M at the end of each line.)

vim is "charityware"
The licensing terms are described later in this chapter; they are fairly liberal. However, the author encourages users who like vim to send a donation to a children's center in Uganda.

Significant C programming extensions
vim has a large set of features for working with C and C++ programs.

The "auto command" facility
vim defines a large number of events, such as before or after reading a file, entering or leaving a window, and so on. For each event, you can set up an "auto command," i.e., a command to be executed when that event occurs.

11.10.1. vim Is Charityware

With vim, Bram Moolenaar has taken a different approach from the usual shareware or freeware author. If you use vim and you like it, Mr. Moolenaar requests that you send a donation to help orphans in Uganda. We applaud his efforts.

Mr. Moolenaar spent a year as a volunteer at Kibaale Children's Centre (KCC), located in Kibaale, a small town in the south of Uganda, near Tanzania. The KCC works to provide food, medical care, and education for children in this area, which is suffering from AIDS more than in any other part of the world. Because of the high incidence of AIDS, many of the children are orphans.

In order to continue supporting KCC, Mr. Moolenaar is trying to raise funds and organize sponsorship. You can find a much longer explanation in the file uganda.txt in the vim distribution. This includes directions for sending donations. You can also look at http://www.vim.org/iccf/ .

11.10.2. C and C++ Programming Features

vim, in the grand tradition of vi, is first and foremost a programmer's editor. In particular, it is a C programmer's editor, and happily, C++ programmers can take advantage of it too. There are lots of features that make the C programmer's life easier. We describe the most significant ones here.

11.10.2.1. Smart indenting

All versions of vi have the autoindent option, which, when set, automatically indents the current line by the same amount as the one next to it. This is handy for C programmers who indent their code, and for anyone else who may need to indicate some kind of structure in their text via indentation.

vim carries this feature further, with two options, smartindent and cindent. The cindent option is the more interesting of the two, and is the topic of this subsection. See Table 11.14 for a list of vim indentation and formatting options.

Table 11.14. vim Indentation and Formatting Options

Option Function
autoindent

Simple-minded indentation, uses that of the previous line.

smartindent

Similar to autoindent, but knows a little about C syntax. Deprecated in favor of cindent.

cindent

Enables automatic indenting for C programs, and is quite smart. C formatting is affected by the rest of the options in this table.

cinkeys

Input keys that trigger indentation options.

cinoptions

Allows you to tailor your preferred indentation style.

cinwords

Keywords that start an extra indentation on the following line.

formatoptions

Made up of a number of single letter flags that control several behaviors, notably how comments are formatted as you type them.

comments

Describes different formatting options for different kinds of comments, both those with starting and ending delimiters, as in C, and those that start with a single symbol and go to the end of the line, such as in a Makefile or shell program.

When set up appropriately, vim automatically rearranges the indentation of your C program as you type. For instance, after an if, vim automatically indents the next line. If the body of the if is enclosed in braces, when you type the right brace, vim will automatically indent it back one tab stop, to line up underneath the if. As another example, with the settings shown below, upon typing the colon that goes with a case, vim will shift the line with the case left one tab stop to line up under the switch.

The following .vimrc produces, in our opinion, very nicely formatted C code:

set nocp incsearch
set cinoptions=:0,p0,t0
set cinwords=if,else,while,do,for,switch,case
set formatoptions=tcqr
set cindent
syntax on
source ~/.exrc

The nocp option turns off strict vi compatibility. The incsearch option turns on incremental searching. The settings for cinoptions, cinwords, and formatoptions differ from the defaults; the result is to produce a fairly strict "K&R" C formatting style. Finally, syntax coloring is turned on, and then the rest of the vi options are read in from the user's .exrc file.

We recommend that you start up vim, set these options as shown, and then spend some time working on a C or C++ program. Five minutes of playing with this facility will give you a better feel for it than whatever static examples we could present on the printed page. We think you'll find the facility really enjoyable to use.

11.10.2.2. Include file searching

Often, when working with large C programs, it is helpful to be able to see where a particular type name, function, variable or macro is defined. The tag facility can help with this, but doing a tag lookup actually moves you to the found location, which may be more than you need.

vim has a number of commands that search through the current file and through included files to find other occurrences of a keyword. We summarize them here.

The vi and ex commands fall into four categories: those that display the first occurrence of a particular object (in the status line), those that display all occurrences of a particular object, those that jump to the location of the first occurrence, and those that open a new window and jump to the first occurrence. Commands that do all four exist to look for keywords, usually the identifier under the cursor, and to look for macro definitions of the identifier under the cursor.

These commands use the smart syntax facilities (the comments variable described earlier) to ignore occurrences of the searched-for identifier inside comments. With a preceding count, they go to the count th occurrence. The search for the identifier starts at the beginning of the file, unless otherwise noted.

See Table 11.15 for a list of the vim identifier searching commands.

Table 11.15. vim Identifier Search Commands

Command Function
[i

Display the first line that contains the keyword under the cursor.

]i

Display the first line that contains the keyword under the cursor, but start the search at the current position in the file. This command is most effective when given a count.

[I

Display all lines that contain the keyword under the cursor. Filenames and line numbers are displayed.

]I

Display all lines that contain the keyword under the cursor, but start from the current position in the file.

[ ^I

Jump to the first occurrence of the keyword under the cursor. (Note that ^I is a TAB.)

] ^I

Jump to the first occurrence of the keyword under the cursor, but start the search from the current position.

^W i

Open a new window showing the location of the first (or countth) occurrence of the identifier under the cursor.

^W ^I
[d

Display the first macro definition for the identifier under the cursor.

]d

Display the first macro definition for the identifier under the cursor, but start the search from the current position.

[D

Display all macro definitions for the identifier under the cursor. Filenames and line numbers are displayed.

]D

Display all macro definitions for the identifier under the cursor, but start the search from the current position.

[ ^D

Jump to the first macro definition for the identifier under the cursor.

] ^D

Jump to the first macro definition for the identifier under the cursor, but start the search from the current position.

^W d

Open a new window showing the location of the first (or countth) macro definition of the identifier under the cursor.

^W ^D

Two options, define and include, describe the source code lines that define macros and include source files. They have default values appropriate for C, but can be changed to suit your programming language (e.g., the value ^\(#\s*define\|[a-z]*\s*const\s*[a-z]*\) for define could be used to also look for definitions of C++ named constants).

The same facilities are also available as ex commands, shown in Table 11.16.

Table 11.16. vim Identifier Search Commands from ex Mode

Command Function
[range]is[earch][!] [count] [/]pattern[/]

Like [i and ]i, but searches in range lines. The default is the whole file. The !, if supplied, forces comments to be searched also. Without the /'s, a word search is done. With them, a regular expression search is done.

[range]il[ist][!] [/]pattern[/]

Like [I and ]I, but searches in range lines. The default is the whole file.

[range]ij[ump][!] [count] [/]pattern[/]

Like [ ^I and ] ^I, but searches in range lines. The default is the whole file.

[range]isp[lit][!] [count] [/]pattern[/]

Like ^W i and ^W ^I, but searches in range lines. The default is the whole file.

[range]ds[earch][!] [count] [/]pattern[/]

Like [d and ]d, but searches in range lines. The default is the whole file.

[range]dl[ist][!] [/]pattern[/]

Like [D and ]D, but searches in range lines. The default is the whole file.

[range]dj[ump][!] [count] [/]pattern[/]

Like [ ^D and ] ^D, but searches in range lines. The default is the whole file.

[range]dsp[lit][!] [count] [/]pattern[/]

Like ^W d and ^W ^D, but searches in range lines. The default is the whole file.

che[ckpath][!]

List all the included files that could not be found. With the !, list all the included files.

The path option is used to search for included files that do not have an absolute pathname. Its default value is .,/usr/include,,, which looks in the directory where the edited file resides, in /usr/include, and in the current directory.

11.10.2.3. Cursor motion commands for programming

A number of enhanced and new cursor motion commands make it easier to find the opposite ends of matching constructs, as well as to find unmatched constructs that should be matched, for example, #if statements that do not have a corresponding #endif. Most of these commands may be preceded by a count, which defaults to one if not given.

See Table 11.17 for a list of the extending matching commands.

Table 11.17. vim Extended Matching Commands

Command Function
%

Extended to match the /* and */ of C comments, nd also the C preprocessor conditionals, #if, #ifdef, #ifndef, #elif, #else, and #endif.

[(

Move to the countth previous unmatched (.

[)

Move to the countth next unmatched ).

[{

Move to the countth previous unmatched {.

[}

Move to the countth next unmatched }.

[#

Move to the countth previous unmatched #if or #else.

]#

Move to the countth next unmatched #else or #endif.

[*, [/

Move to the countth previous unmatched start of a C comment, /*.

]*, ]/

Move to the countth next unmatched end of a C comment, */.

11.10.3. Autocommands

vim allows you to specify actions that should be executed when a particular event occurs. This facility gives you a great deal of flexibility and control. As always though, with power comes responsibility; the vim documentation warns that you should be careful with the autocommand facility so that you don't accidentally destroy your text!

The facility is complicated and detailed. In this section we outline its general capabilities, and provide an example to give you a sense of its flavor.

The autocommand command is named :autocmd. The general syntax is:

:au event filepat command

The event is the kind of event to which this command applies, for example, before and after reading a file (FileReadPre and FileReadPost), before and after writing a file (FileWritePre and FileWritePost), and upon entering or leaving a window (WinEnter and Winleave). There are more defined events, and case in the event name does not matter.

The filepat is a shell-style wildcard pattern that vim applies to filenames. If they match, then the autocommand will be applied for this file.

The command is any ex mode command. vim has a special syntax for retrieving the different parts of filenames, such as the file's extension, or the name without the extension. These can be used in any ex command, but are very useful with autocommands.

Multiple autocommands for the same events and file patterns add commands onto the list. Autocommands can be removed for a particular combination of events and file patterns by appending ! to the :autocmd command.

A particularly elegant example allows you to edit files compressed with the gzip program. The file is automatically decompressed when editing starts, and then recompressed when the file is written out (the fourth line is broken for readability):

:autocmd! BufReadPre,FileReadPre        *.gz set bin
:autocmd! BufReadPost,FileReadPost      *.gz '[,']!gunzip
:autocmd  BufReadPost,FileReadPost      *.gz set nobin
:autocmd  BufReadPost,FileReadPost      *.gz \
          execute ":doautocmd BufReadPost " . expand("%:r")

:autocmd! BufWritePost,FileWritePost    *.gz !mv <afile> <afile>:r
:autocmd  BufWritePost,FileWritePost    *.gz !gzip <afile>:r

:autocmd! FileAppendPre                 *.gz !gunzip <afile>
:autocmd  FileAppendPre                 *.gz !mv <afile>:r <afile>

:autocmd! FileAppendPost                *.gz !mv <afile> <afile>:r
:autocmd  FileAppendPost                *.gz !gzip <afile>:r

The first four commands are for reading compressed files. The first two in this set use ! to remove any previously defined autocommands for compressed files (*.gz). The compressed file is read into the buffer as a binary file, so the first command turns on the bin (short for binary) option.

vim sets the marks '[ and '] to the first and last lines of the just read text. The second command uses this to uncompress the just read file in the buffer.

The next two lines unset the binary option, and then apply any autocommands that apply to the uncompressed version of the file (e.g., syntax highlighting). The %:r is the current filename without the extension.

The next two lines are for writing the compressed file. The first one in this set first removes any previously defined autocommands for compressed files (*.gz), with these events. The commands invoke a shell to rename the file to not have the .gz extension, and then run gzip to compress the file. The <afile>:r is the filename without the extension. (The use of <afile>:r is restricted to autocommands.) vim writes the uncompressed buffer to the file with the .gz extension, thus the need for the renaming.

The second line in this set runs gzip to compress the file. gzip automatically renames the file, adding the .gz extension.

The last four lines handle the case of appending to a compressed file. The first two of these lines uncompress the file and rename it before appending the contents to the file.

Finally, the last two lines recompress the file after writing to it, so that the uncompressed file is not left laying around.

This section just touches the tip of the iceberg of autocommands. For example, autocommands can be placed into groups, so that they can all be executed or removed together. All of the syntax coloring commands described in Section 11.9.2 are placed into the highlight group. An autocommand then executes all of them together when an appropriate file is read.

As an example, instead of having your .vimrc file always execute set cindent for smart C indenting, you might use an autocommand to do it just for C source code, like this:

autocmd BufReadPre,FileReadPre   *.[chy] set cindent


Library Navigation Links

Copyright © 2003 O'Reilly & Associates. All rights reserved.