@c This is part of the Eplain manual. Public domain. @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. * User-defined environments:: User-defined environments. * Page list and page range parsers:: @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 @cindex user-inaccessible macros @cindex inaccessible macros Sometimes you might want to temporarily change the category code of the `@@' character to @code{\letter}, so that you can use or define macros which are normally inaccessible to the user. For such situations, Eplain provides the @code{\makeatletter} @findex makeatletter command. It sets the category code of `@@' to @code{\letter} (11) and defines @code{\resetatcatcode} @findex resetatcatcode to restore the category code to whatever it was before the call to @code{\makeatletter}. For example: @example \makeatletter \def\@@hidden@@macro@{This macro cannot normally be called / redefined by the user@} \resetatcatcode @end example @noindent There is also @code{\makeatother} @findex makeatother which works similarly but sets the category code of `@@' to @code{\other} (12). 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 @noindent 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{\endcsname}, 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 @code{\testfileexistence} takes an optional parameter; when given, it will override @code{\jobname} for the root part of the file name. For example, if you want to test for the file @file{answers.aux}, you can do this with the following: @example \testfileexistence[answers]@{aux@}% \iffileexists \input answers.aux \fi @end example @node User-defined environments @section User-defined environments @cindex environments, user-defined Plain @TeX{} does not provide ``named'' block structures, only the anonymous @code{\begingroup} and @code{\endgroup} pair. The disadvantage of this is that when there are several such groups and one is mismatched, it can be difficult to find the error. Eplain provides a named block structure so that if you forget an @code{\environment} or an @code{\endenvironment}, you will (probably) get an error message about it. For example: @example \def\itpar@{ \environment@{@@italicpar@} \it\par @} \def\enditpar@{ \par \endenvironment@{@@italicpar@}% @} @end example @noindent which could then be used to set italicized paragraphs: @example \itpar If I reprehend anything in this world, it is the use of my oracular tongue, and a nice derangement of epitaphs! \enditpar @end example The above sort of environment allows nesting. But environments shouldn't always be allowed to nest. Put the control sequence @code{\checkenv} at the beginning of a macro that is going to define an environment that should not be nested. @node Page list and page range parsers @section Page list and page range parsers @findex idxparselist @findex idxparserange @findex idxpagei @findex idxpageii The macros which Eplain uses to parse the page lists and ranges in the index, @code{\idxparselist} and @code{\idxparserange} (@pxref{Page destinations for index terms}), are sometimes useful when defining page number encapsulators. They take one argument, text to parse. When a page list (range) is not present, they set @code{\idxpagei} to be @code{\empty}; when a list (range) is detected, they set @code{\idxpagei} and @code{\idxpageii} to the first and the second page numbers, respectively. @findex setidxpagelistdelimiter @findex setidxpagerangedelimiter Eplain's defaults for the page list and page range delimiters are the same as those in MakeIndex, a comma followed by a space (@samp{, }) and two dashes (@samp{--}), respectively. If you customize MakeIndex to use different delimiters, you must not forget to let Eplain know about them with the commands @example \setidxpagelistdelimiter@{@var{list-delim}@} \setidxpagerangedelimiter@{@var{page-delim}@} @end example @noindent These commands save the @var{list-delim} and @var{page-delim} delimiters in @findex idxpagelistdelimiter @findex idxpagerangedelimiter @code{\idxpagelistdelimiter} and @code{\idxpagerangedelimiter}, respectively. @cindex underlining page numbers in index @cindex index, underlining page numbers @findex ituline For example, you may want to define a page number markup command which italicizes and properly underlines page ranges by underlining only the page numbers and not the delimiter: @findex idxpagerangedelimiter @example \def\ituline#1@{% @{\it \idxparserange@{#1@}% \ifx\idxpagei\empty % The argument is a single page number. \underbar@{#1@}% \else % The argument is a page range. \underbar@{\idxpagei@}\idxpagerangedelimiter\underbar@{\idxpageii@}% \fi@}% @} @end example @noindent Note that the @code{\ituline} macro is not aware of page lists. This is not needed if you use hyperlinks in the index, because @code{\hlidx} and @code{\hlidxpage} will break up the page lists before calling the user's page encapsulator (@pxref{Page destinations for index terms}), so @code{\ituline} will never see the lists. If, however, you need to design a macro which also takes care of the lists, you can extend @code{\ituline} with an additional call to @code{\idxparselist}.