% \iffalse meta-comment % Line endings: UNIX % Tab size: 4 % % Copyright 2004 Jonathan Sauer % % This work may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either version 1.3 % of this license 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.3 or later is part of all distributions of LaTeX % version 2003/12/01 or later. % % This work has the LPPL maintenance status "maintained". % % The Current Maintainer of this work is Jonathan Sauer % (). % % This work consists of the files optparams.dtx and optparams.ins % and the derived file optparams.sty. % % \fi % % \iffalse % %<*driver> \documentclass{ltxdoc} \usepackage{optparams} \EnableCrossrefs \CodelineIndex \RecordChanges % Modification of verbatim for tabs in listings \makeatletter {\catcode`\ =\active% \catcode`\^^I=\active% \gdef\@vobeyspaces{% \catcode`\ \active\let \@xobeysp% \catcode`\^^I\active\def^^I{~~}% }}% \makeatother \begin{document} \DocInput{\jobname.dtx} \end{document} % % %\NeedsTeXFormat{LaTeX2e} %\ProvidesPackage{optparams} % [2004/08/14 v0.9 multiple optional parameters in macros] % % \fi % % \CheckSum{12} % \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 \~} % % \DoNotIndex{\@ifnextchar,\@nil,\def,\newcommand} % % \GetFileInfo{\jobname.sty} % % \title{The \textsf{optparams} package\thanks{This document % corresponds to \textsf{\filename}~\fileversion, dated \filedate. The % package is based on David Kastrup's macros for `Around the Bend % 21'.}} % % \author{Jonathan Sauer \\ \texttt{jonathan.sauer@gmx.de}} % % \date{\filedate} % % \maketitle % % \begin{abstract} % This file describes the \textsf{optparams} package that provides a % small macro for creating macros with multiple optional parameters. % % \end{abstract} % % \tableofcontents % % % % \section{Introduction} % % The \LaTeX\ macro |\newcommand| is used to define macros that may % have one optional parameter (the first one). However, there is no % easy way of defining macros having several optional parameters. This % package provides the macro |\optparams| to simplify the creation of % macros with multiple optional parameters (or optional parameters % only). % % % % \section{Examples} % % \subsection{Example one} % % \begin{verbatim} % \long\def\test@[#1][#2][#3][#4]{% % (#1) (#2) (#3) (#4) % } % % \newcommand{\test}{% % \optparams{\test@}{[one][two][three][four]}% % } % \end{verbatim} % You have now defined a macro |\test| that takes up to four optional % parameters (|#1| to |#4|). You can call this macro as: % % \begin{itemize} % \item |\test[this]|, resulting in |(this) (two) (three) (four)|. % % \item |\test[this][is]|, resulting in |(this) (is) (three) (four)|. % % \item |\test[this][is][a]|, resulting in |(this) (is) (a) (four)|. % % \item |\test[this][is][a][test]|, resulting in |(this) (is) (a) (test)|. % % \end{itemize} % You see that the default parameters defined in |\test| are replaced % one by one by the parameters given when |\test| is called. % % % % \subsection{Example two} % % \begin{verbatim} % \long\def\test@[#1][#2][#3][#4]#5{% % (#1) (#2) (#3) (#4) !#5! % } % % \newcommand{\test}{% % \optparams{\test@}{[one][two][three][four]}% % } % \end{verbatim} % You have now defined a macro |\test| that takes up to four optional % parameters (|#1| to |#4|) and one mandatory parameter (|#5)|. You % can call this macro as: % % \begin{itemize} % \item |\test[this]{foo}|, resulting in % |(this) (two) (three) (four) !foo!|. % % \item |\test[this][is]{foo}|, resulting in % |(this) (is) (three) (four) !foo!|. % % \item |\test[this][is][a]{foo}|, resulting in % |(this) (is) (a) (four) !foo!|. % % \item |\test[this][is][a][test]{foo}|, resulting in % |(this) (is) (a) (test) !foo!|. % % \end{itemize} % % % % \section{Description of the macros} % % \DescribeMacro{\optparams} Usage: |\optparams| \marg{macro} % \marg{default parameters}. % % This macro reads any optional parameters from the input and finally % calls your macro with the optional parameters as well as the % remaining default parameters. % % Each default parameter must have the form |[|\meta{value}|]|. As all % default parameters are passed as one parameter to |\optparams|, they % must be enclosed in braces (|{|\meta{default parameters}|}|). % % The macro that is finally called must have as many optional % parameters as have been defined in the call of |\optparams|; their % form must be |[|\meta{parameter}|]|, where \meta{parameter} is a % number beginning with one and ending with nine.\footnote{This is a % general restriction of \TeX: A macro cannot have more than nine % parameters.} The parameter numbers must be numbered consecutively, % i.e. |[#1][#2][#3]| instead of |[#1][#2][#4]|. % % Because of this special way of declaring macro parameters, you % cannot use |\newcommand| but have to use the \TeX\ primitiv |\def|. % As |\def|, contrary to |\newcommand|, does not warn you when you % overwrite an already existing macro, you first should define the % macro as a dummy using |\newcommand| and then correctly using % |\def|, i.e.: % % \begin{verbatim} % \newcommand{\test@}{} % \long\def\test@[#1][#2][#3][#4]{% % % } % \end{verbatim} % This way you do not accidentally overwrite an existing macro. % % What does the |\long| do? In \TeX, in order to quicker capture % errors such as missing right braces |}|, parameters of macros % defined using |\def| cannot contain a |\par|, or \TeX\ will complain % (`runaway argument?'). This makes it easier for the user to spot % mistakes, as in that case \TeX\ will stop processing immediately at % the end of the current paragraph and not continue until i.e. the end % of the file before realizing that a macro parameter has not been % closed via |}|. % % But there is a way to make the usage of |\par| as a macro parameter % possible: Using |\long| in front of the |\def|. In \LaTeX, % |\newcommand| defines macros as |\long| by default, and its variant % |\newcommand*| defines macros restricted to `short' parameters. So % as demonstrated in the examples, you should either use |\newcommand| % and |\long\def| together or |\newcommand*| and |\def| in order to % make your macros behave correctly. % % % % \section{Notes} % % \begin{itemize} % \item If you use the notation used in the examples above, % \meta{macroname} for the main macro and % \meta{macroname}|@| for the macro finally called by % |\optparams|, and if you define these macros not in a % package or class, but in your document preamble, you have % to enclose the definitions in |\makeatletter| \ldots\ % |\makeatother|, otherwise you cannot use |@| in macro % names. % % \item If you define a macro having only optional parameters (as % in the first example above), you have to make sure the % macro is not called in a context where a |[| follows not % as a parameter, but simply as an opening bracket, i.e. % |\test[foo] [as a side note| \ldots, where the call of % |\test| should have only |[foo]| as its only % parameter. In this case |\optparams| will think that % another optional parameter follows, resulting in chaos. % % To prevent this from happening, insert a |\relax| after % the last optional parameter of the macro call, i.e. % |\test[foo]\relax [as a side note| \ldots\ Then % |\optparams| will stop looking for more optional % parameters. % % \end{itemize} % % \StopEventually{} % % % % \section{Implementation} % % \subsection{Main macros} % % \begin{macro}{\optparams} % % Calls |#1| using a variable number of parameters. Default parameters % are provided in |#2| in the form |[|\meta{param one}|]| |[|\meta{param % two}|]| \ldots % % \begin{macrocode} \newcommand{\optparams}[2]{% \optparams@{#1}{}{#2}% } % \end{macrocode} % \end{macro} % % % % \subsection{Internal macros} % % \begin{macro}{\optparams@} % % Checks if the next character from the input is a |[|. If true calls % |\optparams@@|, as there are still optional parameters left. Otherwise % calls \meta{macro} with \meta{parameters read} and \meta{remaining % default parameters}. % % Usage: |\optparams@| \marg{macro} \marg{parameters read} % \marg{remaining default parameters}. % % \begin{macrocode} \def\optparams@#1#2#3{% \@ifnextchar[{% \optparams@@{#1}{#2}#3\@nil% }{% #1#2#3% }% } % \end{macrocode} % \end{macro} % % % \begin{macro}{\optparams@@} % % Reads the next optional parameter from the input (as |#5| or % \meta{new parameter}). Then gobbles up the corresponding default % parameter (as |#3| or \meta{default for parameter read}, appends the % parameter read to \meta{parameters read} and calls |\optparams@| % again to check for more optional parameters. % % Usage: |\optparams@@| \marg{macro} \marg{parameters read} % \marg{default for parameter read} \marg{remaining default % parameters} \marg{new parameter}. % % \begin{macrocode} \def\optparams@@#1#2[#3]#4\@nil[#5]{% \optparams@{#1}{#2[#5]}{#4}% } % \end{macrocode} % \end{macro} % % Now this is quite a coincidence: Thirteen lines of code, and this % package was begun on Friday, 13th \ldots % % \Finale % \PrintChanges % \PrintIndex \endinput