diff options
Diffstat (limited to 'Master/texmf-dist/doc/eplain/base/progdef.texi')
-rw-r--r-- | Master/texmf-dist/doc/eplain/base/progdef.texi | 768 |
1 files changed, 768 insertions, 0 deletions
diff --git a/Master/texmf-dist/doc/eplain/base/progdef.texi b/Master/texmf-dist/doc/eplain/base/progdef.texi new file mode 100644 index 00000000000..4169f151730 --- /dev/null +++ b/Master/texmf-dist/doc/eplain/base/progdef.texi @@ -0,0 +1,768 @@ +@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}. |