%^^A* copyright % \iffalse % % This program is part of the Frankenstein bundle for LaTeX2e. % % Copyright (C) 1995, 1996 Matt Swift % % This program is free software; you can redistribute it and/or modify % it under the terms of the GNU General Public License as published by % the Free Software Foundation; either version 2 of the License, or % (at your option) any later version. % % This program is distributed in the hope that it will be useful, % but WITHOUT ANY WARRANTY; without even the implied warranty of % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the % GNU General Public License for more details. % % You should have received a copy of the GNU General Public License % along with this program; if not, write to the Free Software % Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. % % NOTE: I am willing to specially license this code. % Please simply contact me with your proposal. % %^^A NOTE: \DocInput will start reading after this \fi: % \fi % %^^A* checks % %^^A NOTE: The character table, with two %'s, will get written to all files. %% \CharacterTable %% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z %% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z %% Digits \0\1\2\3\4\5\6\7\8\9 %% Exclamation \! Double quote \" Hash (number) \# %% Dollar \$ Percent \% Ampersand \& %% Acute accent \' Left paren \( Right paren \) %% Asterisk \* Plus \+ Comma \, %% Minus \- Point \. Solidus \/ %% Colon \: Semicolon \; Less than \< %% Equals \= Greater than \> Question mark \? %% Commercial at \@ Left bracket \[ Backslash \\ %% Right bracket \] Circumflex \^ Underscore \_ %% Grave accent \` Left brace \{ Vertical bar \| %% Right brace \} Tilde \~} % % \CheckSum{589} % % \begin{abstract} % A delightful collection of defining, expansion, and debugging commands that % make elegant programming in \LaTeX{} fun and easy. % \end{abstract} % % \part{Discussion} % % These macros were written in response to practical programming needs. I % wouldn't write a package without them now. % % \section{Naming conventions} % % The convention is that a capital \emph{E} means the macro expands something % just once. A lowercase \emph{e}, as in \cs\edef, means the macro expands % something all the way to unexpandable tokens. % % The specification \meta{\\csname} means a control sequence with a preceding % backslash; the specification \meta{csname} means a control sequence without a % preceding backslash. \meta{csname} arguments are expanded. Commands which % take \meta{csname} arguments have |Name| in their names. % % When I write \word{package} in this documentation, I mean \LaTeX{} package or % class. % % \section{Defining commands} % % \DescribeMacro\InitCS % \DescribeMacro{\InitCS*} % \cs\InitCS and \cname{InitCS*} take one argument, \meta{\\csname}, and % initialize it to |{}|. The non-|*|-form is |long|; the |*|-form is not. % % \DescribeMacro\InitName % \DescribeMacro{\InitName*} % \cs\InitName and \cname{InitName*} are the same but take an argument % \meta{csname} without a backslash. % % \DescribeMacro\ShortEmpty % \DescribeMacro\LongEmpty % To make it easier to avoid the problem of comparing |long| and % non-|long| macros with \cname{ifx}, compare macros with \cs\ShortEmpty % and \cs\LongEmpty. % % \DescribeMacro\ReserveCS % \DescribeMacro\ReserveName % \cs\ReserveCS\marg{\\csname} reserves \meta{\\csname} for the current % package's use. \cs\ReserveName\marg{csname} does the same for a % \meta{csname}. % % \DescribeMacro\SaveCS % \DescribeMacro\SaveName % \DescribeMacro\RestoreCS % \DescribeMacro\RestoreName % \cs\SaveCS\marg{\\csname} saves the present value of \meta{\\csname} in a % macro (\cname{MDSaved}\meta{csname}). The saved value is restored to % \meta{\\csname} by \cs\RestoreCS\marg{\\csname}. The macros \cs\SaveName % and \cs\RestoreName are analogus but take a \meta{csname}. % % \DescribeMacro\requirecommand % \cs\requirecommand is like \cs\providecommand, but if the control sequence % is already defined, \cs\CheckCommand is called to make sure it's defined % identically, whereas \cs\providecommand assumes that if it's already % defined, the definition is appropriate. Using \cs\requirecommand % \emph{guarantees} that a control sequence will have the given definition; % or an error will occur. % % \DescribeMacro\newtokens % \DescribeMacro\newlet % \DescribeMacro\newboolean % \cs\newtokens\marg{\\csname}, \cs\newlet\marg{\\csname}\marg{\\csname}, and % \cs\newboolean\marg{csname} give an error if their control sequence % argument is already defined. \cs\newtokens creates a token variable. % \cs\newlet does a \cs\let assignment. \cs\newboolean\marg{csname} creates % three new control sequences: two switches, |\csnametrue| and |\csnamefalse|, % and a test, |\ifcsname|. \cs\newtokens is \emph{not} |outer|. Is there % any reason this really matters? % % \DescribeMacro\providetokens % \DescribeMacro\provideboolean % \DescribeMacro\providesavebox % \DescribeMacro\providecounter % \DescribeMacro\providelength % Like the kernel's \cs\providecommand, the commands % \cs\providetokens\marg{\\csname}, \cs\provideboolean\marg{csname}, % \cs\providesavebox\marg{\\csname}, \cs\providecounter\marg{csname}, and % \cs\providelength\marg{\\csname} will create a new object (or objects) % based on the name \meta{\\csname} or \meta{csname} only if they are not % already defined. See the corresponding commands that begin with |\new| % instead of |\provide| for a description of what kind of object is created. % In contrast with \cs\providecommand, however, these commands will write a % record to the log file if their argument was already defined % (\cs\providecommand does nothing at all in this case). % % \DescribeMacro\UndefineCS % \DescribeMacro\UndefineName % \cs\UndefineCS\marg{\\csname} causes \meta{\\csname} to be undefined. % \cs\UndefineName does the same for a \meta{csname}. Use with caution. % \cs\global works before them. % % \DescribeMacro\defcommand % \DescribeMacro{\defcommand*} % \cs\defcommand\marg{\\csname}\oarg{\# of args}\oarg{default for an optarg} % defines \meta{\\csname} in the same manner as \cs\newcommand except no warning or % error is issued if \meta{\\csname} is already defined. % % \cs\defcommand is very similar to the primitive \cs\def, so why would you % want to use it? For one thing, the syntax is the same as all the other % \LaTeX{} defining commands, so it is easier to read, and easier to change % the word \code{defcommand} to one of the other defining commands. Second, % \cs\defcommand{}s that take arguments have simpler syntax when defining % commands are nested. You still have to double the |#| characters in the % definition body, but the argument specification (e.g., |[n]|) is the same % as if not nested. % % There is a performance-syntax tradeoff; I choose to use \cs\defcommand % whenever the command to be defined is taking an argument. When it does not % take an argument, there is no difference between \cs\def and \cs\defcommand % except that \cs\def is faster. % % I see very little reason to every use \cs\renewcommand. It causes an error % when the control sequence is \emph{not} already defined. Conceivably this % is useful during development to catch programming mistakes, but much more % often I find that I don't care whether the control sequence was defined or % not, and therefore the error \cs\renewcommand might raise is inappropriate % and a problem. % % \DescribeMacro\NewName % \DescribeMacro{\NewName*} % \cs\NewName\marg{csname}\marg{template}\marg{body} defines \meta{csname} to % expand to \meta{body} using a \TeX-style argument \meta{template}, % e.g. |#1#2\@nil| or simply |#1#2|. The |*|-form is not |long|. % If \meta{csname} is already defined, an error will be signalled. % % \DescribeMacro\DefName % \DescribeMacro{\DefName*} % \cs\DefName is like \cs\NewName but no error is signalled if \meta{csname} % is already defined. % % \DescribeMacro\Global % If the command \cs\Global immediately precedes \cs\NewName or \cs\DefName, % then the definition will be global. % % \todo{Get something like \cs\Global going for all the new commands, not % just \cs\DefName and \cs\NewName.} % % \DescribeMacro\CheckName % \DescribeMacro{\CheckName*} % \cs\CheckName is like \cs\NewName but instead of defining the control % sequence, it checks whether the control sequence has the given definition. % If so, no action is taken; if not, a warning is given. % % \DescribeMacro\RequireName % \DescribeMacro{\RequireName*} % \cs\RequireName is to \cs\requirecommand as \cs\NewName is to % \cs\newcommand. The syntax is % \cs\RequireName\marg{csname}\marg{template}\marg{body}. % % \DescribeMacro\NewTextFontCommand % \DescribeMacro\NewRobustCommand % \cs\NewTextFontCommand and \cs\NewRobustCommand are just like the kernel's % \cs\DeclareTextFontCommand and \cs\DeclareRobustCommand, but give an error % instead of just a warning if their first argument is already defined. % % \DescribeMacro\Elet % \DescribeMacro\EElet % \cs\Elet expands the second token after it once and then \cs\let{}s the % first token to the second token. \cs\global works before it. \cs\EElet % expands the two tokens that come after it once each, and then \cs\let{}s % the first to the second. \cs\global works before it. % % \DescribeMacro\NewUserInfo % \DescribeMacro{\NewUserInfo*} % \cs\NewUserInfo\marg{variable}\oarg{user-cmd}, where \meta{variable} has % some capital letters, will define the lowercase version of \meta{variable} % to be a user command that redefines \meta{variable} to its argument. An % optional argument \meta{user-cmd} is used for the user command if supplied, % overriding the default of the a lowercased \meta{variable}. % % For example, |\NewUserInfo*\Subtitle| defines a user command % |\subtitle|\marg{text} which does the equivalent of % |\defcommand\Subtitle{|\meta{text}|}|. % % \section{Controlling expansion} % % \DescribeMacro{\EExpand...\string\In} % \DescribeMacro{\EExpand*...\string\In} % \DescribeMacro{\eExpand...\string\In} % \DescribeMacro{\eExpand*...\string\In} % \DescribeMacro{\eExecute} % \DescribeMacro{\eExecute*} % A common construction is to \cs\edef a scratch variable to something and % then execute the scratch variable. The \cs\eExecute macro takes a single % argument, expands it fully, then executes it. % % \cs\eExpand\marg{first tokens}\cs\In\marg{second tokens} expands the % \meta{first tokens} inside \meta{second tokens} wherever |#1| occurs. % \cs\EExpand expands the first token of \meta{first tokens} only once. The % |*|-versions make each argument |short|. These commands can nest. % % For example, % \begin{bothexample} % \def\a {\b} % \def\b {Hello } % \eExpand\a world\In {% % \def\c {This is a good way to avoid lots of noexpands and % expandafters. #1. And I continue.}% % \c % } % % \EExpand\a BLOOB\In {% % \edef#1{\b world}% % This is a good way to avoid lots of noexpands and % expandafters. \a BLOOB. And I continue.% % } % \end{bothexample} % The two commands expand to the same three sentences. % % \section{Gobbling} % % \DescribeMacro{\Gobble} % \DescribeMacro{\GobbleM} % \DescribeMacro{\GobbleO} % \DescribeMacro{\GobbleMM} % \DescribeMacro{\GobbleMO} % \DescribeMacro{\GobbleOM} % It occurs fairly often that you want to gobble things while \cs\makeatother % is in effect, so these command names have no |@|'s. The |M| stands for a % mandatory argument, and the |O| stands for an optional argument. For % example, suppose there is a command |\foo|\oarg{optarg}\marg{marg}. If you % |\let\foo\GobbleOM|, then the arguments to |\foo| will be gobbled % appropriately. % % \cs\Gobble is the same as \cs\GobbleM, in imitation of the internal % \cname{@gobble}. % % \section{Option declaration} % % The follwing two commands may be used in packages before the % \cs\ProcessOptions command is issued. % % \DescribeMacro\DeclareBooleanOptions % \cs\DeclareBooleanOptions\marg{on}\marg{off} declares a new boolean % variable |@|\meta{on}|@| and makes it |true| if the option \option{on} is % given to the package, and |false| if the option \option{off} is given, or % if neither is given. I think it is good programming style not to rely on % the default, always declaring either \meta{on} or \meta{off} with an % \cs\ExecuteOptions statement. % % \DescribeMacro\DeclareBooleanUserOptions % \cs\DeclareBooleanUserOptions\marg{on}\marg{off} is like % \cs\DeclareBooleanOptions, but additionally declares two user commands % \meta{\\on} and \meta{\\off} which are \cs\let to |\@|\meta{on}|@true| and % |\@|\meta{off}|@false|, respectively. Use this command when it is sensible % to change the status of the option after the package has been loaded. % % \section{Debugging} % % I have plans for expanding this section in the next release with some API % commands for controlling the level of debugging output. % % \DescribeMacro\VerboseErrors % \LaTeX{} by default gives very little context for errors. % \cs\VerboseErrors\oarg{number} causes \LaTeX{} to give \meta{number} lines % of context, or the maximum by default. % % \DescribeMacro\Debug % \cs\Debug\marg{number} sets a debugging parameter to \meta{number}. I have % plans to turn this into a bitwise parameter like many C programs, but right % now the behavior is to issue a message with \cs\typeout, call % \cs\VerboseErrors, and use the parameter to assign values to % \cs\tracingoutput, \cs\tracingpages, \cs\tracingmacros, and % \cs\tracingcommands. % % \DescribeMacro\MonsterError % \DescribeMacro\MonsterWarning % \DescribeMacro\MonsterInfo % \DescribeMacro\MonsterDebug % The commands \cs\MonsterError, \cs\MonsterWarning, and \cs\MonsterInfo are % defined here for use by other \monster packages and classes. They are % simply wrappers for the obvious kernel commands. % % \section{Miscellaneous internals} % % \DescribeMacro{\@ifundefined@cs} % \cname{@ifundefined@cs}\marg{\\csname}\marg{true}\marg{false} executes the % \meta{true} clause if \meta{\\csname} is not defined, and the \meta{else} % clause otherwise. % % \DescribeMacro{\addto@macro} % \DescribeMacro{\lg@addto@macro} % \cname{addto@macro}\marg{\\csname}\marg{tokens} adds \meta{tokens} to the % end of \marg{\\csname}. The redefinition of \marg{\\csname} is local. The % kernel provides the global equivalent, \cname{g@addto@macro}. % \cname{lg@addto@macro} is both |long| and global. % % \DescribeMacro{\prependto@macro} % \DescribeMacro{\g@prependto@macro} % \DescribeMacro{\lg@prependto@macro} % \cname{prependto@macro}\marg{\\csname}\marg{tokens} adds \meta{tokens} to % the beginning of \marg{\\csname}. The redefinition of \marg{\\csname} is % local. The global equivalent is \cname{g@prependto@macro}. % \cname{lg@prependto@macro} is both |long| and global. % % \DescribeMacro{\E@car...\string\@nil} % \DescribeMacro{\E@cdr...\string\@nil} % Let $T$ be the sequence of tokens between \cname{E@car} and \cname{@nil}. % The first token of $T$ is expanded once, and \cs{\E@car...\@nil} % expands to the first token of the result. % % \cname{E@cdr...\@nil} is similar, but expands to the entire result % \emph{except} its first token. % % For example, after % \begin{codeexample} % \def\a {Hello} % \def\b { world} % \end{codeexample} % |\E@car \a there\b.\@nil| would expand first of all to % |H|\@. And |\E@cdr \a there\b.\@nil| would expand first of all to % |ellothere\b.|, and then eventually expand fully to |ellothere world.|. % % The example is more complicated than you would normally use. Usually you % want to |car| and |cdr| a sequence of tokens contained in macro |\foo|, and % this is easy enough with |\E@car\foo\@nil|. To chop off the first token of % |\foo|, |\edef\foo {\E@cdr\foo\@nil}|. (If you're wondering, the space % after |\foo| is irrelevant.) % % \StopEventually{} % % \part{Implementation} % % \section{Version control} % % \begin{macro}{\fileinfo} % \begin{macro}{\fileversion} % \begin{macro}{\filedate} % \begin{macro}{\docdate} % \begin{macro}{\PPOptArg} % These definitions must be the first ones in the file. % \begin{macrocode} \def\fileinfo{more defining commands (Frankenstein's brain)} \def\fileversion{v1.02 (beta)} \def\filedate{1996/03/25} \def\docdate{1996/03/25} \edef\PPOptArg {% \filedate\space \fileversion\space \fileinfo } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % Stop right here if we're just loading the file's information, and don't want % to load this code for typesetting its documentation (only makes sense for % certain packages). The |JuStLaAdInFoRmAtIoN| flag will be set by the % documentation driver; the |DoXNeeDME| flag will be set in the % \ext{dtx} file, and will appear above if it's set. % \begin{macrocode} \makeatletter \@ifundefined{JuStLoAdInFoRmAtIoN} {% }{% ELSE \@ifundefined{DoXNeeDME} {% }{% ELSE \UndefineCS\JuStLoAdInFoRmAtIoN \usepackage{moredefs}% } \makeatother \endinput } % \end{macrocode} % % Now we check for \LaTeX2e and declare the package. % \begin{macrocode} \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{moredefs}[\PPOptArg] % \end{macrocode} % % ^^A NOTE: We have to compensate for the above backslashes, which are not % ^^A actually in the doctex file I work on. %% % \AddToCheckSum{26} % % \makeatletter % \@ifundefined{DoXNeeDME} {} {\AddToCheckSum{2}} % \makeatother % % % \section{Getting started} % % We will begin to use commands as we define them. % % \begin{macro}{\@ifundefined@cs} % We want this macro to make other macros easier to read. % \begin{macrocode} \newcommand*\@ifundefined@cs [1] {% \edef\reserved@a{% \expandafter\@gobble\string #1% }% \@ifundefined\reserved@a \@firstoftwo \@secondoftwo } % \end{macrocode} % \end{macro} % % \section{Defining commands} % % \begin{macro}{\sc@star@or@long} % \begin{macro}{\sc@star@nothing} % The macros \cname{sc@star@or@long} and \cname{sc@star@nothing} are parallel % to the kernel's \cname{@star@or@long} and \cname{l@ngrel@x}, which control % whether definitions are |long| or not. \cname{sc@star@or@long} causes the % value of \cname{sc@star@nothing} to be either |*| or empty, depending on % whether it finds a |*| when it is called. It also sets the kernel's % \cname{l@ngrel@x} to nothing or \cs\long, respectively. (We need both % flags at least once.) % \begin{macrocode} \newcommand*\sc@star@nothing{} \newcommand*\sc@star@or@long [1] {% args: defining-command \@ifstar {% \let\l@ngrel@x\relax \def\sc@star@nothing {*}#1% }{% ELSE \let\l@ngrel@x\long \def\sc@star@nothing {}% #1% }% } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\requirecommand} % \begin{macro}{\requirecommand*} % \begin{macro}{\require@command} % A typical application of the star mechanisms is \cs\requirecommand. % \begin{macrocode} \newcommand\requirecommand {% \sc@star@or@long\require@command } \newcommand\require@command [1] {% args: \csname \@ifundefined@cs{#1} {% \expandafter\newcommand\sc@star@nothing }{% ELSE \expandafter\CheckCommand\sc@star@nothing }% {#1}% } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\InitCS} % \begin{macro}{\InitCS*} % \begin{macro}{\InitName} % \begin{macro}{\InitName*} % \begin{macro}{\ReserveCS} % \begin{macro}{\ReserveName} % \begin{macro}{\ShortEmpty} % \begin{macro}{\LongEmpty} % \mbox{} % \begin{macrocode} \newcommand\InitCS {% \@star@or@long\Init@CS } \newcommand\Init@CS [1] {% args: \csname \l@ngrel@x\def#1{}% } \newcommand\InitName {% \sc@star@or@long\Init@Name } \newcommand\Init@Name [1] {% args: csname \expandafter\DefName\sc@star@nothing{#1}{}{}% } \newcommand\ReserveCS [1] {% args: \csname \newcommand{#1} {}% } \newcommand\ReserveName [1] {% args: csname \NewName{#1}{} {}% } \InitCS*\ShortEmpty \InitCS\LongEmpty % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\sc@t@a} % \begin{macro}{\sc@t@b} % \begin{macro}{\sc@t@c} % \begin{macro}{\sc@t@d} % \begin{macro}{\sc@t@e} % \begin{macro}{\sc@t@f} % \begin{macro}{\sc@t@g} % Scratch variables. ^^A FIX % \begin{macrocode} \ReserveCS\sc@t@a \ReserveCS\sc@t@b \ReserveCS\sc@t@c \ReserveCS\sc@t@d \ReserveCS\sc@t@e \ReserveCS\sc@t@f \ReserveCS\sc@t@g % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\newtokens} % \begin{macro}{\newlet} % Because \cs\newtoks is \cs\outer, we have to fool \cs\def into allowing it % to be in its argument by using \cname{@nameuse}. % \begin{macrocode} \newcommand\newtokens [1] {% args: \csname \@ifdefinable #1 {% \@nameuse{newtoks}#1% }% } \newcommand*\newlet [2] {% args: \csname-a \csname-b \@ifdefinable #1 {% \let#1#2% }% } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\providetokens} % \begin{macro}{\providelength} % \begin{macro}{\providesavebox} % \begin{macro}{\providecounter} % \begin{macro}{\newboolean} % \begin{macro}{\provideboolean} % The \cs\newboolean command is the same as the one in the \package{ifthen} % package; so that packge won't clash with this one. Isn't % \cs\requirecommand nice? % \begin{macrocode} \newcommand*\providetokens [1] {% args: \csname \@ifundefined@cs{#1} {% \@nameuse{newtokens}#1% }{% ELSE \MonsterInfo{moredefs}{\protect\providetokens\space is not reallocating token variable \protect#1.\MessageBreak The existing contents are [\the#1]}% }% } \newcommand*\providelength [1] {% args: \csname \@ifundefined@cs{#1} {% \newlength{#1}% }{% ELSE \MonsterInfo{moredefs}{\protect\providelength\space is not reallocating \protect#1.\MessageBreak The existing value is [\the#1]}% }% } \newcommand*\providesavebox [1] {% args: \csname \@ifundefined@cs{#1} {% \newsavebox{#1}% }{% ELSE \MonsterInfo{moredefs}{\protect\providesavebox\space is not reallocating box \protect#1.}% }% } \newcommand*\providecounter [1] {% args: string \@ifundefined{c@#1} {% \newcounter{#1}% }{% ELSE \MonsterInfo{moredefs}{\protect\providecounter\space is not reallocating counter #1.\MessageBreak The existing value is [\expandafter\number\csname c@#1\endcsname]}% }% } \requirecommand*\newboolean [1] {% args: string \csname newif\expandafter\endcsname\csname if#1\endcsname } \newcommand*\provideboolean [1] {% args: string \@ifundefined {if#1} {% \newboolean{#1}% }{% ELSE \MonsterInfo{moredefs}{\protect\provideboolean\space is not reallocating \protect#1.\MessageBreak The value is [\@nameuse{if#1}TRUE\else FALSE\fi]}% }% } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\sc@toks@a} % \begin{macro}{\addto@macro} % \begin{macro}{\lg@addto@macro} % \begin{macro}{\prependto@macro} % \begin{macro}{\g@prependto@macro} % \begin{macro}{\lg@prependto@macro} % There are still missing a couple of the permutations, but I won't add them % until I need them. You can add them yourself in the configuration file % \file{moredefs.cfg}. % \begin{macrocode} \newtokens\sc@toks@a \newcommand\addto@macro [2] {% \sc@toks@a=\expandafter{#1#2}% \edef#1{% \the\sc@toks@a }% } \newcommand\lg@addto@macro [2] {% \sc@toks@a=\expandafter{#1#2}% \long\xdef#1{% \the\sc@toks@a }% } \newcommand\prependto@macro [2] {% \sc@toks@a=\expandafter{#1#2}% \edef#1{% \the\sc@toks@a }% } \newcommand\g@prependto@macro [2] {% \sc@toks@a=\expandafter{#1#2}% \global\edef#1{% \the\sc@toks@a }% } \newcommand\lg@prependto@macro [2] {% \sc@toks@a=\expandafter{#1#2}% \long\xdef#1{% \the\sc@toks@a }% } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\UndefineCS} % \begin{macro}{\UndefineName} % \cs\global works before them. % \begin{macrocode} \newcommand\UndefineCS [1] {% args: \csname \let#1\@undefined } \newcommand\UndefineName [1] {% args: csname \expandafter\let\csname#1\endcsname\@undefined } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\defcommand} % \begin{macro}{\defcommand*} % \begin{macro}{\def@command} % See the user documentation for a discussion of when to use this insteae of \cs\def. % \begin{macrocode} \newcommand\defcommand {% \@star@or@long\def@command } \newcommand\def@command {% \let\@ifdefinable\@rc@ifdefinable \new@command } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\DefName} % \begin{macro}{\DefName*} % \begin{macro}{\def@name} % \begin{macro}{\NewName} % \begin{macro}{\NewName*} % \begin{macro}{\new@name} % \begin{macro}{\Global} % \begin{macro}{\sc@global} % \cs\Global works before \cs\DefName and \cs\NewName only! % \begin{macrocode} \newcommand\DefName {% \@star@or@long\def@name } \newcommand\def@name [3] {% args: arglist csname body \sc@global\l@ngrel@x\@namedef{#1}#2{#3}% } \newcommand\NewName {% \@star@or@long\new@name } \newcommand\new@name [3] {% args: arglist csname body \@ifundefined{#1} {% \sc@global\l@ngrel@x\@namedef{#1}#2{#3}% }{% ELSE \defcommand\reserved@a {% #1% }% \@notdefinable }% } \newcommand\sc@global {% \relax } \newcommand\Global {% \def\sc@global {% \global\let\sc@global\relax\global }% } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\CheckName} % \begin{macro}{\CheckName*} % \begin{macro}{\check@name} % \begin{macro}{\RequireName} % \begin{macro}{\RequireName*} % \begin{macro}{\require@name} % \mbox{} % \begin{macrocode} \newcommand\CheckName {% \@star@or@long\check@name } \newcommand\check@name [3] {% args: arglist csname body \expandafter\DefName\sc@star@nothing{reserved@a}{#2}{#3}% \expandafter\@check@eq\csname #1\endcsname\reserved@a } \newcommand\RequireName {% \sc@star@or@long\require@name } \newcommand\require@name [3] {% args: arglist csname body \@ifundefined{#1} {% \expandafter\DefName\sc@star@nothing{#1}{#2}{#3}% }{% ELSE \expandafter \expandafter \expandafter \CheckName \expandafter \sc@star@nothing \csname #1\endcsname {#2}{#3}% }% } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\NewTextFontCommand} % \begin{macro}{\NewRobustCommand} % \begin{macro}{\new@robustcommand} % \mbox{} % \begin{macrocode} \newcommand\NewTextFontCommand [2] {% args: \csname font-command \ReserveCS{#1}% \DeclareTextFontCommand{#1}{#2}% } \newcommand\NewRobustCommand {% \@star@or@long\new@robustcommand } \newcommand\new@robustcommand [1] {% \@ifdefinable #1 {% \edef\reserved@a {\string#1}% \def\reserved@b {#1}% \edef\reserved@b {% \expandafter\strip@prefix\meaning\reserved@b }% \edef#1{% \ifx\reserved@a\reserved@b \noexpand\x@protect \noexpand#1% \fi \noexpand\protect \expandafter\noexpand\csname \expandafter\@gobble\string#1 \endcsname }% \let\@ifdefinable\@rc@ifdefinable \expandafter\new@command\csname \expandafter\@gobble\string#1 \endcsname }% } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\Elet} % \mbox{} % \begin{macrocode} \newcommand\Elet {% \expandafter\let\expandafter } % \end{macrocode} % \end{macro} % % \begin{macro}{\EElet} % \mbox{} % \begin{macrocode} \newcommand*\EElet {% \expandafter\expandafter\expandafter\let\expandafter\expandafter } % \end{macrocode} % \end{macro} % % \begin{macro}{\NewUserInfo} % \begin{macro}{\NewUserInfo*} % \begin{macro}{\new@userinfo} % Using \cs\lowercase in this macro is tricky, since it gets expanded only in % \TeX's stomach. % \begin{macrocode} \newcommand\NewUserInfo {% \sc@star@or@long\new@userinfo } \newcommand*\new@userinfo [2][] {% \expandafter\InitCS\sc@star@nothing{#2}% \def\sc@t@b {#1}% \ifx\sc@t@b\ShortEmpty \edef\sc@t@a {% \edef\noexpand\sc@t@b{% \E@cdr\string#2\@nil }% }% \lowercase\expandafter{\sc@t@a}% \else \edef\sc@t@b {\E@cdr\string#1\@nil}% \fi \edef\sc@t@a {% \noexpand\NewName\sc@star@nothing{\sc@t@b}{####1} {\noexpand\renewcommand\sc@star@nothing\noexpand#2{####1}} }% \sc@t@a } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}\SaveCS % \begin{macro}\RestoreCS % \begin{macro}\SaveName % \begin{macro}\RestoreName % \mbox{} % \begin{macrocode} \newcommand\SaveCS [1] {% args: \csname \expandafter\newlet\csname MDSaved\E@cdr\string#1\@nil\endcsname#1% } \newcommand\RestoreCS [1] {% args: \csname \Elet#1\csname MDSaved\E@cdr\string#1\@nil\endcsname \UndefineName{MDSaved\E@cdr\string#1\@nil}% } \newcommand\SaveName [1] {% args: csname \ReserveName{#1}% \EElet\csname MDSaved#1\endcsname\sc@t@a\csname #1\endcsname } \newcommand\RestoreName [1] {% args: csname \EElet\csname #1\endcsname\csname MDSaved#1\endcsname \UndefineName{MDSaved#1}% } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \section{Controlling expansion} % % \begin{macro}{\EExpand...\In} % \begin{macro}{\EExpand*...\In} % \begin{macro}{\sc@EExpand} % \begin{macro}{\eExpand...\In} % \begin{macro}{\eExpand*...\In} % \begin{macro}{\sc@eExpand} % \begin{macro}{\eExecute} % \begin{macro}{\eExecute*} % \begin{macro}{\sc@eExecute} % Uses \cname{sc@t@a}, \cname{sc@t@b}, \cname{sc@t@c}. % \begin{macrocode} \newcommand\eExpand {% \sc@star@or@long\sc@eExpand } \NewName{sc@eExpand} {#1\In#2} {% args: object body \l@ngrel@x\edef\sc@t@a{#1}% \expandafter\defcommand\sc@star@nothing\sc@t@b [1] {#2}% \expandafter \sc@t@b \expandafter {\sc@t@a}% } \newcommand\EExpand {% \sc@star@or@long\sc@EExpand } % \end{macrocode} % When this is |short|, both the two args are |short|. \cname{sc@star@nothing} % gets reset by the first \cs\defcommand, so we save it in \cname{sc@t@c}. % \begin{macrocode} \NewName{sc@EExpand}{#1\In#2} {% args: object body \let\sc@t@c\sc@star@nothing \expandafter \expandafter \expandafter \defcommand \expandafter \sc@t@c \expandafter \sc@t@a \expandafter {#1}% \expandafter\defcommand\sc@t@c\sc@t@b [1] {#2}% \expandafter\sc@t@b \expandafter{\sc@t@a}% } \newcommand\eExecute {% \sc@star@or@long\sc@eExecute } \newcommand\sc@eExecute [1] {% args: body \l@ngrel@x\edef\sc@t@a {#1}% \sc@t@a } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\E@car} % \begin{macro}{\E@cdr} % \mbox{} % \begin{macrocode} \NewName{E@cdr} {#1\@nil} {% \expandafter\@cdr #1\@nil } \NewName{E@car} {#1\@nil} {% \expandafter\@car #1\@nil } % \end{macrocode} % \end{macro} % \end{macro} % % \section{Gobbling} % % \begin{macro}{\Gobble} % \begin{macro}{\GobbleM} % \begin{macro}{\GobbleO} % \begin{macro}{\GobbleMM} % \begin{macro}{\GobbleMO} % \begin{macro}{\GobbleOM} % \begin{macro}{\sc@gobbleOM} % \textsf{M} for mandatory arg, i.e., one token. \textsf{O} for optional arg, % i.e., a square-brace pair. % \begin{macrocode} \newlet\Gobble\@gobble \newlet\GobbleM\@gobble \NewName{GobbleO} {[#1]} {} \newlet\GobbleMM\@gobbletwo \newcommand\GobbleOM {% \@ifnextchar [ \sc@gobbleOM \Gobble } \NewName{sc@gobbleOM} {[#1]#2} {} \newcommand\GobbleMO [1] {% \@ifnextchar [ \GobbleO {}% } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \section{Option declaration} % % \begin{macro}{\DeclareBooleanOptions} % \begin{macro}{\DeclareBooleanUserOptions} % \mbox{} % \begin{macrocode} \newcommand\DeclareBooleanOptions [2] {% args: on off \newboolean{@#1@} \DeclareOption{#1} {% \@nameuse{@#1@true} } \DeclareOption{#2} {% \@nameuse{@#1@false} } } \newcommand\DeclareBooleanUserOptions [2] {% args: on off \DeclareBooleanOptions{#1}{#2} \ReserveName{#1} \ReserveName{#2} \EElet \csname#1\endcsname\csname @#1@true\endcsname \EElet \csname#2\endcsname\csname @#1@false\endcsname } % \end{macrocode} % \end{macro} % \end{macro} % % \section{Debugging} % % \begin{macro}{\VerboseErrors} % We do not use \cs\setcounter but rather set these counters locally. % \begin{macrocode} \newcommand*\VerboseErrors [1][\@M] {% args: [number] \c@errorcontextlines #1% \showboxbreadth #1% \showboxdepth #1% } % \end{macrocode} % \end{macro} % % \begin{macro}{\Debug} % Set \cs\debug to 0, 1, or~2. ^^A remember \cs\showlists % \begin{macrocode} \newcommand*\Debug[1] {% args: debug-level \ifnum #1 > 0% \let\sc@t@a\@M \else \let\sc@t@a\m@ne \fi \VerboseErrors[\sc@t@a]% \tracingoutput#1 % \tracingpages#1 % \tracingmacros#1 % \tracingcommands#1 % \typeout{++++ Debugging [#1] \on@line}% } % \end{macrocode} % \end{macro} % % \begin{macro}{\MonsterError} % \begin{macro}{\MonsterWarning} % \begin{macro}{\MonsterInfo} % \mbox{} % \begin{macrocode} \newcommand\MonsterWarning [2] {% args: package warning \GenericWarning % continuation message {(#1)\@spaces\@spaces\@spaces\@spaces\@spaces} {Frankenstein (#1) WARNING: #2}% } \newcommand\MonsterError [3] {% args: package error-message help-text \GenericError % args: continuation message where-help what-help {(#1)\@spaces\@spaces\@spaces\@spaces\@spaces} {Frankenstein (#1) error: #2} {See the documenation for the #1 package for more information.} {#3}% } \newcommand\MonsterInfo [2] {% args: package info \GenericInfo % continuation message {(#1)\@spaces\@spaces\@spaces\@spaces\@spaces} {Frankenstein (#1) says: #2}% } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % \Finale