diff options
Diffstat (limited to 'Master/texmf-dist/doc/latex/newcommand/newcommand.tex')
-rw-r--r-- | Master/texmf-dist/doc/latex/newcommand/newcommand.tex | 742 |
1 files changed, 742 insertions, 0 deletions
diff --git a/Master/texmf-dist/doc/latex/newcommand/newcommand.tex b/Master/texmf-dist/doc/latex/newcommand/newcommand.tex new file mode 100644 index 00000000000..4f4265c2376 --- /dev/null +++ b/Master/texmf-dist/doc/latex/newcommand/newcommand.tex @@ -0,0 +1,742 @@ +\documentclass{ltxdoc} +\usepackage[T1]{fontenc} +\usepackage{tabularx} +\usepackage{syntax} +\usepackage{varioref} +\usepackage{color} +\usepackage{booktabs} +\usepackage{alltt} +\usepackage{textcomp} +\usepackage[bookmarksopen=true]{hyperref} + +% Define this document's metadata. +\def\ncfileversion{2.0} +\def\ncfiledate{2010/06/01} + +\title{The \textsf{newcommand.py} utility\thanks{\textsf{newcommand.py} + has version number \ncfileversion, last revised \ncfiledate.}} +\author{\href{mailto:scott+nc@pakin.org}{Scott Pakin} \\ + \href{mailto:scott+nc@pakin.org}{scott+nc@pakin.org}} +\date{\ncfiledate} +\hypersetup{% + pdftitle={The newcommand.py utility}, + pdfauthor={Scott Pakin <scott+nc@pakin.org>}, + pdfsubject={Creating user-defined macros with more flexible argument + processing}, + pdfkeywords={LaTeX macros, optional arguments, newcommand, parenthesized + arguments, starred commands, Python} +} + +% Help prevent weird line breaks in URLs +\def\UrlBreaks{} +\def\UrlBigBreaks{\do/} + +% Define some useful shortcuts. +\newcommand*{\ncpy}{\texttt{newcommand.py}} % The name of the script +\newcommand*{\usercmd}[1]{\textcolor{blue}{#1}} % User command entry +\newcommand{\prototype}[1]{{% % Prompt and user entry + \bigskip + \noindent + \ttfamily\small\raggedright + \hangafter=1\hangindent=4em + ~~~~\% Prototype:~\textcolor{blue}{#1}\strut\par + \vspace*{-0.5\baselineskip}% +}} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\begin{document} +\maketitle +\sloppy + +\begin{abstract} + \LaTeX's \cs{newcommand} is fairly limited in the way it processes + optional arguments, but the \TeX\ alternative, a batch of \cs{def}s + and \cs{futurelet}s, can be overwhelming to the casual \LaTeX\ user. + \ncpy\ is a Python program that automatically generates + \LaTeX\ macro definitions for macros that require more powerful + argument processing than \cs{newcommand} can handle. \ncpy\ is + intended for \LaTeX\ advanced beginners (i.e., those who know how to + use \cs{newcommand} but not internal \LaTeXe\ macros like + |\@ifnextchar|) and for more advanced users who want to save some + typing when defining complex macros. +\end{abstract} + +\section{Introduction} + +\LaTeX's \cs{newcommand} is a rather limited way to define new macros. +Only one argument can be designated as optional, it must be the first +argument, and it must appear within square brackets. Defining macros +that take multiple optional arguments or in which an optional argument +appears in the middle of the argument list is possible but well beyond +the capabilities of the casual \LaTeX\ user. It requires using +\TeX\ primitives such as \cs{def} and \cs{futurelet} and/or +\LaTeXe\ internal macros such as \cs{@ifnextchar}. + +\ncpy\ is a Python program that reads a specification of an argument +list and automatically produces \LaTeX\ code that processes the +arguments appropriately. \ncpy\ makes it easy to define +\LaTeX\ macros with more complex parameter parsing than is possible +with \cs{newcommand} alone. Note that you do need to have Python +installed on your system to run \ncpy. Python is freely available for +download from \url{http://www.python.org/}. + +To define a \LaTeX\ macro, one gives \ncpy\ a macro description +written in a simple specification language. The description +essentially lists the required and optional arguments and, for each +optional argument, the default value. The next section of this +document describes the syntax and provides some examples, but for now, +let's look at how one would define the most trivial macro possible, +one that takes no arguments. Enter the following at your operating +system's prompt: + +\begin{alltt} + \usercmd{newcommand.py "MACRO trivial"} +\end{alltt} + +\noindent +(Depending on your system, you may need to prefix that command with +``|python|''.) The program should output the following \LaTeX\ code +in response: + +\begin{verbatim} + % Prototype: MACRO trivial + \newcommand{\trivial}{% + % Put your code here. + } +\end{verbatim} + +\noindent +Alternatively, you can run \ncpy\ interactively, entering macro +descriptions at the ``|% Prototype:|'' prompt: + +\prototype{MACRO trivial} +\begin{verbatim} + \newcommand{\trivial}{% + % Put your code here. + } + % Prototype: +\end{verbatim} + +\noindent +Enter your operating system's end-of-file character (Ctrl-D in Unix or +Ctrl-Z in Windows) to exit the program. + +While you certainly don't need \ncpy\ to write macros that are as +trivial as \cs{trivial}, the previous discussion shows how to run the +program and the sort of output that you should expect. There will +always be a ``\texttt{Put your code here}'' comment indicating where +you should fill in the actual macro code. At that location, all of +the macro's parameters---both optional and required---will be defined +and can be referred to in the ordinary way: |#1|, |#2|, |#3|, etc. + + +\section{Usage} + +As we saw in the previous section, macros are defined by the word +``|MACRO|'' followed by the macro name, with no preceding backslash. +In this section we examine how to specify increasingly sophisticated +argument processing using \ncpy. + + +\subsection{Required arguments} + +Required arguments are entered as~|#1|, |#2|, |#3|, \dots, with no +surrounding braces: + +\prototype{MACRO required \#1 \#2 \#3 \#4 \#5} +\begin{verbatim} + \newcommand{\required}[5]{% + % Put your code here. + % You can refer to the arguments as #1 through #5. + } +\end{verbatim} + +Parameters must be numbered in monotonically increasing order, +starting with~|#1|. Incorrectly ordered parameters will produce an +error message: + +\prototype{MACRO required \#1 \#3 \#4} +\begin{verbatim} + ^ + newcommand.py: Expected parameter 2 but saw parameter 3. +\end{verbatim} + + +\subsection{Optional arguments} + +Optional arguments\label{par:optional-args} are written as either +``|OPT[|\meta{param}|=|\linebreak[1]|{|\meta{default}|}]|'' or +``|OPT(|\meta{param}|=|\linebreak[1]|{|\meta{default}|})|''. In the +former case, square brackets are used to offset the optional argument; +in the latter case, parentheses are used. \meta{param} is the +parameter number (|#1|, |#2|, |#3|, \dots), and \meta{default} is the +default value for that parameter. Note that curly braces are required +around \meta{default}. + +\prototype{MACRO optional OPT[\#1=\{maybe\}]} +\begin{verbatim} + \newcommand{\optional}[1][maybe]{% + % Put your code here. + % You can refer to the argument as #1. + } +\end{verbatim} + +Up to this point, the examples have been so simple that \ncpy\ is +overkill for entering them. We can now begin specifying constructs +that \LaTeX's \cs{newcommand} can't handle, such as a parenthesized +optional argument, an optional argument that doesn't appear at the +beginning of the argument list, and multiple optional arguments: + +\prototype{MACRO parenthesized OPT(\#1=\{abc\})} +\begin{verbatim} + \makeatletter + \newcommand{\parenthesized}{% + \@ifnextchar({\parenthesized@i}{\parenthesized@i({abc})}% + } + + \def\parenthesized@i(#1){% + % Put your code here. + % You can refer to the argument as #1. + } + \makeatother +\end{verbatim} + + +\prototype{MACRO nonbeginning \#1 OPT[\#2=\{abc\}]} +\begin{verbatim} + \makeatletter + \newcommand{\nonbeginning}[1]{% + \@ifnextchar[{\nonbeginning@i{#1}}{\nonbeginning@i{#1}[{abc}]}% + } + + \def\nonbeginning@i#1[#2]{% + % Put your code here. + % You can refer to the arguments as #1 and #2. + } + \makeatother +\end{verbatim} + +\prototype{MACRO multiple OPT[\#1=\{abc\}] OPT[\#2=\{def\}]} +\begin{verbatim} + \makeatletter + \newcommand{\multiple}[1][abc]{% + \@ifnextchar[{\multiple@i[{#1}]}{\multiple@i[{#1}][{def}]}% + } + + \def\multiple@i[#1][#2]{% + % Put your code here. + % You can refer to the arguments as #1 and #2. + } + \makeatother +\end{verbatim} + +The template for optional arguments that was +shown~\vpageref[above]{par:optional-args} stated that optional +arguments contain a ``\meta{param}|={|\meta{default}|}|'' +specification. In fact, optional arguments can contain +\emph{multiple} ``\meta{param}|={|\meta{default}|}|'' specifications, +as long as they are separated by literal text: + +\prototype{MACRO multiopt OPT(\#1=\{0\},\#2=\{0\})} +\begin{verbatim} + \makeatletter + \newcommand{\multiopt}{% + \@ifnextchar({\multiopt@i}{\multiopt@i({0},{0})}% + } + + \def\multiopt@i(#1,#2){% + % Put your code here. + % You can refer to the arguments as #1 and #2. + } + \makeatother +\end{verbatim} + +\noindent +In that example, \cs{multiopt} takes an optional parenthesized +argument. If omitted, it defaults to |(0,0)|. If provided, the +argument must be of the form ``|(|\meta{x}|,|\meta{y}|)|''. In either +case, the comma-separated values within the parentheses are parsed +into~|#1| and~|#2|. Contrast that with the following: + +\prototype{MACRO multiopt OPT(\#1=\{0,0\})} +\begin{verbatim} + \makeatletter + \newcommand{\multiopt}{% + \@ifnextchar({\multiopt@i}{\multiopt@i({0,0})}% + } + + \def\multiopt@i(#1){% + % Put your code here. + % You can refer to the argument as #1. + } + \makeatother +\end{verbatim} + +The optional argument still defaults to |(0,0)|, but |#1| receives +\emph{all} of the text that lies between the parentheses; +\cs{multiopt} does not parse it into two comma-separated values +in~|#1| and~|#2|, as it did in the previous example. + +\bigskip + +The \meta{default} text in an |OPT| term can reference any macro +parameter introduced before the |OPT|\@. Hence, the following defines +a macro that accepts a required argument followed by an optional +argument. The default value of the optional argument is the value +provided for the required argument: + +\prototype{MACRO paramdefault \#1 OPT[\#2=\{\#1\}]} +\begin{verbatim} + \makeatletter + \newcommand{\paramdefault}[1]{% + \@ifnextchar[{\paramdefault@i{#1}}{\paramdefault@i{#1}[{#1}]}% + } + + \def\paramdefault@i#1[#2]{% + % Put your code here. + % You can refer to the arguments as #1 and #2. + } + \makeatother +\end{verbatim} + + +\subsection{Literal text} + +In addition to required and optional parameters, it is also possible +to specify text that must appear literally in the macro call. Merely +specify it within curly braces: + +\prototype{MACRO textual \#1 \{ and \} \#2 \{.\}} +\begin{verbatim} + \makeatletter + \newcommand{\textual}[1]{% + \textual@i{#1}% + } + + \def\textual@i#1 and #2.{% + % Put your code here. + % You can refer to the arguments as #1 and #2. + } + \makeatother +\end{verbatim} + +\noindent +A macro such as \cs{textual} can be called like this: + +\begin{verbatim} + \textual {Milk} and {cookies}. +\end{verbatim} + +\noindent +Actually, in that example, because both |Milk| and |cookies| are +delimited on the right by literal text, \TeX\ can figure out how to +split \cs{textual}'s argument into~|#1| and~|#2| even if the curly +braces are omitted: + +\begin{verbatim} + \textual Milk and cookies. +\end{verbatim} + +\subsection{Starred macros} + +The names of some \LaTeX\ macros can be followed by an optional +``|*|'' to indicate a variation on the normal processing. For +example, \cs{vspace}, which introduces a given amount of vertical +space, discards the space if it appears at the top of the page. +|\vspace*|, in contrast, typesets the space no matter where it +appears. \ncpy\ makes it easy for users to define their own starred +commands: + +\prototype{MACRO starred * \#1 \#2} +\begin{verbatim} + \makeatletter + \newif\ifstarred@star + \newcommand{\starred}{% + \@ifstar{\starred@startrue\starred@i*}{\starred@starfalse\starred@i*}% + } + + \def\starred@i*#1#2{% + \ifstarred@star + % Put code for the "*" case here. + \else + % Put code for the non-"*" case here. + \fi + % Put code common to both cases here (and/or above the \ifstarred@star). + % You can refer to the arguments as #1 and #2. + } + \makeatother +\end{verbatim} + +\noindent +Note that unlike the generated code shown up to this point, the code +for starred macros includes \emph{multiple} placeholders for user +code. + +The ``|*|'' in a starred macro does not have to immediately follow the +macro name; it can appear anywhere in the macro specification. +However, \ncpy\ currently limits macros to at most one asterisk. + +Embedding an asterisk within curly braces causes it to be treated not +as an optional character but as (required) literal text. Contrast the +preceding example with the following one: + +\prototype{MACRO starred \{*\} \#1 \#2} +\begin{verbatim} + \makeatletter + \newcommand{\starred}{% + \starred@i% + } + + \def\starred@i*#1#2{% + % Put your code here. + % You can refer to the arguments as #1 and #2. + } + \makeatother +\end{verbatim} + +The asterisk in that definition of \cs{starred} must be included in +every macro invocation or \TeX\ will abort with a ``\texttt{Use of + \string\starred@i doesn't match its definition}'' error. + + +\subsection{More than nine arguments} + +\TeX\ imposes a limit of nine arguments per macro. Internally, +``|#|'' is expected to be followed by exactly one digit, which means +that ``|#10|'' refers to argument~|#1| followed by the character~|0|. +Fortunately, it's rare that a macro needs more than nine arguments and +rarer still that those arguments are not better specified as a list of +\meta{key}|=|\meta{value} pairs, as supported by the \textsf{keyval} +package and many other \LaTeX\ packages. + +If large numbers of arguments are in fact necessary, \ncpy\ does let +you specify them. The trick that the generated code uses is to split +the macro into multiple macros, each of which takes nine or fewer +arguments and stores the value of each argument in a variable that can +later be accessed. Because digits are awkward to use in macro names, +\ncpy\ uses roman numerals to name arguments in the case of more than +nine arguments: |\|\meta{name}|@arg@i| for |#1|, +|\|\meta{name}|@arg@ii| for |#2|, |\|\meta{name}|@arg@iii| for |#3|, +|\|\meta{name}|@arg@iv| for |#4|, and so forth. The following example +takes 14 required arguments and one optional argument (which defaults +to the string ``|etc|''): + +\prototype{MACRO manyargs \#1 \#2 \#3 \#4 \#5 \#6 \#7 \#8 \#9 \#10 + \#11 \#12 \#13 \#14 OPT[\#15=\{etc\}]} +\begin{verbatim} + \makeatletter + \newcommand{\manyargs}[9]{% + \def\manyargs@arg@i{#1}% + \def\manyargs@arg@ii{#2}% + \def\manyargs@arg@iii{#3}% + \def\manyargs@arg@iv{#4}% + \def\manyargs@arg@v{#5}% + \def\manyargs@arg@vi{#6}% + \def\manyargs@arg@vii{#7}% + \def\manyargs@arg@viii{#8}% + \def\manyargs@arg@ix{#9}% + \manyargs@i + } + + \def\manyargs@i#1#2#3#4#5{% + \def\manyargs@arg@x{#1}% + \def\manyargs@arg@xi{#2}% + \def\manyargs@arg@xii{#3}% + \def\manyargs@arg@xiii{#4}% + \def\manyargs@arg@xiv{#5}% + \@ifnextchar[{\manyargs@ii}{\manyargs@ii[{etc}]}% + } + + \def\manyargs@ii[#1]{% + \def\manyargs@arg@xv{#1}% + % Put your code here. + % You can refer to the arguments as \manyargs@arg@i through \manyargs@arg@xv. + } + \makeatother +\end{verbatim} + +The current version of \ncpy\ is limited to 4000 arguments, which +should be more than enough for most purposes. + + +\subsection{Summary} + +A macro is defined in \ncpy\ with: + +\begin{center} + \texttt{MACRO} \meta{name} \meta{arguments} +\end{center} + +\noindent +in which \meta{name} is the name of the macro, and \meta{arguments} is +zero or more of the following: + +\begin{center} +\renewcommand{\arraystretch}{1.1} +\begin{tabularx}{\linewidth}{@{}lXl@{}} + \toprule + \multicolumn{1}{@{}c}{Argument} & + \multicolumn{1}{c}{Meaning} & + \multicolumn{1}{c@{}}{Example} \\ + \midrule + + |#|\meta{number} & Parameter (required) & |#1| \\ + \marg{text} & Literal text (required) & |{+}| \\ + |OPT[#|\meta{number}|=|\marg{text}|]| & Parameter (optional, with default) & + |OPT[#1={tbp}]| \\ + |OPT(#|\meta{number}|=|\marg{text}|)| & Same as the above, but with + parentheses instead of brackets & |OPT(#1={tbp})| \\ + |*| & Literal asterisk (optional) & |*| \\ + \bottomrule +\end{tabularx} +\end{center} + +Within an |OPT| argument, |#|\meta{number}|=|\marg{text} can be +repeated any number of times, as long as the various instances are +separated by literal text. + + +\section{Further examples} + +\subsection{Mimicking \LaTeX's \texttt{picture} environment} + +The \LaTeX\ |picture| environment takes two, parenthesized, +coordinate-pair arguments, the second pair being optional. Here's how +to define a macro that takes the same arguments as the |picture| +environment and parses them into $x_1$, $y_1$, $x_2$, and~$y_2$ +(i.e.,~|#1|--|#4|): + +\prototype{MACRO picturemacro \{(\}\#1\{,\}\#2\{)\} OPT(\#3=\{0\},\#4=\{0\})} +\begin{verbatim} + \makeatletter + \newcommand{\picturemacro}{% + \picturemacro@i% + } + + \def\picturemacro@i(#1,#2){% + \@ifnextchar({\picturemacro@ii({#1},{#2})}{\picturemacro@ii({#1},{#2})({0},{0})}% + } + + \def\picturemacro@ii(#1,#2)(#3,#4){% + % Put your code here. + % You can refer to the arguments as #1 through #4. + } + \makeatother +\end{verbatim} + +The first pair of parentheses and the comma are quoted because they +represent required, literal text. + + +\subsection{Mimicking \LaTeX's \texttt{\string\parbox} macro} + +\LaTeX's \cs{parbox} macro takes three optional arguments and two +required arguments. Furthermore, the third argument defaults to +whatever value was specified for the first argument. This is easy to +express in \LaTeX\ with the help of \ncpy: + +\prototype{MACRO parboxlike OPT[\#1=\{s\}] OPT[\#2=\{\string\relax\}] + OPT[\#3=\{\#1\}] \#4 \#5} +\begin{verbatim} + \makeatletter + \newcommand{\parboxlike}[1][s]{% + \@ifnextchar[{\parboxlike@i[{#1}]}{\parboxlike@i[{#1}][{\relax}]}% + } + + \def\parboxlike@i[#1][#2]{% + \@ifnextchar[{\parboxlike@ii[{#1}][{#2}]}{\parboxlike@ii[{#1}][{#2}][{#1}]}% + } + + \def\parboxlike@ii[#1][#2][#3]#4#5{% + % Put your code here. + % You can refer to the arguments as #1 through #5. + } + \makeatother +\end{verbatim} + + +\subsection{Dynamically changing argument formats} +\label{sec:dynamic-args} + +With a little cleverness, it is possible for a macro to accept one of +two completely different sets of arguments based on the values +provided for earlier arguments. For example, suppose we want to +define a macro, \cs{differentargs} that can be called as either + +\begin{verbatim} + \differentargs*[optarg]{reqarg} +\end{verbatim} + +\noindent +or + +\begin{verbatim} + \differentargs{reqarg}(optarg) +\end{verbatim} + +\noindent +That is, the presence of an asterisk determines whether +\cs{differentargs} should expect an optional argument in square +brackets followed by a required argument or to expect a required +argument followed by an optional argument in parentheses. + +The trick is to create two helper macros: one for the ``|*|'' case +(\cs{withstar}) and the other for the non-``|*|'' case +(\cs{withoutstar}). \cs{differentargs} can then invoke one of +\cs{withstar} or \cs{withoutstar} based on whether or not it sees an +asterisk. The following shows how to use \ncpy\ to define +\cs{differentargs}, \cs{withstar}, and \cs{withoutstar} and how to +edit \cs{differentargs} to invoke its helper macros: + +\prototype{MACRO differentargs *} +\begin{verbatim} + \makeatletter + \newif\ifdifferentargs@star + \newcommand{\differentargs}{% + \@ifstar{\differentargs@startrue\differentargs@i*} + {\differentargs@starfalse\differentargs@i*}% + } +\end{verbatim} +\begingroup +\small +\begin{alltt} + \cs{def}\cs{differentargs@i}*\{% + \cs{ifdifferentargs@star} + % Put code for the "*" case here. + \colorbox{yellow}{\cs{let}\cs{next}=\cs{withstar}} + \cs{else} + % Put code for the non-"*" case here. + \colorbox{yellow}{\cs{let}\cs{next}=\cs{withoutstar}} + \cs{fi} + % Put code common to both cases here (and/or above the \cs{ifdifferentargs@star}). + \colorbox{yellow}{\cs{next}} + \} + \cs{makeatother} +\end{alltt} +\endgroup + +\prototype{MACRO withstar OPT[\#1=\{starry\}] \#2} +\begin{verbatim} + \newcommand{\withstar}[2][starry]{% + % Put your code here. + % You can refer to the arguments as #1 and #2. + } +\end{verbatim} + +\prototype{MACRO withoutstar \#1 OPT(\#2=\{dark\})} +\begin{verbatim} + \makeatletter + \newcommand{\withoutstar}[1]{% + \@ifnextchar({\withoutstar@i{#1}}{\withoutstar@i{#1}({dark})}% + } + + \def\withoutstar@i#1(#2){% + % Put your code here. + % You can refer to the arguments as #1 and #2. + } + \makeatother +\end{verbatim} + +Note that we edited \cs{differentargs@i} to let \cs{next} be +equivalent to either \cs{withstar} or \cs{withoutstar} based on +whether an asterisk was encountered. \cs{next} is evaluated outside +of the \cs{ifdifferentargs@star}\dots\linebreak[0]\cs{fi} control +structure. This rigmarole is necessary because directly calling +\cs{withstar} or \cs{withoutstar} would cause those macros to see +\cs{ifdifferentargs@star}'s \cs{else} or \cs{fi} as their first +argument when they ought to see the text following the +\cs{differentargs} call. + + +\section{Grammar} + +The following is the formal specification of \ncpy's grammar, written +in a more-or-less top-down manner. Literal values, shown in a +typewriter font, are case-sensitive. \meta{letter} refers to a letter +of the (English) alphabet. \meta{digit} refers to a digit. + +\setlength{\grammarindent}{7em} +\begin{grammar} +<decl> ::= \[[ "MACRO" <ident> <arglist> \]] + +<ident> ::= \[[ \begin{rep} <letter> \end{rep} \]] + +<arglist> ::= \[[ \begin{rep} \\ <arg> \end{rep} \]] + +<arg> ::= \[[ + \begin{stack} + <formal> \\ + <quoted> \\ + <optarg> \\ + "*" + \end{stack} + \]] + +<formal> ::= \[[ "#" \begin{rep} <digit> \end{rep} \]] + +<quoted> ::= \[[ "{" <rawtext> "}" \]] + +<rawtext> ::= \[[ \begin{rep} \tok{anything except a "{", "}", or "\#"} \end{rep} \]] + +<optarg> ::= \[[ "OPT" <delim> <defvals> <delim> \]] + +<delim> ::= \[[ \begin{stack} "[" \\ "]" \\ "(" \\ ")" \end{stack} \]] + +<defvals> ::= \[[ + \begin{rep} + <defval> \\ + \begin{stack} + <quoted> \\ + <rawtext> + \end{stack} + \end{rep} + \]] + +<defval> ::= \[[ <formal> "=" <quoted> \]] +\end{grammar} + + +\section{Acknowledgements} + +I'd like to say thank you to the following people: + +\begin{itemize} + \item John Aycock for writing the + \href{http://pages.cpsc.ucalgary.ca/~aycock/spark/}{Scanning, + Parsing, and Rewriting Kit (SPARK)}---the lexer and parser + underlying \ncpy---and making it freely available and + redistributable. + + \item Hendri Adriaens for pointing out a bug in the code generated + by \ncpy. Previously, bracketed text within a mandatory argument + could be mistaken for an optional argument. + + \item Tom Potts for reporting a spurious error message caused by the + processing of |OPT|. This bug has now been fixed. Tom Potts also + proposed the example used in Section~\ref{sec:dynamic-args} in + which the starred and unstarred versions of a macro take different + arguments. +\end{itemize} + + +\section{Copyright and license} + +Copyright~\copyright{} 2010, Scott Pakin + +\bigskip + +This package may be distributed and/or modified under the conditions +of the \LaTeX{} Project Public License, either version~1.3c of this +license or (at your option) any later version. The latest version of +this license is in: + +\begin{center} + \url{http://www.latex-project.org/lppl.txt} +\end{center} + +\noindent +and version~1.3c or later is part of all distributions of \LaTeX{} +version 2006/05/20 or later. + +\end{document} |