%^^A* legal notices % \iffalse % % This program is part of the Frankenstein bundle for LaTeX. % % Copyright 1995-2001 Matt Swift . % % This file contains both the code and documentation for the % moredefs LaTeX package. It will work ONLY if it is placed in a % proper directory. Files called README, INSTALL, moredefs.tex % and moredefs.ins should have also been distributed to you % with this file. See them for more information on how to typeset % the documentation with LaTeX and how to generate a version of this % file that will work faster than this one. % % This program is free software; you may redistribute it and/or % modify it under the conditions of the LaTeX Project Public % License, either version 1.2 or (at your option) any later version. % The latest version of this license is in % http://www.latex-project.org/lppl.txt, and version 1.2 or later is % part of all distributions of LaTeX version 1999/12/01 or later. % % 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 % LaTeX Project Public License for more details. % % \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{793} % % \begin{abstract} % A delightful collection of defining, expansion, and debugging commands that % make elegant programming in \LaTeX{} fun and easy. % \end{abstract} % \tableofcontents % % \part{Discussion} % % These macros were written in response to practical programming needs. Most % of the packages I have written, whether distributed or not, depend on this % package. Using these constructs has saved me a lot of time and made my code % much more readable---that is, maintainable and improvable. For examples of % these macros in useful applications, see the packages in the \Frankenstein % bundle. % % \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{Conditionals} % % \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{\IfElement...\string\In} % To check whether a token \meta{thingma} is \cs\ifx-equal to any token in a % list of tokens stored in a macro \meta{list}, use % \cs\IfElement\meta{thingma}\cs\In\meta{list}\marg{true}\marg{false}. The % top-level expansion of \meta{list} must be a list of tokens to compare with % \meta{thingma} with \cs\ifx. If the \meta{thingma} is in the \meta{list}, % the \meta{true} clause is executed; otherwise, the \meta{false} clause is % executed. % % \section{Defining commands} % \subsection{\protect\code{*} and no-\protect\code{*} forms} % The naming convention of most defining commands in the \LaTeX{} kernel and % in \package{moredefs} is that the no-|*| form of the command is |long| and % the |*|-form is not |long|. % % \subsection{User commands} % % \DescribeMacro\InitCS % \DescribeMacro{\InitCS*} % \cs\InitCS and \cname{InitCS*} take one argument, \meta{\\csname}, and % initialize it to |{}|. % % \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{\ReserveCS*} % \cs\ReserveCS\marg{\\csname} reserves \meta{\\csname} for the current % package's use. The variable is also initialized with the \cs\InitCS or % \cs\InitCS* as appropriate. % % \DescribeMacro\ReserveName % \DescribeMacro{\ReserveName*} % \cs\ReserveName and \cname{ReserveName*} are the same but take an argument % \meta{csname} without a backslash. % % \DescribeMacro\SaveCS % \DescribeMacro\RestoreCS % \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}. % % \DescribeMacro\SaveName % \DescribeMacro\RestoreName % \cs\SaveName and \cname{RestoreName} are the same but take an argument % \meta{csname} without a backslash. % % \DescribeMacro\requirecommand % \DescribeMacro{\requirecommand*} % \cs\requirecommand takes arguments like \cs\newcommand and behaves like % \cs\providecommand (defined in the kernel) with the following difference: % if the control sequence is already defined, \cs\requirecommand calls % \cs\CheckCommand to make sure that the new and existing definitions are % identical, whereas \cs\providecommand assumes that if the control sequence % is already defined, the existing definition is appropriate. % \cs\requirecommand, like \cs\defcommand, \emph{guarantees} that a control % sequence will have the given definition, but \cs\requirecommand also warns % you if there was a previous and different existing definition. % % \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? % % \begin{warning} % Limitation: You can't use \cs\newlet to \cs\let a command sequence % to a character with a catcode not equal to 10 (space), 11 (letter), 12 % (other), or 13 (active). For example, you can't say |\newlet\foo#|. % Also, you cannot use |=| with \cs\newlet like you can with \cs\let. % \end{warning} % % \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 ever 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|. % 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, \cs\DefName, or % \cs\ToggleBoolean, 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 they signal 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\oarg{user-cmd}\marg{variable}, 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. The % argument \meta{user-cmd}, if supplied, is used for the user command, % overriding the default of the lowercased \meta{variable}. % % For example, |\NewUserInfo*\Subtitle| defines a user command % |\subtitle|\marg{text} which does the equivalent of % |\defcommand\Subtitle{|\meta{text}|}|. % % \cs\NewUserInfo uses \cs\ReserveCS to initialize \meta{variable}; % \cs\NewUserInfo** uses \cs\ReserveCS*. % % These have |@| in their names because they are modelled after kernel % commands. \todo{Sort out naming comventions and write them down.} % % \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. % \caveat{These commands won't work with a \meta{\\csname} that takes % arguments.} % \begin{todo} % Probably it would not be too hard to handle that case. Here is how you would % do it by hand for one example: % \begin{codeexample} % % something like: \def\@chapter[#1]#2{...} % % \typeout{\meaning\@chapter} % % \renewcommand\addto@macro [2] {% % \sc@toks@a=\expandafter{#1[##1]{##2}#2}% % \edef#1[##1]##2{% % \the\sc@toks@a % }% % } % % \def\doodie#1{bobo \textsc{#1}} % \tracingonline1 % % \Debug2 % \addto@macro\@chapter {\doodie blorful} % \Debug0 % % \typeout{\meaning\@chapter} % \end{codeexample} % \end{todo} % % \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. % % \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. % These commands can nest. % % For example, % \begin{bothexample} % \def\a {\b} % \def\b {Hello } % \def\x {d} % \eExpand\a worl\x\In {% % \def\c {This is a good way to avoid lots of noexpands and % expandafters. #1. And I continue.}% % \def\x {boogaloo}% \x is already expanded in the def of \c % \c % } % % \EExpand\a BLOOB\x\In {% % \def\x{avoid } % \edef#1{\b world}% BLOOB\x is syntactic sugar % This is a good way to \x lots of noexpands and % expandafters. \a BLOOB\x. And I continue.% % } % \end{bothexample} % The two commands expand to the same three sentences. Here is one more % example, showing (again) how \cs\EExpand expands only the first token of its % argument only once:: % \begin{bothexample} % \def\x{XXX} % \def\a{AAA\x} % \def\b{BBB} % \EExpand\a\b\In{% % \def\x{xxx} % \def\a{aaa} % \def\b{YYY} % #1 % } % \end{bothexample} % % \begingroup % \catcode`\ =11\relax % \DescribeMacro{\E@car...\string\@nil } % \DescribeMacro{\E@cdr...\string\@nil } % \endgroup % 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.) % % \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{\meta{on}} is given to the package, and |false| if the option % \option{\meta{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{Toggle a boolean} % % \DescribeMacro\ToggleBoolean % \cs\ToggleBoolean\marg{boolean} changes the state of \meta{boolean} from % |false| to |true| or vice versa. The argument \meta{boolean} should not % include an initial |if| or final |true| or |false|. The redefinition is % local unless \cs\Global precedes \cs\ToggleBoolean. % % \section{Debugging} % % \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\GVerboseErrors % Like \cs\VerboseErrors but effective globally. % % \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\GDebug % \cs\GDebug\marg{number} is as \cs\Debug but its assignments are % \cs\global. % % \DescribeMacro\DTypeout % \DescribeMacro\DDTypeout % \DescribeMacro\DDDTypeout % \cs\DTypeout expands to \cs\typeout when \cs\Debug is 1 or greater, and % \cs\GobbleM otherwise. \cs\DDTypeout is \cs\GobbleM unless \cs\Debug is 2 % or greater; \cs\DDDTypeout is \cs\GobbleM unless \cs\Debug is 3 or greater. % % \DescribeMacro\DGobbleM % Like \cs\GobbleM but when \cs\Debug is 1 or greater, tells you what it's % gobbling with a \cs\typeout. % % \DescribeMacro\FrankenError % \DescribeMacro\FrankenWarning % \DescribeMacro\FrankenInfo % The commands \cs\FrankenError, \cs\FrankenWarning, and \cs\FrankenInfo are % defined here for use by other \Frankenstein packages and classes. They are % simply wrappers for the obvious kernel commands (i.e., substitute % ``Generic'' for ``Franken''). % % \StopEventually{} % % \part{Implementation} % % \section{Version control} % % \begin{macro}{\fileinfo} % \begin{macro}{\DoXUsepackagE} % \begin{macro}{\HaveECitationS} % \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\DoXPackageS {} \def\fileversion{v1.8} \def\filedate{2001/08/31} \def\docdate{2001/08/31} \edef\PPOptArg {% \filedate\space \fileversion\space \fileinfo } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % If we're loading this file from a \cs\ProcessDTXFile command (see the % \package{compsci} package), then \cs\JusTLoaDInformatioN will be defined; % othewise we assume it is not (that's why the FunkY NamE). % % If we're loading from \cs\ProcessDTXFile, we want to load the packages listed % in \cs\DoXPackageS (needed to typeset the documentation for this file) and % then bail out. Otherwise, we're using this file in a normal way as a % package, so do nothing. \cs\DoXPackageS, if there are any, are declared in % the \ext{dtx} file, and, if you're reading the typeset documentation of this % package, would appear just above. (It's OK to call \cs\usepackage with an % empty argument or \cs\relax, by the way.) % \begin{macrocode} \makeatletter% A special comment to help create bst files. Don't change! \@ifundefined{JusTLoaDInformatioN} {% }{% ELSE (we know the compsci package is already loaded, too) \UndefineCS\JusTLoaDInformatioN \SaveDoXVarS \eExpand\csname DoXPackageS\endcsname\In {%use \csname in case it's undefined \usepackage{#1}% }% \RestoreDoXVarS \makeatother \endinput }% A special comment to help create bst files. Don't change! % \end{macrocode} % % Now we check for \LaTeX2e and declare the LaTeX package. % \begin{macrocode} \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{moredefs}[\PPOptArg] % \end{macrocode}^^A special comment to help create bst files. Don't change! % % ^^A NOTE: We have to compensate for the above backslashes, which are not % ^^A actually in the .dtx file the author works on, by adding to the % ^^A CheckSum. %% % \AddToCheckSum{17}^^A `dtx-update-checksum' automatically handles this. % \AddToCheckSum{7}^^A The half a macrocode env. at the top is missed, however... % \AddToCheckSum{10}^^A ... and so are the 5 \defs from the .dtx file % ^^A that precede it. % \IfCitations {% % \AddToCheckSum{2}^^A When \initelyHavECitationS is defined in % } ^^A the .dtx file, we need 2 more in the CheckSum. % % % \section{Conditionals} % We start with the conditionals section because we want to use % \cname{@ifundefined@cs} in this package to make some of the subsequent % definitions easier to read. % % \begin{macro}{\@ifundefined@cs} % \mbox{} % \begin{macrocode} \newcommand*\@ifundefined@cs [1] {% \edef\reserved@a{% \expandafter\@gobble\string #1% }% \@ifundefined\reserved@a \@firstoftwo \@secondoftwo } % \end{macrocode} % \end{macro} % % \begin{macro}{\IfElement...\In} % \mbox{} % \begin{macrocode} \newcommand\IfElement{} \def\IfElement #1\In#2{% \@tempswafalse \expandafter \@tfor \expandafter \sc@t@a \expandafter :% \expandafter =#2\do {% \ifx #1\sc@t@a % \DTypeout{[\meaning #1] matches element [\meaning\sc@t@a] % in [\string#2].}% \@tempswatrue \@break@tfor \else % \DTypeout{[\meaning #1] matches NO elements in [\string #2].}% \fi }% \if@tempswa \expandafter\@firstoftwo \else \expandafter\@secondoftwo \fi } % \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}{\md@check@star} % Looks for a star with \cname{@ifstar} and sets \cname{sc@star@nothing} to % |*| if there is a star and \cs\ShortEmpty if not. % \begin{macrocode} \newcommand\md@check@star {% \@ifstar {% \def\sc@star@nothing {*}% }{% ELSE \let\sc@star@nothing \ShortEmpty }% } % \end{macrocode} % \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}{\ReserveCS*} % \begin{macro}{\ReserveName} % \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 {% \sc@star@or@long\Reserve@CS } \newcommand\Reserve@CS [1] {% args: \csname \expandafter\newcommand\sc@star@nothing{#1} {}% } \newcommand\ReserveName {% \sc@star@or@long\Reserve@Name } \newcommand\Reserve@Name [1] {% args: csname \expandafter\NewName\sc@star@nothing{#1}{} {}% } \InitCS*\ShortEmpty \InitCS\LongEmpty % \end{macrocode} % \end{macro} % \end{macro} % \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 package 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 \FrankenInfo{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 \FrankenInfo{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 \FrankenInfo{moredefs}{\protect\providesavebox\space is not reallocating box \protect#1.}% }% } \newcommand*\providecounter [1] {% args: string \@ifundefined{c@#1} {% \newcounter{#1}% }{% ELSE \FrankenInfo{moredefs}{\protect\providecounter\space is not reallocating counter #1.\MessageBreak The existing value is [\expandafter\number\csname c@#1\endcsname]}% }% } % \end{macrocode} % The following definition follows the one in the \package{ifthen} package: % \begin{macrocode} % \ProvidesPackage{ifthen} % [1999/01/07 v1.1a Standard LaTeX ifthen package (DPC)] \requirecommand*\newboolean [1] {% args: string \expandafter \@ifdefinable\csname if#1\endcsname {% \expandafter\newif\csname if#1\endcsname }% } % old def of \cs\newboolean I had before 15 Feb 00: % \csname newif\expandafter\endcsname\csname if#1\endcsname % \end{macrocode} % Notice that \cs\defcommand is not defined yet. % % If the \package{ifthen} package is loaded \emph{either} before or % after this package, the \cs\provideboolean command will be the one defined in % \package{ifthen}. Otherwise, it will be the one defined here. % % There are two minor differences between this definition and the one in the % \package{ifthen} package: (1) my command will barf on undefined but % ``undefinable'' commands, e.g., ones that begin with \cs\end, which \LaTeX{} % reserves; (2) my command writes an informational message to the log file when % the boolean variable is already defined. I'm not sure how useful the % informational message is, but the first difference should I think also be in % the \package{ifthen} package, so \todo{I'm putting it on my list to write the % \LaTeX{} team requesting this change.} % \begin{macrocode} \@ifpackageloaded{ifthen} {% }{% ELSE \requirecommand*\provideboolean [1] {% args: string \@ifundefined {if#1} {% \newboolean{#1}% }{% ELSE \FrankenInfo{moredefs}{\protect\provideboolean\space is not reallocating \protect#1.\MessageBreak The value is [\@nameuse{if#1}TRUE\else FALSE\fi]}% }% }% } % \end{macrocode} % The following definition is what's in the \package{ifthen} package, for % reference. % \begin{macrocode} % \requirecommand*\provideboolean [1] {% args: string % \@ifundefined{if#1}{% % \expandafter % \newif\csname if#1\endcsname}\relax % } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\sc@toks@a} % \begin{macro}{\sc@toks@b} % \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 \newtokens\sc@toks@b \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={#2}% \sc@toks@b=\expandafter{#1}% \edef#1{% \the\sc@toks@a\the\sc@toks@b }% } \newcommand\g@prependto@macro [2] {% \sc@toks@a={#2}% \sc@toks@b=\expandafter{#1}% \xdef#1{% \the\sc@toks@a\the\sc@toks@b }% } \newcommand\lg@prependto@macro [2] {% \sc@toks@a={#2}% \sc@toks@b=\expandafter{#1}% \long\xdef#1{% \the\sc@toks@a\the\sc@toks@b }% } % \end{macrocode} % \end{macro} % \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, \cs\NewName, and \cs\ToggleBoolean % 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} % \begin{macro}{\new@@robustcommand} % \mbox{} % \begin{macrocode} \newcommand\NewTextFontCommand [2] {% args: \csname font-command \NewRobustCommand#1[1]{% \ifmmode \nfss@text{#2##1}% \else \leavevmode {\text@command{##1}% #2\check@icl ##1\check@icr \expandafter}% \fi }% } \newcommand\NewRobustCommand {% \@star@or@long\new@robustcommand } % \end{macrocode} % We need a second level here because otherwise the \cs\fi that closes % \cname{@ifdefinable} will become the definition of the closing % \cname{new@command}. We could use a chain of \cs\expandafter{}s but that % would be confusing. % \begin{macrocode} \newcommand\new@robustcommand [1] {% \let\sc@t@a\relax \@ifdefinable #1 {% \def\sc@t@a {% \new@@robustcommand #1% }% }% \sc@t@a } \newcommand\new@@robustcommand [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} % \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][] {% args: [\csname] \csname \expandafter\ReserveCS\sc@star@nothing{#2}% \def\sc@t@b {#1}% % \end{macrocode} % If we were not given the optional user-cmd, define scratch |b| to be a % lowercase version of the variable, without the backslash. Otherwise use the % user-cmd given, without the backslash. % \begin{macrocode} \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 % \end{macrocode} % Now define the user-cmd to be a redefinition of the variable. % \begin{macrocode} \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{MDSaved#1}% \EElet\csname MDSaved#1\endcsname \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@gobbleO} % \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 \newcommand\GobbleO {% \@ifnextchar [ \sc@gobbleO \relax } \newlet\GobbleMM\@gobbletwo \newcommand\GobbleOM {% \@ifnextchar [ \sc@gobbleOM \Gobble } \newcommand\GobbleMO [1] {% \@ifnextchar [ \sc@gobbleO \relax } \NewName{sc@gobbleOM} {[#1]#2} {} \NewName{sc@gobbleO} {[#1]} {} % \end{macrocode} % \end{macro} % \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{Toggle a boolean} % % \begin{macro}{\ToggleBoolean} % \mbox{} % \begin{macrocode} \newcommand\ToggleBoolean [1] {% arg: boolean \csname if#1\endcsname \sc@global\csname #1false\endcsname \else \sc@global\csname #1true\endcsname \fi } % \end{macrocode} % \end{macro} % % \section{Debugging} % % \begin{macro}{\VerboseErrors} % \begin{macro}{\GVerboseErrors} % 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% } \newcommand*\GVerboseErrors [1][\@M] {% args: [number] \global\c@errorcontextlines #1% \global\showboxbreadth #1% \global\showboxdepth #1% } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\Debug} % \begin{macro}{\GDebug} % \begin{macro}{\md@maybe@global} % Set \cs\debug to 0, 1, or~2. ^^A remember \cs\showlists % \begin{macrocode} \ReserveCS\md@maybe@global \newcommand*\Debug {% \let\md@maybe@global\relax \md@debug } \newcommand*\GDebug {% \let\md@maybe@global\global \md@debug } \newcommand*\md@debug [1] {% args: debug-level \ifnum #1 > 0% \let\sc@t@a\@M \md@maybe@global\def\DTypeout ##1{% \typeout{##1}% }% \md@maybe@global\def\DGobbleM ##1{% \typeout{DGobbleM: [##1]}% }% \ifnum #1 > 1% \md@maybe@global\def\DDTypeout ##1{% \typeout{##1}% }% \ifnum #1 > 2% \md@maybe@global\def\DDDTypeout ##1{% \typeout{##1}% }% \fi \fi \else \let\sc@t@a\m@ne \md@maybe@global\let\DTypeout\GobbleM \md@maybe@global\let\DDTypeout\GobbleM \md@maybe@global\let\DDDTypeout\GobbleM \md@maybe@global\let\DGobbleM\GobbleM \fi \md@maybe@global\tracingoutput#1 % \md@maybe@global\tracingpages#1 % \md@maybe@global\tracingmacros#1 % \md@maybe@global\tracingcommands#1 % \ifx\md@maybe@global\relax \VerboseErrors[\sc@t@a]% \typeout{++++ Debugging [#1]\on@line}% \else \GVerboseErrors[\sc@t@a]% \typeout{++++ Global debugging [#1]\on@line}% \fi } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\DTypeout} % \begin{macro}{\DTypeout} % \begin{macro}{\DTypeout} % \begin{macro}{\DGobbleM} % When the debugging parameter is not set, these commands gobble their % argument. \todo{Streamline dox about ``debugging parameter''; should be % something checkable, no?} % \begin{macrocode} \newlet\DTypeout\GobbleM \newlet\DDTypeout\GobbleM \newlet\DDDTypeout\GobbleM \newlet\DGobbleM\GobbleM % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\FrankenError} % \begin{macro}{\FrankenWarning} % \begin{macro}{\FrankenInfo} % \mbox{} % \begin{macrocode} \newcommand\FrankenWarning [2] {% args: package warning \GenericWarning % continuation message {(#1)\@spaces\@spaces\@spaces\@spaces\@spaces} {Frankenstein (#1) WARNING: #2}% } \newcommand\FrankenError [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\FrankenInfo [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