9  Scheme as TeX's extension language

The command \eval allows you to use arbitrary Scheme expressions, as opposed to just TeX macros, to guide the course of the typesetter. Note that by typesetter we mean both TeX (which produces DVI output) and TeX2page (which produces HTML output).

Since there are two outputs to distinguish, we cannot get by with just one standard output port in the Scheme code introduced by \eval. So, we will use the regular standard output port for \eval's TeX output (which eventually becomes DVI), and the port *html* for \eval's TeX2page output (which eventually becomes part of the final HTML). We can use this feature to play to a medium-selected gallery.

\eval{
(display "Paper beats screen.") 
(newline)

(display "Screen beats paper." *html*)
(newline *html*)
}

\eval allows the document writer access to full Scheme, including the Scheme definitions inside the TeX2page implementation. This serves as a very powerful second extension language. The first extension language is the TeX macro language, or rather, TeX2page's implementation of a subset of the TeX macro language.

Note that the extensions possible through \eval and Scheme are not restricted to the HTML output only. The print output is equally maneuverable via Scheme. Indeed, we can use \eval to introduce new functionality that is used consistently in both the browsable and printable outputs.

But first we will first look at a simple example where \eval lets you define an HTML version of an already existing TeX macro that is either impossible or at least prohibitively difficult to process using TeX2page's mimicry of TeX. Consider a hypothetical \proto macro, used to introduce the description of a Lisp operator by giving a prototypical call. Typical calls to \proto are:

\proto{cons}{a d}{procedure}
\proto{car}{c}{procedure}
\proto{cdr}{c}{procedure}

which typeset as follows:

(cons a d)        ;procedure

(car c)        ;procedure

(cdr c)        ;procedure

The macro \proto takes three arguments: the operator name; the metavariables for its operands; and the operator kind. In particular, it typesets the operator and the operands in different fonts, surrounding the call in parens. Note the intervening space between operator and operands.

In the case where there are no operands, the intervening space should not. Thus,

\proto{gentemp}{}{procedure}

should not produce

(gentemp )        ;procedure

but rather

(gentemp)        ;procedure

(Ie, no space between gentemp and the closing paren.)

The \proto macro can be written in TeX as follows:

\def\proto#1#2#3{\noindent
\hbox{{\tt(#1}\spaceifnotempty{#2}{\it#2}{\tt)}%
\qquad ;#3}\par}

where, \spaceifnotempty is a helper macro that expands to a space only if its argument is not empty. TeX2page can expand this definition for \proto, provided it knows how to deal with the \spaceifnotempty.

One way to write \spaceifnotempty in TeX is:

\newdimen\templen
\newbox\tempbox

\def\spaceifnotempty#1{%
\setbox\tempbox\hbox{#1}%
\templen\wd\tempbox
\ifdim\templen>0pt{\ }\fi}

This piece of box-measuring contortion is too much for TeX2page's mimicry of the TeX macro system. However it's easy enough to achieve the same effect using the string-processing capabilities of TeX2page's extension language, Scheme:

\htmlonly

\eval{
(define all-blanks?
  (lambda (s)
    (andmap char-whitespace?
      (string->list s))))
}

\def\spaceifnotempty{\eval{
(let ((x (ungroup (get-token))))
  (if (not (all-blanks? x))
    (display " " *html*)))
}}

\endhtmlonly

\eval's argument is a balanced-brace expression that can contain any character at all, including %. (If you need to include an unmatched brace in \eval's argument, simply put a bogus matching brace inside a Scheme comment.)