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 \eval
s can
use definitions introduced in previous \eval
s,
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
\eval
s, 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].