The definitions in this section are only likely to be useful when you are writing nontrivial macros, not when writing a document.
Plain TeX defines \active
(as the number 13) for use in
changing category codes. Although the author of The TeXbook
has "intentionally kept the category codes numeric", two other
categories are commonly used: letters (category code 11) and others
(12). Therefore, Eplain defines \letter
and
\other
.
Sometimes it is cleaner to make a character active without actually
writing a \catcode
command. The \makeactive
command takes
a character as an argument to make active (and ignores following
spaces). For example, here are two commands which both make \
active:
\makeactive`\\ \makeactive92
Usually, when you give a definition to an active character, you have
to do so inside a group where you temporarily make the character active,
and then give it a global definition (cf. the definition of
\obeyspaces
in The TeXbook).
This is inconvenient if you are writing a long macro, or if the
character already has a global definition you do not wish to transcend.
Eplain provides \letreturn
, which defines the usual end-of-line
character to be the argument. For example:
\def\mymacro{... \letreturn\myreturn ... } \mymacro hello there
The end-of-line between `hello' and `there' causes
\myreturn
to be expanded.
The TeXbook describes \uncatcodespecials
,
which makes all characters which are normally "special" into "other"
characters, but the definition never made it into plain TeX.
Eplain therefore defines it.
Finally, \percentchar
expands into a literal `%' character. This is useful when you
\write
TeX output to a file, and want to avoid spurious
spaces. For example, Eplain writes a \percentchar
after the
definition of cross-references. The macros \lbracechar
and \rbracechar
expand similarly.
Plain TeX provides macros that allocate registers of each primitive
type in TeX, to prevent different sets of macros from using the same
register for two different things. The macros are all named starting
with `new',
e.g., \newcount
allocates a new "count"
(integer) register. Such allocations are usually needed only at the top
level of some macro definition file; therefore, plain TeX makes the
allocation registers \outer
,
to help find errors. (The error this helps to find is a missing right
brace in some macro definition.)
Sometimes, however, it is useful to allocate a register as part of
some macro. An outer control sequence cannot be used as part of a macro
definition (or in a few other contexts: the parameter text of a
definition, an argument to a definition, the preamble of an alignment,
or in conditional text that is being skipped). Therefore, Eplain
defines "inner" versions of all the allocation macros, named with the
prefix `inner':
\innernewbox
,
\innernewcount
,
\innernewdimen
,
\innernewfam
,
\innernewhelp
,
\innernewif
,
\innernewinsert
,
\innernewlanguage
,
\innernewread
,
\innernewskip
,
\innernewtoks
,
\innernewwrite
.
You can also define non-outer versions of other macros in the same way
that Eplain defines the above. The basic macro is called
\innerdef
:
\innerdef \innername {outername}
The first argument (\innername) to \innerdef
is the
control sequence that you want to define. Any previous definition of
\innername is replaced. The second argument
(outername) is the characters in the name of the outer
control sequence. (You can't use the actual control sequence name,
since it's outer!)
If the outer control sequence is named \cs, and you want to
define innercs
as the inner one, you can use
\innerinnerdef
,
which is just an abbreviation for a call to \innerdef
. For
example, these two calls are equivalent:
\innerdef\innerproclaim{proclaim} \innerinnerdef{proclaim}
You can iterate through a comma-separated list of items with
\for
.
Here is an example:
\for\name:=karl,kathy\do{% \message{\name}% }%
This writes `karl' and `kathy' to the terminal. Spaces
before or after the commas in the list, or after the :=
, are
not ignored.
\for
expands the iterated values fully (with \edef
), so
this is equivalent to the above:
\def\namelist{karl,kathy}% \for\name:=\namelist\do ...
It is occasionally useful to redefine a macro that takes arguments to
do nothing. Eplain defines \gobble
,
\gobbletwo
,
and \gobblethree
to swallow one, two, and three arguments,
respectively.
For example, if you want to produce a "short" table of
contents--one that includes only chapters, say--the easiest thing to
do is read the entire .toc
file (see section Contents), and just
ignore the commands that produce section or subsection entries. To be
specific:
\let\tocchapterentry = \shorttocchapter \let\tocsectionentry = \gobbletwo \let\tocsubsectionentry = \gobbletwo \readtocfile
(Of course, this assumes you only have chapters, sections, and subsections in your document.)
In addition, Eplain defines \eattoken
to swallow the single following token, using \let
. Thus,
\gobble
followed by `{...}' ignores the entire
brace-enclosed text. \eattoken
followed by the same ignores only
the opening left brace.
Eplain defines a macro \identity
which takes one argument and expands to that argument. This may be
useful if you want to provide a function for the user to redefine, but
don't need to do anything by default. (For example, the default
definition of \eqconstruct
(see section Formatting equation references) is \identity
.)
You may also want to read an optional argument. The established
convention is that optional arguments are put in square brackets, so
that is the syntax Eplain recognizes. Eplain ignores space tokens
before an optional argument, via \futurenonspacelet
.
You test for an optional argument by using \@getoptionalarg
.
It takes one argument, a control sequence to expand after reading the
argument, if present. If an optional argument is present, the control
sequence \@optionalarg
expands to it; otherwise,
\@optionalarg
is \empty
. You must therefore have the
category code of @ set to 11 (letter). Here is an example:
\catcode`@=\letter \def\cmd{\@getoptionalarg\finishcmd} \def\finishcmd{% \ifx\@optionalarg\empty % No optional argument present. \else % One was present. \fi }
If an optional argument contains another optional argument, the inner one will need to be enclosed in braces, so TeX does not mistake the end of the first for the end of the second.
Eplain defines \xrlabel
to produce control sequence names for cross-reference labels, et al.
This macro expands to its argument with an `_' appended. (It does
this because the usual use of \xrlabel
is to generate a control
sequence name, and we naturally want to avoid conflicts between control
sequence names.)
Because \xrlabel
is fully expandable, to make a control
sequence name out of the result you need only do
\csname \xrlabel{label}\endcsname
The \csname
primitive makes a control sequence name out
of any sequence of character tokens, regardless of category code.
Labels can therefore include any characters except for `\',
`{', `}', and `#', all of which are used in macro
definitions themselves.
\sanitize
takes a control sequence as an argument and converts
the expansion of the control sequence into a list of character tokens.
This is the behavior you want when writing information like chapter
titles to an output file. For example, here is part of the definition
of \writenumberedtocentry
; #2
is the title that the user
has given.
... \def\temp{#2}% ... \write\tocfile{% ... \sanitize\temp ... }%
This section describes some miscellanous macros for expansion, etc.
\csn
and \ece
\csn
{name} simply abbreviates \csname
name
\encsname
, thus saving some typing. The extra level of expansion
does take some time, though, so I don't recommend it for an inner loop.
\expandafter token \csname name \endcsname
For example,
\def\fontabbrevdef#1#2{\ece\def{@#1font}{#2}} \fontabbrevdef{normal}{ptmr}
defines a control sequence \@normalfont
to expand to
ptmr
.
\edefappend
\edefappend
is a way of adding on to an existing definition. It
takes two arguments: the first is the control sequence name, the second
the new tokens to append to the definition. The second argument is
fully expanded (in the \edef
that redefines the control sequence).
For example:
\def\foo{abc} \def\bar{xyz} \edefappend\foo{\bar karl}
results in \foo
being defined as `abcxyzkarl'.
A hook is simply a name for a group of actions which is executed
in certain places--presumably when it is most useful to allow
customization or modification. TeX already provides many builtin
hooks; for example, the \every ...
token lists are all
examples of hooks.
Eplain provides several macros for adding actions to hooks. They all take two arguments: the name of the hook and the new actions.
hookaction name actions
hookappend name actions
hookprepend name actions
hookactiononce name \cs
\hookactiononce
adds cs to name, like the macros
above, but first it adds
\global\let \cs \relaxto the definition of \cs. (This implies \cs must be a true expandable macro, not a control sequence
\let
to a
primitive or some other such thing.) Thus, \cs is expanded the
next time the hook name is run, but it will disappear after that.
The \global
is useful because \hookactiononce
is most
useful when the grouping structure of the TeX code could be anything.
Neither this nor the other hook macros do global assignments to the hook
variable itself, so TeX's usual grouping rules apply.
The companion macro to defining hook actions is \hookrun
, for
running them. This takes a single argument, the name of the hook. If
no actions for the hook are defined, no error ensues.
Here is a skeleton of general \begin
and \end
macros that
run hooks, and a couple of calls to define actions. The use of
\hookprepend
for the begin action and \hookappend
for the
end action ensures that the actions are executed in proper sequence with
other actions (as long as the other actions use \hookprepend
and
\hookappend
also).
\def\begin#1{ ... \hookrun{begin} ... } \def\end#1{ ... \hookrun{end} ... } \hookprepend{begin}\start_underline \hookappend{end}\finish_underline
A property is a name/value pair associated with another symbol, traditionally called an atom. Both atom and property names are control sequence names.
Eplain provides two macros for dealing with property lists:
\setproperty
and \getproperty
.
\setproperty atom propname value
\setproperty
defines the property property on the atom
atom to be value. atom and propname can be
anything acceptable to \csname
. value can be anything.
\getproperty atom propname
\getproperty
expands to the value stored for propname on
atom. If propname is undefined, it expands to nothing
(i.e., \empty
).
The idea of properties originated in Lisp (I believe). There, the implementation truly does associate properties with atoms. In TeX, where we have no builtin support for properties, the association is only conceptual.
The following example typesets `xyz'.
\setproperty{a}{pr}{xyz} \getproperty{a}{pr}
\expandonce
\expandonce
is defined as \expandafter\noexpand
. Thus,
\expandonce token
expands token once, instead of to
TeX primitives. This is most useful in an \edef
.
For example, the following defines \temp
to be \foo
, not
`abc'.
\def\foo{abc} \def\bar{\foo} \edef\temp{\expandonce\bar}
\ifundefined
\ifundefined{cs} t \else f \fi
expands the
t text if the control sequence \cs
is undefined or
has been \let
to \relax
, and the f text otherwise.
Since \ifundefined
is not a primitive conditional, it cannot be
used in places where TeX might skip tokens "at high speed", e.g.,
within another conditional---TeX can't match up the \if
's and
\fi
's.
This macro was taken directly from The TeXbook, page 308.
\futurenonspacelet
The \futurelet
primitive allows you to look at the next token
from the input. Sometimes, though, you want to look ahead ignoring any
spaces. This is what \futurenonspacelet
does. It is otherwise
the same as \futurelet
: you give it two control sequences as
arguments, and it assigns the next nonspace token to the first, and then
expands the second. For example:
\futurenonspacelet\temp\finishup \def\finishup{\ifx\temp ...}
\obeywhitespace
makes both end-of-lines and space characters in
the input be respected in the output. Unlike plain TeX's
\obeyspaces
, even spaces at the beginnings of lines turn into
blank space.
By default, the size of the space that is produced by a space
character is the natural space of the current font, i.e.,
what \
produces.
Ordinarily, a blank line in the input produces as much blank vertical
space as a line of text would occupy. You can adjust this by assigning
to the parameter \blanklineskipamount
:
if you set this negative, the space produced by a blank line will be
smaller; if positive, larger.
Tabs are not affected by this routine. In particular, if tabs occur at the beginning of a line, they will disappear. (If you are trying to make TeX do the "right thing" with tabs, don't. Use a utility program like expand instead.)
\numbername
produces the written-out form of its argument, i.e., `zero' through
`ten' for the numbers 0--10, and numerals for all others.
TeX's built-in \penalty
command simply appends to the
current list, no matter what kind of list it is. You might intend a
particular penalty to always be a "vertical" penalty, however, i.e.,
appended to a vertical list. Therefore, Eplain provides
\vpenalty
and \hpenalty
which first leave the other mode and then do \penalty
.
More precisely, \vpenalty
inserts \par
if the current
mode is horizontal, and \hpenalty
inserts \leavevmode
if
the current mode is vertical. (Thus, \vpenalty
cannot be used in
math mode.)
It is common to write some information out to a file to be used on a
subsequent run. But when it is time to read the file again, you only
want to do so if the file actually exists. \testfileexistence
is given an argument which is appended to \jobname
,
and sets the conditional \iffileexists
appropriately.
For example:
\testfileexistence{toc}% \iffileexists \input \jobname.toc \fi