12.10. Interesting Features

vile has a number of interesting features that are the topic of this section.

The vile editing model

vile's editing model is somewhat different from vi's. Based on concepts from emacs, it provides key rebinding and a more dynamic command line.

Major modes

vile supports editing "modes." These are groups of option settings that make it convenient for editing different kinds of files.

The procedure language

vile's procedure language allows you to define functions and macros that make the editor more programmable and flexible.

Miscellaneous small features

A number of smaller features make day-to-day editing easier.

12.10.1. The vile Editing Model

In vi and the other clones, editing functionality is "hardwired" into the editor. The association between command characters and what they do is built into the code. For example, the x key deletes characters, and the i key enters insert mode. Without resorting to severe trickery, you cannot switch the functionality of the two keys (if it can even be done at all).

vile's editing model, derived from emacs through MicroEMACS, is different. The editor has defined, named functions, each of which performs a single editing task, such as delete-next-character or delete-previous-character. Many of the functions are then bound to keystrokes, such as binding delete-next-character to x.[1]

Changing bindings is very easy to do. You use the :bind-key command. [2] As arguments, you give it the name of the function, and then the key sequence to bind the function to. You might put the following commands into your .vilerc file:

bind-key incremental-search /
bind-key reverse-incremental-search ?

These commands change the / and ? search commands to do incremental searching.

In addition to pre-defined functions, vile contains a simple programming language that allows you to write procedures. You may then bind the command for executing a procedure to a keystroke sequence. GNU emacs uses a variant of Lisp for its language, which is extremely powerful. vile has a somewhat simpler, less general-purpose language.

Also, as in emacs, the vile command line is very interactive. Many commands display a default value for their operand, which you can edit if not appropriate, or select by hitting RETURN. As you type vi mode editing commands, such as those that change or delete characters, you will see feedback about the operation in the status line.

The "amazing" ex mode that Paul referred to earlier is best reflected in the behavior of the :s (substitute) command. It prompts for each part of the command: the search pattern, the replacement text, and any flags.

As an example, let's assume you wish to change all instances of perl to awk everywhere in your file. In the other editors, you'd simply type :1,$s/perl/awk/gRETURN, and that's what would appear on the command line. The following set of screens describes what you see on the vile colon command line as you type:

KeystrokesResults
:1,$s

The first part of the substitute command.

/
substitute pattern: _

vile prompts you for the pattern to search for. Any previous pattern is placed there for you to re-use.

perl/
replacement string: _

At the next / delimiter, vile prompts you for the replacement text. Any previous text is placed there for you to re-use.

awk/
(g)lobally, ([1-9])th occurrence on line, 
(c)onfirm, and/or (p)rint result: _

At the final delimiter, vile prompts for the optional flags. Enter any desired flags, then RETURN.

The last prompt line is broken for readability. vile prints it all on one line.

vile follows through with this style of behavior on all appropriate ex commands. For example, the read command (:r) will prompt you with the name of the last file you read. To read that file again, just hit RETURN.

Finally, vile's ex command parser is weaker than in the other editors. For example, you cannot use search patterns to specify line ranges (:/now/,/forever/s/perl/awk/g), and the move command (m) is not implemented. In practice, what's not implemented does not seem to hinder you very much.

12.10.2. Major Modes

A major mode is a collection of option settings that apply when editing a certain class of file. [3] These options apply on a per-buffer basis, such as the tab-stop settings. The major mode concept was first introduced in vile 7.2.

vile provides three types of options:

The buffer- and window-option settings may be global or local values. Any buffer (or window, depending on the option) can have its own private (local) option value. If it does not have a private value, it uses the global value. Major modes add a level between the buffer global and local values by providing option values that a buffer uses if it does not have a private value.

vile has two built-in major modes, cmode, for editing C and C++ programs, and vilemode, for its scripts which are loaded into memory buffers. With cmode, you can use % to match C preprocessor conditionals (#if, #else, and #endif). vile will do automatic source code indentation based on the placement of braces ({ and }). And it will do smart formatting of C comments. The tabstop and shiftwidth options are set on a per-major-mode basis as well.

Using major modes, you can apply the same features to programs written in other languages. This example, courtesy of Thomas Dickey, defines a new major mode, shmode, for editing Bourne shell scripts. (This is useful for any Bourne-style shell, such as ksh, bash, or zsh.)

define-mode sh
set shsuf "\.sh$"
set shpre "^#!\\s*\/.*sh\\>$"
define-submode sh comment-prefix "^\\s*/[:#]"
define-submode sh comments "^\\s*/\\?[:#]\\s+/\\?\\s*$"
define-submode sh fence-if   "^\\s*\\<if\\>"
define-submode sh fence-elif "^\\s*\\<elif\\>"
define-submode sh fence-else "^\\s*\\<else\\>"
define-submode sh fence-fi   "^\\s*\\<fi\\>"

The shsuf (shell suffix) variable describes the file name suffix that indicates a file is a shell script. The shpre (shell preamble) variable describes a first line of the file that indicates that the file contains shell code. The define-submode commands then add options that apply only to buffers where the corresponding major mode is set. The examples here set up the smart comment formatting and the smart % command matching for shell programs.

The example shown is more verbose than needed. vile's scripting language recognizes a more concise description using ~with:

define-mode sh
~with define-submode sh
	suf		"\.sh$"
	pre		"^#!\\s*\/.*sh\\>$"
	comment-prefix	"^\\s*/[:#]"
	comments	"^\\s*/\\?[:#]\\s+/\\?\\s*$"
	fence-if	"^\\s*\\<if\\>"
	fence-elif	"^\\s*\\<elif\\>"
	fence-else	"^\\s*\\<else\\>"
	fence-fi	"^\\s*\\<fi\\>"
~endwith

With its initialization scripts, vile provides 90 pre-defined major modes. Use the :show-majormodes command to see the definitions of the available major modes.

The suffix and prefix are criteria which vile uses to decide which major mode to apply, when it reads a file into a buffer. [4] Table 12.8 lists all of the criteria:

Table 12.8. Major Mode Criteria

Criteria

Description

after

Force the defined major mode to be checked after the given major mode. Normally major modes are checked in the order they are defined.

before

Force the defined major mode to be checked before the given major mode. Normally major modes are checked in the order they are defined.

mode-filename (mf)

A regular expression describing filenames for which the corresponding major mode will be set. The expression is applied only to the portion of the complete pathname after removing the directory name.

mode-pathname (mp)

A regular expression describing pathnames for which the corresponding major mode will be set.

preamble (pre)

A regular expression describing the first line of filenames for which the corresponding major mode will be set.

qualifiers

Tells how to combine the preamble and suffixes criteria. Use all to tell vile to use both, and any to use either.

suffixes (suf)

A regular expression describing filenames for which the corresponding major mode will be set.

You can always tell vile to use a specific major mode, e.g.,

:setl cmode
will set it to "c" mode.[5] But that does not update the syntax highlighting. Use the macro
:set-h cmode
(set-highlighting, see Table 12.7) which does both parts.

12.10.3. The Procedure Language

vile's procedure language is almost unchanged from that of MicroEMACS. Comments begin with a semi-colon or a double quote character. Environment variable names (editor options) start with a $, user variable names start with %. A number of built-in functions exist for doing comparisons and testing conditions; their names all begin with &. Flow control commands and certain others begin with ~. An @ with a string prompts the user for input, and the user's answer is returned. This rather whimsical example from the macros.doc file should give you a taste of the language's flavor:

~if &sequal %curplace "timespace vortex"
	insert-string "First, rematerialize\n"
~endif
~if &sequal %planet "earth"     ;If we have landed on earth...
	~if &sequal %time "late 20th century"  ;and we are then
		write-message "Contact U.N.I.T."
	~else
		insert-string "Investigate the situation....\n"
		insert-string "(SAY 'stay here Sara')\n"
	~endif
~elseif &sequal %planet "luna"  ;If we have landed on our neighbor...
	write-message "Keep the door closed"
~else
	setv %conditions @"Atmosphere conditions outside? "
	~if &sequal %conditions "safe"
		insert-string &cat "Go outside......" "\n"
		insert-string "lock the door\n"
	~else
		insert-string "Dematerialize..try somewhen else"
		newline
	~endif
~endif

You can store these procedures into a numbered macro, or give them names that can be bound to keystrokes. The above procedure is most useful when using the Tardis vile port. ⌣

This more realistic example from Paul Fox runs grep, searching for the word under the cursor in all C source files. It then puts the results in a buffer named after the word, and sets things up so that the built-in error finder (^X ^X) will use this output as its list of lines to visit. Finally, the macro is bound to ^A g. The ~force command allows the following command to fail without generating an error message:

14 store-macro
	set-variable %grepfor $identifier
	edit-file &cat "!egrep -n " &cat %grepfor " *.[ch]"
	~force rename-buffer %grepfor
	error-buffer $cbufname
~endm
bind-key execute-macro-14 ^A-g

User-defined procedures can have parameters, much like Bourne shell – but the parameters can be limited to specific data types. This makes procedures work as expected with vile's editing model (and command-history mechanism). The procedures are not completely interchangeable with the built-in commands, since there is not yet a mechanism for making the undo feature treat a whole macro as a single operation.

Finally, the read-hook and write-hook variables can be set to names of procedures to run after reading and before writing a file, respectively. This allows you to do things similar to pre- and post-operation files in elvis and the autocommand facility in vim.

The language is quite capable, including flow control and comparison features, and variables that provide access to a large amount of vile's internal state. The macros.doc file in the vile distribution describes the language in detail.

12.10.4. Miscellaneous Small Features

Several other, smaller features are worth mentioning:

Piping into vile

If you make vile the last command in a pipeline, it will create a buffer named [Standard Input] and edit that buffer for you. This is perhaps the "pager to end all pagers."

Editing DOS files

When set to true, the dos option causes vile to strip carriage returns at the end of a line in files when reading, and to write them back out again. This makes it easy to edit DOS files on a UNIX or Linux system.

Text reformatting

The ^A f command reformats text, performing word wrapping on selected text. It understands C and shell comments (lines with a leading * or #) and quoted email (a leading >). It is similar to the UNIX fmt command, but faster.

Formatting the information line

The modeline-format variable is a string which controls the way vile formats the status line. This is the line at the bottom of each window that describes the buffer's status, such as its name, current major mode, modification status, insert versus command mode, and so on. [6]

The string consists of printf(3) style percent-sequences. For example, %b for the buffer name, %m for the major mode, and %l for the line number if ruler has been set. Characters in the string which are not part of a format specifier are output verbatim.

vile has many other features. The vi finger-feel makes it easy to move to. The programmability provides flexibility, and its interactive nature and use of defaults is perhaps friendlier for the novice than traditional vi.

Notes

[1]

vile 9.6 has 421 defined functions (including some that are available only in the X11 or Win32 configurations), with predefined key bindings for about 260.

[2]

vile has different flavors of key bindings for insert-, command- and selection-modes. Here we are describing the bindings for the normal editing mode.

[3]

vile's documentation spells it as a single word.

[4]

These criteria are a fourth category of option, counting universal, buffer and window. They are not listed with the others in Table C.5 because you set them in an entirely different way.

[5]

The setl sets the local properties of the buffer. The command

:set cmode
would set the default major mode if vile is unable to recognize the file.

[6]

vile's documentation refers to this as the modeline. However, since vile also implements the vi modeline feature, we are calling it a status line, to reduce confusion.