vile has a number of interesting features that are the topic of this section.
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.
Changing bindings is very easy to do. You use the :bind-key command. 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:
Keystrokes | Results |
---|---|
: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.
A major mode is a collection of option settings that apply when editing a certain class of file. Many of 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, and is more fully developed in 7.4 and 8.0.
vile has one pre-defined major mode, cmode, for editing C and C++ programs. 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 Tom 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.
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
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.
Several other, smaller features are worth mentioning:
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.
Copyright © 2003 O'Reilly & Associates. All rights reserved.