The ability to automatically indent code is
indispensable when editing files containing Scheme code
or other s-expression-based text such Common Lisp,
ART*Enterprise, and other Lisps. Vi provides the
option lisp, which in conjunction with the options
autoindent, lispwords, and showmatch
provides a form of Lisp indenting, but except in the
improved Vi clone Vim [5], this support is poor
in at least two respects: (1) Escaped parentheses are
not treated correctly; and (2) all head-words
are treated like define.
Fortunately, Vi lets you delegate the responsibility
for indenting such code to an external filter program
of your choosing. This distribution provides a
filtering script scmindent.scm written in Scheme.
scmindent.scm
takes Scheme text from its standard input and produces
an indented version thereof on its standard output.
(Thus, it is possible to use
scmindent.scm as a command-line filter to
``beautify'' Scheme code, even if you don't use Vi.)
Recall that in Vi, one invokes a filter by typing
! (the ``bang'' or ``exclamation point'' character),
then a movement command,
and then the filter's name
followed by Return.
This causes the filter to act on the block of text spanned by the movement command. For instance, to indent the first 20 lines of the current buffer, you could type
1G to go to the top of the buffer,
then ! to declare that you'll be filtering,
then 19j to scoop up the 20 lines in question,
then scmindent.scm
and Return.
This assumes you've placed scmindent.scm in your
PATH. (Windows users should invoke something like
mzscheme -f \ebin\escmindent.scm (use the appropriate
pathname) instead of scmindent.scm.)
It is convenient to map a keyboard character to some
preferred or typical indenting sequence, such as
indenting the block of code containing the current
line. This can be accomplished by putting the
following command in your .exrc file:
map [q {!}scmindent.scm<CR>
Here, <CR> is the quoted (Carriage)
Return character, and is entered (in Vi) by typing
Control-V followed by Return or Control-M.
This map has the side-effect of moving your cursor to the start of the indented block, which could possibly be many lines away from the line you were working on before starting the indent. The following, only slightly more complicated, map takes care to keep the cursor on the current line:
map [q O;;;;;-;;;;;<Esc>{!}scmindent.scm<CR>/^ *;;;;;-;;;;;<CR>dd
Here, <Esc> is the quoted Escape character, and is
entered (in Vi) by typing Control-V followed
by Escape or Control-[.
By default, the indentation procedure treats application forms split over two or more lines as follows:
If the head of the form (i.e., its first subform) is followed by at least one other subform on the same line, then subsequent lines in the form are indented to line up directly under the second subform.
If the head subform is on a line by itself, then subsequent lines in the form are indented to line up directly under the head subform.
For example:
(head-subform subform-1
subform-2
...)
(head-subform
subform-1
subform-2
...)
However, certain head symbols like define, lambda,
and let are treated specially. For these, subforms
on subsequent lines are always indented one space
after the beginning of the head subform. E.g.,
(define subform-1 subform-2) (define subform-1 subform-2)
You can have other keywords indent like define by
putting them in the
file .schemewords in your home directory. This file, if it
exists, should
should contain a Scheme list of symbols.
For example,
~/.schemewords with the following contents
( define-macro define-struct )
will cause these keywords to henceforth indent like
define.
| [1] |
Paul Fox, Tom Dickey, and Kevin Buettner.
vile - VI Like
Emacs.
|
| [2] |
Thomer M Gil.
vi Lovers Home Page.
|
| [3] |
Sven Guckes.
The vi Editor and Its
Clones.
|
| [4] |
Linda Lamb and Arnold Robbins.
Learning the vi
Editor.
O'Reilly, 6th edition, 1998.
|
| [5] |
Bram Moolenaar.
The VIM (Vi IMproved) Home Page.
|