Editing Scheme files in vi

 Dorai Sitaram 
 Download version 1b2 


But then, when was the last time you heard
of a lisp programmer that used vi?

-- Paul Fox, Vile [1] developer

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-[.

Special keywords

By default, the indentation procedure treats application forms split over two or more lines as follows:

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.

References

[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.

HTML conversion by TeX2page 2003-08-03