The command \eval allows you to use arbitrary
Lisp
expressions, as opposed to just TeX macros, to
guide the course of the typesetter.
The text written
to standard output by the Lisp code is substituted
for the \eval statement. E.g., consider the
following complete document, root2.tex:
\input tex2page
The square root of 2 is
\eval{
(princ (sqrt 2))
}. \byeRunning TeX2page on
root2.tex produces
the following HTML output:
The square root of 2 is 1.4142135623730951.
In effect, TeX2page processes the \eval call
using Lisp, producing some output in an auxiliary
TeX file, which is then re-inserted into the document at the location of
the \eval.
A definition for \eval that TeX can use
is provided in the macro file eval4tex.tex.
tex2page.tex will automatically load eval4tex.tex if it finds it in
TEXINPUTS.
Thus, running TeX on
root2.tex produces a DVI file whose
content matches the HTML version.
It is clear that Lisp code via \eval can serve as
a very powerful second extension language for
TeX, and that its benefits are available to both the
DVI and the HTML outputs. As we have seen, TeX2page
implements a subset of the TeX macro language, and for
those cases where this macro language isn’t enough,
Lisp can be used to fill the breach. More generally,
Lisp may be preferable to the TeX macro language even
for just DVI, where no HTML version of the document is
contemplated. We’ll explore both of these
aspects of \eval.
\eval’s argument is a balanced-brace
expression. At the top-level, i.e., not within the body of a macro,
\eval’s argument is sent verbatim to Lisp, except that the pipe character
(‘|’) functions as the TeX escape. Use || to represent a single
pipe in the Lisp code. If you need to include an unmatched brace, simply
put a bogus matching brace inside a Lisp comment.
Inside a macro body, it is too late for \eval to set the catcodes
to make verbatim any character within its argument. Either define or
use control sequences to represent special characters, or use
Lisp
workarounds (e.g., code‑char) to construct those characters.
Let us 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 presenting a prototypical
use of it.
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
(I.e., 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 Lisp:
\ifx\shipout\UnDeFiNeD
\eval{
(defun all-blanks-p (s) (every (lambda (c) (or (char= c #\space) (char= c #\tab) (not (graphic-char-p c)))) s))
}
\def\spaceifnotempty{\eval{
(let ((x (ungroup (get-token)))) (unless (all-blanks-p x) (princ (code-char 92)) (princ "space")))
}} \fiNote that we had to use
(code‑char 92) to refer to the
backslash character, as the \eval is inside a macro body and ‘\’
is not and cannot be made a letter.
(Otherwise we could have simply written (princ "\\space").)
Later \evals can
use definitions introduced in previous \evals,
as with all‑blanks‑p in our example.
If being processed by TeX2page only (as in our example),
the code inside \eval is allowed to use not just general Lisp
but also procedures like
ungroup and get‑token, which are defined by
TeX2page. (There is no need to package-qualify their names, as \eval
code is evaluated inside the tex2page package.)
The key thing to remember is that
an \eval-call is replaced by whatever text the
Lisp code in that \eval-call writes to its
standard output. This approach will work whether the
document is being processed by TeX2page to produce HTML
or by TeX to produce DVI.
For those TeX documents that are not intended for HTML conversion, but
nevertheless use \eval, this macro is available in the macro file
eval4tex.tex. Run TeX (or LaTeX) on such a document, say
jobname.tex, and then evaluate
the resultant jobname‑Z‑E.lisp in Lisp, to create the
necessary aux TeX files. Running TeX on the master document a second
time will
insert these aux TeX files at the location of the corresponding \eval
calls. This is quite analogous to how TeX2page would have processed the
\evals, except that TeX requires you to explicitly call Lisp to
create the aux files which it can use on its second run, whereas
TeX2page, being written in Lisp, creates and loads the aux files
immediately.
For complete details on using \eval with
TeX, please consult the companion manual,
An \eval for
TeX [44].