Plan 9 from Bell Labs’s /usr/web/sources/contrib/steve/root/sys/lib/texmf/doc/eplain/progdef.texi

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


@c Copyright (C) 1992, 93, 94 Karl Berry.
@c This is part of the Eplain manual.
@c For copying conditions, see the file eplain.texi.

@node Programming definitions
@chapter Programming definitions

The definitions in this section are only likely to be useful when you
are writing nontrivial macros, not when writing a document.

@menu
* Category codes::              Changing category codes.
* Allocation macros::           Non-outer versions of \newcount et al.
* Iteration::                   Doing `for' loops in TeX.
* Macro arguments::             Reading and ignoring them.
* Converting to characters::    Normalizing control sequences and spaces.
* Expansion::                   Controlling expansion.
* Obeying spaces::              Making whitespace count anywhere.
* Writing out numbers::         Making `1' into `one'.
* Mode-specific penalties::     
* Auxiliary files::             Testing for their existence.
@end menu


@node Category codes
@section Category codes

@cindex category codes

Plain @TeX{} defines @code{\active} (as the number 13) for use in
changing category codes.  Although the author of @cite{The @TeX{}book}
@cindex Knuth, Donald Ervin
has ``intentionally kept the category codes numeric'', two other
categories are commonly used: letters (category code 11) and others
(12).  Therefore, Eplain defines @code{\letter} and
@code{\other}.
@findex letter
@findex other

Sometimes it is cleaner to make a character active without actually
@cindex active characters
writing a @code{\catcode} command.  The @code{\makeactive} command takes
@findex catcode
@findex makeactive
a character as an argument to make active (and ignores following
spaces).  For example, here are two commands which both make @kbd{\}
active:
@cindex backslash character

@example
\makeactive`\\   \makeactive92
@end example

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
@code{\obeyspaces} in @cite{The @TeX{}book}).
@cindex definitions, global
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 @code{\letreturn}, which defines the usual end-of-line
@findex letreturn
@cindex return character
character to be the argument.  For example:

@example
\def\mymacro@{@dots{} \letreturn\myreturn @dots{} @}
\mymacro hello
there
@end example

The end-of-line between @samp{hello} and @samp{there} causes
@code{\myreturn} to be expanded.

@cite{The @TeX{}book} describes @code{\uncatcodespecials},
@findex 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, @code{\percentchar}
@findex percentchar
expands into a literal `%' character.  This is useful when you
@code{\write} @TeX{} output to a file, and want to avoid spurious
spaces.  For example, Eplain writes a @code{\percentchar} after the
definition of cross-references.  The macros @code{\lbracechar}
@findex lbracechar
and @code{\rbracechar}
@findex rbracechar
expand similarly.


@node Allocation macros
@section Allocation macros

@cindex allocation macros
@cindex register allocation

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 @samp{new},
@findex new@dots{}
e.g., @code{\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 @code{\outer},
@findex 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 @samp{inner}:
@code{\innernewbox},
@findex innernewbox
@code{\innernewcount},
@findex innernewcount
@code{\innernewdimen},
@findex innernewdimen
@code{\innernewfam},
@findex innernewfam
@code{\innernewhelp},
@findex innernewhelp
@code{\innernewif},
@findex innernewif
@code{\innernewinsert},
@findex innernewinsert
@code{\innernewlanguage},
@findex innernewlanguage
@code{\innernewread},@*
@findex innernewread
@code{\innernewskip},
@findex innernewskip
@code{\innernewtoks},
@findex innernewtoks
@code{\innernewwrite}.
@findex 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
@code{\innerdef}:
@findex innerdef

@example
\innerdef @var{\innername} @{@var{outername}@}
@end example

The first argument (@var{\innername}) to @code{\innerdef} is the
control sequence that you want to define.  Any previous definition of
@var{\innername} is replaced.  The second argument
(@var{outername}) is the @emph{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 @var{\cs}, and you want to
define @code{inner@var{cs}} as the inner one, you can use
@code{\innerinnerdef},
@findex innerinnerdef
which is just an abbreviation for a call to @code{\innerdef}.  For
example, these two calls are equivalent:

@example
\innerdef\innerproclaim@{proclaim@}
\innerinnerdef@{proclaim@}
@end example


@node Iteration
@section Iteration

@cindex iteration
@cindex for loops

You can iterate through a comma-separated list of items with
@code{\for}.
@findex for
Here is an example:

@example
\for\name:=karl,kathy\do@{%
   \message@{\name@}%
@}%
@end example

This writes @samp{karl} and @samp{kathy} to the terminal.  Spaces
before or after the commas in the list, or after the @code{:=}, are
@emph{not} ignored.

@code{\for} expands the iterated values fully (with @code{\edef}), so
this is equivalent to the above:

@example
\def\namelist@{karl,kathy@}%
\for\name:=\namelist\do @dots{}
@end example


@node Macro arguments
@section Macro arguments

@cindex arguments, ignoring
@cindex ignoring arguments
@cindex gobbling arguments
It is occasionally useful to redefine a macro that takes arguments to
do nothing.  Eplain defines @code{\gobble},
@findex gobble
@code{\gobbletwo},
@findex gobbletwo
and @code{\gobblethree} to swallow one, two, and three arguments,
respectively.

For example, if you want to produce a ``short'' table of
@cindex table of contents, short
contents---one that includes only chapters, say---the easiest thing to
do is read the entire @code{.toc} file (@pxref{Contents}), and just
ignore the commands that produce section or subsection entries.  To be
specific:

@example
\let\tocchapterentry = \shorttocchapter
\let\tocsectionentry = \gobbletwo
\let\tocsubsectionentry = \gobbletwo
\readtocfile
@end example
@noindent (Of course, this assumes you only have chapters, sections, and
subsections in your document.)

In addition, Eplain defines @code{\eattoken}
@findex eattoken
to swallow the single following token, using @code{\let}.  Thus,
@code{\gobble} followed by @samp{@{@dots{}@}} ignores the entire
brace-enclosed text.  @code{\eattoken} followed by the same ignores only
the opening left brace.

Eplain defines a macro @code{\identity}
@findex 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 @code{\eqconstruct} (@pxref{Formatting equation
references}) is @code{\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 @code{\futurenonspacelet}.

You test for an optional argument by using @code{\@@getoptionalarg}.
@c this confuses texinfo.tex: findex @@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 @code{\@@optionalarg} expands to it; otherwise,
@code{\@@optionalarg} is @code{\empty}.  You must therefore have the
category code of @kbd{@@} set to 11 (letter).  Here is an example:

@example
\catcode`@@=\letter
\def\cmd@{\@@getoptionalarg\finishcmd@}
\def\finishcmd@{%
  \ifx\@@optionalarg\empty
    % @r{No optional argument present.}
  \else
    % @r{One was present.}
  \fi
@}
@end example

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.


@node Converting to characters
@section Converting to characters

@cindex characters, converting to
Eplain defines  @code{\xrlabel}
@findex xrlabel
to produce control sequence names for cross-reference labels, et al.
This macro expands to its argument with an @samp{_} appended.  (It does
this because the usual use of @code{\xrlabel} is to generate a control
sequence name, and we naturally want to avoid conflicts between control
sequence names.)

Because @code{\xrlabel} is fully expandable, to make a control
sequence name out of the result you need only do
@example
@code{\csname \xrlabel@{@var{label}@}\endcsname}
@end example

@noindent The @code{\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 @samp{\},
@samp{@{}, @samp{@}}, and @samp{#}, all of which are used in macro
definitions themselves.

@findex sanitize
@code{\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 @code{\writenumberedtocentry}; @code{#2} is the title that the user
has given.

@example
@dots{}
\def\temp@{#2@}%
@dots{}
  \write\tocfile@{%
    @dots{}
    \sanitize\temp
    @dots{}
  @}%
@end example


@node Expansion
@section Expansion

This section describes some miscellanous macros for expansion, etc.

@menu
* \csn and \ece::               Abbreviations for \csname expansions.
* \edefappend::                 
* Hooks::                       Manipulating and executing named actions.
* Properties::                  Associating information with a csname.
* \expandonce::                 
* \ifundefined::                
* \futurenonspacelet::          
@end menu


@node \csn and \ece
@subsection @code{\csn} and @code{\ece}

@findex csn
@code{\csn}@{@var{name}@} simply abbreviates @code{\csname} @var{name}
@code{\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.

@findex ece
@code{\ece}@{@var{token}@}@{@var{name}@} abbreviates

@example
\expandafter @var{token} \csname @var{name} \endcsname
@end example

@noindent For example,

@example
\def\fontabbrevdef#1#2@{\ece\def@{@@#1font@}@{#2@}@}
\fontabbrevdef@{normal@}@{ptmr@}
@end example

@noindent defines a control sequence @code{\@@normalfont} to expand to
@code{ptmr}.


@node \edefappend
@subsection @code{\edefappend}

@findex edefappend
@code{\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 @code{\edef} that redefines the control sequence).

For example:

@example
\def\foo@{abc@}
\def\bar@{xyz@}
\edefappend\foo@{\bar karl@}
@end example

@noindent results in @code{\foo} being defined as @samp{abcxyzkarl}.


@node Hooks
@subsection Hooks

@cindex hooks
A @dfn{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 @code{\every @dots{}} 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.

@table @code

@findex hookaction
@itemx hookaction @var{name} @var{actions}
@findex hookappend
@itemx hookappend @var{name} @var{actions}
@findex hookprepend
@item hookprepend @var{name} @var{actions}
Each of these adds @var{actions} to the hook @var{name}.  (Any
previously-defined actions are retained.)  @var{name} is not a control
sequence, but rather the characters of the name.

@findex hookactiononce
@item hookactiononce @var{name} @code{\@var{cs}}
@code{\hookactiononce} adds @var{cs} to @var{name}, like the macros
above, but first it adds

@example
\global\let @var{\cs} \relax
@end example

@noindent to the definition of @var{\cs}.  (This implies @var{\cs} must
be a true expandable macro, not a control sequence @code{\let} to a
primitive or some other such thing.)  Thus, @var{\cs} is expanded the
next time the hook @var{name} is run, but it will disappear after that.

The @code{\global} is useful because @code{\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.
@end table

@findex hookrun
The companion macro to defining hook actions is @code{\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 @code{\begin} and @code{\end} macros that
run hooks, and a couple of calls to define actions.  The use of
@code{\hookprepend} for the begin action and @code{\hookappend} for the
end action ensures that the actions are executed in proper sequence with
other actions (as long as the other actions use @code{\hookprepend} and
@code{\hookappend} also).

@example
\def\begin#1@{ @dots{} \hookrun@{begin@} @dots{} @}
\def\end#1@{ @dots{} \hookrun@{end@} @dots{} @}
\hookprepend@{begin@}\start_underline
\hookappend@{end@}\finish_underline
@end example


@node Properties
@subsection Properties

@cindex properties
@cindex atom
A @dfn{property} is a name/value pair associated with another symbol,
traditionally called an @dfn{atom}.  Both atom and property names are
control sequence names.

Eplain provides two macros for dealing with property lists:
@code{\setproperty} and @code{\getproperty}.

@table @code

@findex setproperty
@item \setproperty @var{atom} @var{propname} @var{value}
@code{\setproperty} defines the property @var{property} on the atom
@var{atom} to be @var{value}.  @var{atom} and @var{propname} can be
anything acceptable to @code{\csname}.  @var{value} can be anything.

@findex getproperty
@item \getproperty @var{atom} @var{propname}
@code{\getproperty} expands to the value stored for @var{propname} on
@var{atom}.  If @var{propname} is undefined, it expands to nothing
(i.e., @code{\empty}).

@end table

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 @samp{xyz}.

@example
\setproperty@{a@}@{pr@}@{xyz@}
\getproperty@{a@}@{pr@}
@end example


@node \expandonce
@subsection @code{\expandonce}

@cindex expansion, one-level 
@findex expandonce
@code{\expandonce} is defined as @code{\expandafter\noexpand}.  Thus, 
@code{\expandonce @var{token}} expands @var{token} once, instead of to
@TeX{} primitives.  This is most useful in an @code{\edef}.  

For example, the following defines @code{\temp} to be @code{\foo}, not
@samp{abc}.

@example
\def\foo@{abc@}
\def\bar@{\foo@}
\edef\temp@{\expandonce\bar@}
@end example


@node \ifundefined
@subsection @code{\ifundefined}

@findex ifundefined
@code{\ifundefined@{@var{cs}@} @var{t} \else @var{f} \fi} expands the
@var{t} text if the control sequence @code{\@var{cs}} is undefined or
has been @code{\let} to @code{\relax}, and the @var{f} text otherwise.

@cindex skipping tokens
@cindex undefined control sequence, checking for
Since @code{\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 @code{\if}'s and
@code{\fi}'s.

This macro was taken directly from @cite{The @TeX{}book}, page 308.


@node \futurenonspacelet
@subsection @code{\futurenonspacelet}

@cindex lookahead without spaces
@cindex spaces, ignoring
@findex futurenonspacelet
The @code{\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 @code{\futurenonspacelet} does.  It is otherwise
the same as @code{\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:

@example
\futurenonspacelet\temp\finishup
\def\finishup@{\ifx\temp @dots{}@}
@end example


@node Obeying spaces
@section Obeying spaces

@cindex whitespace
@cindex spaces, obeying
@cindex newlines, obeying
@findex obeywhitespace

@code{\obeywhitespace} makes both end-of-lines and space characters in
the input be respected in the output.  Unlike plain @TeX{}'s
@code{\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 @code{\ } 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 @code{\blanklineskipamount}:
@findex blanklineskipamount @r{in obeyed text}
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 @i{expand} instead.)
@cindex tabs


@node Writing out numbers
@section Writing out numbers

@cindex numbers, written form of
   @code{\numbername}
@findex numbername
produces the written-out form of its argument, i.e., `zero' through
`ten' for the numbers 0--10, and numerals for all others.


@node Mode-specific penalties
@section Mode-specific penalties

@TeX{}'s built-in @code{\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
@code{\vpenalty}
@findex vpenalty
and @code{\hpenalty}
which first leave the other mode and then do @code{\penalty}.

More precisely, @code{\vpenalty} inserts @code{\par} if the current
mode is horizontal, and @code{\hpenalty} inserts @code{\leavevmode} if
the current mode is vertical.  (Thus, @code{\vpenalty} cannot be used in
math mode.)


@node Auxiliary files
@section Auxiliary files

@cindex axuiliary files, existence of
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.  @code{\testfileexistence}
@findex testfileexistence
is given an argument which is appended to @code{\jobname},
@findex jobname
and sets the conditional @code{\iffileexists}
@findex iffileexists
@findex fileexists @r{(conditional)}
appropriately.

For example:

@example
\testfileexistence@{toc@}%
\iffileexists
   \input \jobname.toc
\fi
@end example

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.