Permalink
Find file
Fetching contributors…
Cannot retrieve contributors at this time
1560 lines (1557 sloc) 59.4 KB
%
% \iffalse /!\ this file contains non-ascii -- encoding is utf-8 /!\
%
% xargs package by Manuel P\'egouri\'e-Gonnard <mpg@elzevir.fr>
% -------------------------------------------------------------
%
% This work 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:
%
% http://www.latex-project.org/lppl.txt
%
% and version 1.3c or later is part of all distributions of LaTeX
% version 2006/05/20 or later.
%
% This work has the LPPL maintenance status `maintained'.
%
% The current maintainer of this work is Manuel P\'egouri\'e-Gonnard.
%
% This work consists of the file xargs.dtx and the derived files
% xargs.sty, xargs.pdf and xargs-fr.pdf.
%
%
%<*gobble>
\ProvidesFile{xargs.dtx}
%</gobble>
%<package>\NeedsTeXFormat{LaTeX2e}
%<package>\ProvidesPackage{xargs}
%<*package>
% \fi
% \ProvidesFile{xargs.dtx}
[2008/03/22 v1.1 \space extended macro definitions \space (mpg)]
% \iffalse
%</package>
% \fi
% \CheckSum{782}
% \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 \~}
% \iffalse
%<*gobble>
\begingroup
%</gobble>
%<*batchfile>
\input docstrip
\keepsilent
\preamble
xargs package by Manuel P\string\'egouri\string\'e-Gonnard %
<mpg@elzevir.fr>
This is a generated file. See xargs.dtx for license information.
\endpreamble
\askforoverwritefalse
%\generate{\file{xargs.ins}{\from{xargs.dtx}{batchfile}}}
%\generate{\file{xargs.drv}{\from{xargs.dtx}{driver}}}
\generate{\file{xargs.sty}{\from{xargs.dtx}{package}}}
\generate{\file{xargs-fr.drv}{\from{xargs.dtx}{pilote}}}
%</batchfile>
%<*gobble>
\endgroup
%</gobble>
%<*driver|pilote>
\documentclass[oneside, a4paper]{ltxdoc}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\usepackage{fixltx2e, mparhack}
\usepackage[babel=true, expansion=false]{microtype}
\usepackage{xargs}
\expandafter\newif\csname iffrenchdoc\endcsname % cachez ce if que je ne...
%<pilote>\frenchdoctrue
%</driver|pilote>
%<*gobble>
\iffrenchdoc
%</gobble>
%<*pilote>
\usepackage[lmargin=4.5cm, rmargin=3cm]{geometry}
\OnlyDescription
\usepackage[english, frenchb]{babel}
\FrenchFootnotes \AddThinSpaceBeforeFootnotes
\newcommand*\eng[1]{\emph{\foreignlanguage{english}{#1}}}
\usepackage[colorlinks=true, bookmarks=true,
bookmarksnumbered=true, bookmarksopen=true, bookmarksopenlevel=3,
pdfauthor={Manuel Pégourié-Gonnard},
pdftitle={L'extension xargs},
pdfsubject={Définitions de macros étendues pour LaTeX2e},
]{hyperref}
%</pilote>
%<*gobble>
\else
%</gobble>
%<*driver>
\AlsoImplementation
\usepackage[english]{babel}
\usepackage[colorlinks=true, bookmarks=true,
bookmarksnumbered=true, bookmarksopen=true, bookmarksopenlevel=3,
pdfauthor={Manuel Pégourié-Gonnard},
pdftitle={The xargs package},
pdfsubject={Extended macro definitions for LaTeX2e},
]{hyperref}
\settowidth\MacroIndent{\rmfamily\scriptsize 000\ }
\setlength\MacroTopsep{0pt}
\usepackage[nohints, english]{minitoc}
\mtcsetpagenumbers{secttoc}{off}
\mtcsetrules{secttoc}{off}
\mtcsetdepth{secttoc}{3}
\setlength{\stcindent}{0pt}
\mtcsetfont{secttoc}{subsection}{\normalfont}
\newcommand\tocwithmini{%
\dosecttoc[n]
\setcounter{tocdepth}{1}\tableofcontents
\setcounter{tocdepth}{3}\faketableofcontents}
%</driver>
%<*gobble>
\fi
%</gobble>
%<*driver|pilote>
\newcommand\pf{\textsf}
\newcommand\optstar{\meta{$*$}}
\newcommand\topcs[1]{\texorpdfstring{\cs{#1}}{#1}}
\newcommand\eTeX{$\varepsilon$-\TeX}
\begin{document}
\DocInput{xargs.dtx}
\end{document}
%</driver|pilote>
%<*package>
% \fi
%
% \GetFileInfo{xargs.dtx}
%
% \title{\iffrenchdoc L'extension \pf{xargs}\else The \pf{xargs} package\fi}
% \author{Manuel Pégourié-Gonnard\\
% \href{mailto:mpg@elzevir.fr}{mpg@elzevir.fr}}
% \date{\fileversion\ (\filedate)}
%
% \maketitle
% \iffrenchdoc\else \tocwithmini \fi
%
% \iffrenchdoc\else
% \medskip
% \emph{Important note for French users}: a French version of the user
% documentation is included in the \nolinkurl{xargs-fr.pdf} file.
% \fi
%
% \section{Introduction}
%
% \iffrenchdoc
%
% \LaTeXe{} permet de définir facilement des commandes ayant un argument
% optionel. Cependant, il y a deux restrictions : il peut y avoir au plus un
% argument optionel, et ce doit être le premier. L'extension \pf{xargs}
% fournit des versions étendues de \cs{newcommand} et de ses analogues
% standard, qui ne présentent pas ces restrictions : il est désormais
% facile de définir des commandes avec plusieurs arguments optionnels,
% placés où l'on veut, par une syntaxe agréable du style
% \meta{clé}=\meta{valeur}. Par exemple, voici comment définir une
% commande avec deux arguments optionnels.
%
% \begin{center}
% |\newcommandx*\coord[3][1=1, 3=n]{(#2_{#1},\ldots,#2_{#3})}|
% \newcommandx*\coord[3][1=1, 3=n]{(#2_{#1},\ldots,#2_{#3})}
% \par\medskip
% \begin{tabular}{ll}
% |$\coord{x}$| & $\coord{x}$ \\
% |$\coord[0]{y}$| & $\coord[0]{y}$ \\
% |$\coord{z}[m]$| & $\coord{z}[m]$ \\
% |$\coord[0]{t}[m]$| & $\coord[0]{t}[m]$ \\
% \end{tabular}
% \end{center}
%
% \else
%
% Defining commands with an optional argument is easy in \LaTeXe{}.
% There is, however, two limitations: you can make only one argument
% optional and it must be the first one. The \pf{xargs} package provide
% extended variants of \cs{newcommand} \& friends, for which these
% limitations no longer hold: It is now easy to define commands with
% many (and freely placed) optional arguments, using a nice
% \meta{key}=\meta{value} syntax. For example, the following defines a
% command with two optional arguments.
%
% \begin{center}
% |\newcommandx*\coord[3][1=1, 3=n]{(#2_{#1},\ldots,#2_{#3})}|
% \newcommandx*\coord[3][1=1, 3=n]{(#2_{#1},\ldots,#2_{#3})}
% \par\medskip
% \begin{tabular}{ll}
% |$\coord{x}$| & $\coord{x}$ \\
% |$\coord[0]{y}$| & $\coord[0]{y}$ \\
% |$\coord{z}[m]$| & $\coord{z}[m]$ \\
% |$\coord[0]{t}[m]$| & $\coord[0]{t}[m]$ \\
% \end{tabular}
% \end{center}
%
% \fi
%
% \section{Usage}
%
% \iffrenchdoc
%
% \subsection{Les bases}
%
% L'extension \pf{xargs} fournit des analogues de toutes les macros de
% \LaTeXe{} relatives à la définition de macros. Les macros de \pf{xargs} ont
% le même nom que leur analogue standard, mais avec un |x| supplémentaire à la
% fin. En voici la liste complète.
%
% \begin{center}
% \begin{tabular}{ll}
% \cs{newcommandx} & \cs{renewcommandx} \\
% \cs{newenvironmentx} & \cs{renewenvironmentx} \\
% \cs{providecommandx} & \cs{DeclareRobustCommandx} \\
% \cs{CheckCommandx}
% \end{tabular}
% \end{center}
%
% Si vous ne connaissez pas toutes ces commandes, ne vous inquiétez pas.
% Vous pouvez utiliser seulement les analogues des macros que vous
% connaissez ; ou apprendre les autres par exemple dans le livre de
% \bsc{Lamport}, le \LaTeX{} Companion, ou tout autre manuel sur \LaTeXe.
%
% \medskip
%
% Ces commandes partageant toutes la même syntaxe, je parlerai seulement
% de |\newcommandx| par la suite, mais gardez à l'esprit que les
% explications sont valables pour les autres commandes. (Bien sûr, pour
% les environnements, il y a un dernier argument en plus, pour la
% définition de fin.) Voici la syntaxe complète de |\newcommand|.
%
% \begin{center}
% \cs{newcommandx}\optstar\marg{commande}\oarg{nombre}\oarg{liste}^^A
% \marg{définition}
% \end{center}
%
% Rappelons brièvement tout ce qui est commun avec la syntaxe usuelle, à
% savoir tout sauf \meta{liste}. Si une $*$ est présente, elle signifie
% que la macro crée est \emph{courte} au sens de \TeX{}, c'est-à-dire
% que ses arguments ne peuvent pas contenir de saut de paragraphe
% (\cs{par} ou ligne vide). La \meta{commande} est n'importe quelle
% séquence de contrôle, que vous pouvez ou non entourer d'accolades
% suivant vos goûts. Le \meta{nombre} définit le nombre total d'argument
% de la \meta{commande}, c'est un entier compris entre $0$ et $9$. La
% \meta{définition} est un texte équilibré en accolades, et où chaque
% caractère |#| est suivi soit d'un chiffre représentant un des
% arguments, soit d'un autre caractère |#|. Les arguments \meta{nombre}
% et \meta{liste} sont optionnels.
%
% \medskip
%
% La partie intéressante maintenant. La \meta{liste} est une\ldots{}
% liste (!) d'éléments de la forme \meta{chiffre}=\meta{valeur}, séparés
% par des virgules. Le \meta{chiffre} doit être un entier compris entre
% $1$ et le nombre d'arguments, donné par \meta{nombre}. La
% \meta{valeur} est n'importe quelle texte équilibré en accolades. Il
% peut être vide si vous le souhaitez : le signe égal qui le précède
% peut alors être omis. Tous les arguments dont le numéro figure en tant
% que \meta{chiffre} dans la \meta{liste} seront optionnels, avec pour
% valeur par défaut celle donnée par la \meta{valeur} correspondante.
%
% Quelques remarques supplémentaires sur la syntaxe de la \meta{liste},
% que vous pouvez sauter si vous êtes familiers avec la syntaxe fournie
% par \pf{xkeyval}. Vu que les éléments sont séparés par des virgules,
% si une \meta{valeur} doit contenir une virgule, il faut entourer la
% valeur par des accolades pour protéger la virgule. (Cette précaution
% est également indispensable si la \meta{valeur} contient une accolade
% fermante.) Ne vous inquiétez pas, cette parie d'accolade sera retirée
% ultérieurement. D'ailleurs, jusqu'à trois paires d'accolades seront
% retirées ainsi, et si vous voulez vraiment que votre valeur reste
% entourée d'accolades, il vous faudra écrire quelque chose
% comme~|1={{{{\large blabla}}}}|.
%
% \medskip
%
% C'est tout pour les bases : vous en savez maintenant assez pour
% utiliser \pf{xargs}, et vous pouvez laisser la fin de la documentation
% pour plus tard si vous voulez. Si, au contraire, vous vous demandez ce
% qui se passe avec plusieurs arguments optionnels à la suite, que vous
% voulez effectuer des définitions globales, ou que vous aves besoin de
% connaître les limites précises de \pf{xargs}, vous pouvez lire les
% sections suivantes.
%
% \subsection{La clé \texttt{usedefault}}
%
% Voyons donc se qui se passe quand plusieurs arguments optionnels se
% suivent. Le comportement par défaut est calqué sur celui de commandes
% \LaTeX{} comme \cs{makebox} et \cs{parbox} : on ne peut spécifier une
% valeur pour le troisième argument optionnel que si on l'a fait pour
% les deux premiers. Par exemple, dans l'exemple du début, remarquez
% comment j'avais pris soin de placer l'argument obligatoire au milieu
% pour séparer les arguments optionnels.
%
% Cependant, ce n'est pas très pratique, et on aimerait pouvoir choisir
% l'ordre des arguments plutôt selon leur sens, sans se poser de
% questions. Bien, la clé |usedefault| est justement là pour ça :
% incluez-la dans la \meta{liste}, et vous pouvez désormais utiliser
% |[]| pour sauter un argument optionnel, en utilisant sa valeur par
% défaut.
%
% \begin{center}
% |\newcommandx*\coord[3][2=1,3=n,usedefault]{(#2_{#1},\ldots,#2_{#3})}|
% \newcommandx*\coord[3][2=1, 3=n, usedefault]{(#2_{#1},\ldots,#2_{#3})}
% \par\medskip
% \begin{tabular}{ll}
% |$\coord{x}$| & $\coord{x}$ \\
% |$\coord{y}[0]$| & $\coord{y}[0]$ \\
% |$\coord{z}[][m]$| & $\coord{z}[][m]$ \\
% |$\coord{t}[0][m]$| & $\coord{t}[0][m]$ \\
% \end{tabular}
% \end{center}
%
% Bien sûr, sur cet exemple simple, c'est surtout une histoire de goût,
% mais parfois |usedefault| peut vous épargner pas mal de frappe
% inutile, car la valeur par défaut d'un argument est parfois longue, et
% qu'on a pas toujours assez d'arguments obligatoires pour séparer les
% arguments optionnels comme plus haut.
%
% Cette utilisation simple de |usedefault| présente un inconvénient :
% vous ne pouvez plus spécifier la valeur vide pour un argument
% optionnel. En fait, il faut nécessairement une valeur spéciale de
% l'argument pour dire \og utiliser la valeur par défaut \fg{}, mais ce
% n'est pas nécessairement la chaîne vide : en fait, on peut choisir
% cette valeur en disant |usedefault=|\meta{valeur}. L'exemple suivant
% ne sert à rien, à part illustrer ceci.
%
% \begin{center}
% |\newcommandx*\test[2][1=A, 2=B, usedefault=@]{(#1,#2)}|
% \newcommandx*\test[2][1=A, 2=B, usedefault=@]{(#1,#2)}
% \par\medskip
% \begin{tabular}{ll}
% |\test[b]| & \test[b] \\
% |\test[][b]| & \test[][b] \\
% |\test[@][b]| & \test[@][b] \\
% \end{tabular}
% \end{center}
%
% \subsection{Ajouter un préfixe}
%
% La commande |\newcommand| standard permet de définir au choix des
% macros \og longues \fg{} (dont les arguments peuvent contenir des
% \cs{par}) ou \og courtes \fg{} (les \cs{par} ou lignes vides sont
% interdits dans les arguments) au moyen de l'étoile optionnelle. C'est
% une partie de ce que \TeX{} appelle un préfixe, plus précisément la
% composante \cs{long}. Les autres composantes d'un préfixe peuvent être
% \cs{global}, \cs{outer}, ou (avec \eTeX) \cs{protected}. Il n'y a pas
% de moyen d'utiliser ces composantes avec \cs{newcommand}, bien que,
% par exemple, \cs{global} puisse être utile pour qu'une définition
% faite à l'intérieur d'un groupe (comme un environnement) ne soit pas
% \og oubliée \fg{} à la fin. (Pour des détails sur les autres, voir le
% \TeX book ou le manuel d'\eTeX.)
%
% Avec \pf{xargs}, vous pouvez utiliser la clé |addprefix|, \emph{sauf}
% pour la composante \cs{outer}, qui n'est pas et ne sera pas supportée
% (et, à ma connaissance n'est jamais utilisée dans \LaTeXe). Remarquons
% que cette clé \emph{ajoute} une préfixe à celui en cours, elle
% n'écrase rien. Au début, le préfixe par défaut est \cs{long}, ou vide
% si une étoile a été utilisée. Par exemple, les deux instructions
% suivantes ont exactement le même effet.
%
% \begin{quote}
% |\newcommandx*\truc[0][addprefix=\global, addprefix=\long,|\\
% | addprefix=\protected]{machin}|\\
% |\newcommandx\truc[0][addprefix=\global\protected]{machin}|
% \end{quote}
%
% En passant, les macros avec au moins un argument optionnel sont
% définies de façon robuste au sens que \LaTeXe{} donne à ce mot, je ne
% sais donc pas si le préfixe \cs{protected} est très utile. Je pense
% que la possibilité d'effectuer des définitions globales est l'usage
% principale de la clé |usedefault|.
%
% \subsection{Compatibilité et limitations connues}
%
% La mauvaise nouvelle (les limitations) en premier. Il y en a
% essentiellement une : on ne peut pas utiliser dans la \meta{liste}
% certaines choses, qui ne sont pas gérées correctement par
% \pf{xkeyval}. Précisément, il s'agit des signes |#| (les lexèmes de
% \cs{catcode} $6$) et des lexèmes \cs{par}. Aussi, aucune composante
% de la \meta{liste} ne doit avoir l'air mal équilibrée en \cs{if}s aux
% yeux de \TeX. Seule la première de ces limitations est partagée pas le
% \cs{newcommand} standard, qui n'accepte pas non plus de |#| dans les
% valeurs par défaut. Autrement, vous pouvez utiliser ce que vous
% voulez, où vous voulez (autant que je sache).
%
% Maintenant les bonnes nouvelles. J'ai pris grand soin que les macros
% définies avec \pf{xargs} ressemblent autant que possibles à celles
% définies avec les commandes standard de \LaTeX. En fait, quand on
% demande à \cs{newcommandx} d'effectuer une définition que
% \cs{newcommand} aurait pu faire, la commande sera définie exactement
% comme si on avait utilisé ce dernier. Plus précisément, le code
% suivant (et les tests similaires) ne renvoie pas d'avertissement.
%
% \begin{quote}
% |\newcommandx\truc[2][1=default]{def-truc}|\\
% |\CheckCommand\truc[2][default]{def-truc}|\\
% |\newcommand\chose{def-chose}|\\
% |\CheckCommandx*\chose[0][addprefix=\long]{def-chose}|
% \end{quote}
%
% De plus, il y a seulement trois points (à ma connaissance) sur
% lesquels les commandes d'\pf{xargs} diffèrent de celles de \LaTeX{}.
% Le premier a déjà été évoqué, c'est la limitation sur le \meta{liste}
% due à \pf{xkeyval}. Les deuxièmes et troisièmes points, par contre,
% sont censés être positifs. Le deuxième est donc, que j'ai essayé
% d'éviter de reproduire dans \cs{CheckCommandx} deux
% problèmes\footnote{%
% \url{http://www.latex-project.org/cgi-bin/ltxbugs2html?pr=latex/3971}}
% dont souffre l'implémentation actuelle de \cs{CheckCommand} dans
% \LaTeX.
%
% Le dernier point concerne la gestion des espaces, lors de la recherche
% du prochain caractère, pour déterminer s'il s'agit ou non d'un crocher
% carré, quand on teste la présence d'un argument optionnel. Pour ceci,
% je n'utilise ni la version du noyau, ni celle d'\pf{amsmath}, de
% \cs{@ifnextchar}, mais la mienne, qui a le comportement suivant : elle
% avale les espaces jusqu'à trouver le prochain caractère, puis les
% restitue si ce n'était pas le début d'un argument optionnel. Je ne
% suis plus tout à fait sûr que ce soit la bonne façon de faire, et il
% est probable que je ferai une option à ce sujet dans une prochaine
% version, afin que l'utilisateur puisse choisir son comportement
% préféré.
%
% \bigskip
%
% \begin{quote}
% Vous savez maintenant absolument tout ce qu'il y a à savoir sur
% l'utilisation de \pf{xargs}. Si vous souhaitez vous pencher sur son
% implémentation, il vous faudra lire les commentaires en anglais car je
% n'ai pas eu le courage de commenter mon code en deux langues.
% \end{quote}
%
% \begin{center}\large
% C'est tout pour cette fois ! \\
% Amusez-vous bien avec \LaTeX{} !
% \end{center}
%
% \else
%
% \subsection{Basics}
%
% ^^A \DescribeMacro{\newcommandx}
% ^^A \DescribeMacro{\renewcommandx}
% ^^A \DescribeMacro{\newenvironmentx}
% ^^A \DescribeMacro{\renewenvironmentx}
% ^^A \DescribeMacro{\providecommandx}
% ^^A \DescribeMacro{\DeclareRobustCommandx}
% ^^A \DescribeMacro{\CheckCommandx}
% The \pf{xargs} package defines an extended variant for every \LaTeX{}
% macro related to macro definition. \pf{xargs}'s macro are named after
% their \LaTeX{} counterparts, just adding an |x| at end (see the list
% in the margin). Here is the complete list:
%
% \begin{center}
% \begin{tabular}{ll}
% \cs{newcommandx} & \cs{renewcommandx} \\
% \cs{newenvironmentx} & \cs{renewenvironmentx} \\
% \cs{providecommandx} & \cs{DeclareRobustCommandx} \\
% \cs{CheckCommandx}
% \end{tabular}
% \end{center}
%
% If you are not familiar with all of them, you can either just keep
% using the commands you already know, or check Lamport's book or the
% \LaTeX{} Companion (or any \LaTeXe{} manual) to learn the others.
%
% \medbreak
%
% Since these commands all share the same syntax, I'll always use
% \cs{newcommandx} in the following, but remember it works the same for
% all seven commands. (Of course, command about environments take one
% more argument, for the end definition.) Here is |\newcommandx|'s
% complete syntax.
%
% \begin{center}
% \cs{newcommandx}\optstar\marg{command}\oarg{number}\oarg{list}^^A
% \marg{definition}
% \end{center}
%
% Everything here is the same as the usual \cs{newcommand} syntax,
% except \meta{list}. Let's recall this briefly. The optional $*$ make
% \LaTeX{} define a ``short'' macro, that is a macro that won't accept a
% paragraph break (\cs{par} or an empty line) inside its argument; if
% you don't put it, the macro will be long. \meta{command} is any
% control sequence, and can but need not be enclosed in braces, as you
% like. The \meta{number} specifies how many arguments your macro will
% take (including optional ones): it should be a non-negative integer,
% and at most $9$. The macro's \meta{definition} is a balanced text,
% where every |#| sign must be followed by a number, thus representing
% an argument, or by another |#| sign. The two arguments \meta{number}
% and \meta{list} are optionals.
%
% \medskip
%
% Now comes the new and funny part. \meta{list} is a coma-separated list
% of element \meta{digit}=\meta{value}. Here, \meta{digit} should be
% non-zero, and at most \meta{number} (the total number of arguments).
% The \meta{value} is any balanced text, and can be empty. If so, the
% |=| sign becomes optional: You only need to write \meta{digit} if you
% want the \meta{digit}th argument to be optional, with empty default
% value. Of course, every argument whose number is a \meta{digit} in the
% \meta{list} becomes optional, with \meta{value} as its default value.
%
% If you are not very familiar with some aspects of the syntax provided
% by the \pf{xkeyval} package, you may be interested in the following
% remarks about the syntax of \meta{list}. Since \meta{list} is
% coma-separated, if you want to use a coma inside a \meta{value}, you
% need to enclose it (either the coma or the whole \meta{value}) in
% braces. The same applies if you want to use a closing square bracket
% inside the \meta{list}. Don't worry about those unwanted braces, they
% will be removed later. Actually, \pf{xkeyval} removes up to $3$ braces
% set: If you really want braces around a value, you need to type
% something like |1={{{{\large stuff}}}}|.
%
% \medskip
%
% That's all for the basics: you are now ready to use \pf{xargs}, and
% can stop reading this doc now if you want. If, however, you are
% wondering about what happens if you have many successive optional
% arguments, or care about doing global definitions, or even need to
% know precisely the limitations of \pf{xargs}, go on with the next
% subsections.
%
% \subsection{The \texttt{usedefault} key}
%
% So, what happens with many successive optional arguments? The default
% behaviour is that of \LaTeX's commands like \cs{makebox} or
% \cs{parbox}: you can't specify the third argument if you didn't
% specify the first two ones. For example, in my first example, please
% notice how I used the mandatory argument to separate the two optional
% ones.
%
% However, maybe you don't like this and prefer choosing your argument's
% order as you want, according to their logical meaning. Ok. That's
% exactly what the |usedefault| key is for. Just include it in the
% \meta{list}, and you can now use |[]| to skip one optional argument
% (using its default value) and go to the next one.
%
% \begin{center}
% |\newcommandx*\coord[3][2=1,3=n,usedefault]{(#2_{#1},\ldots,#2_{#3})}|
% \newcommandx*\coord[3][2=1, 3=n, usedefault]{(#2_{#1},\ldots,#2_{#3})}
% \par\medskip
% \begin{tabular}{ll}
% |$\coord{x}$| & $\coord{x}$ \\
% |$\coord{y}[0]$| & $\coord{y}[0]$ \\
% |$\coord{z}[][m]$| & $\coord{z}[][m]$ \\
% |$\coord{t}[0][m]$| & $\coord{t}[0][m]$ \\
% \end{tabular}
% \end{center}
%
% Of course, on this simple example, this is merely a matter of
% taste, but sometimes the |usedefault| key can save you a lot of
% typing, since the optional value for an argument can be rather long,
% and you don't always have enough mandatory arguments to separate the
% optional ones.
%
% This simple way of using |usedefault| has one problem: you can no more
% specify an empty value for an optional argument. Of course you need a
% special value of the argument to mean ``please use the default value
% there'', but it doesn't need to be always the empty string. Actually,
% you can say |usedefaut=|\meta{flag} to choose this special value. The
% following example has no other purpose that illustrating this.
%
% \begin{center}
% |\newcommandx*\test[2][1=A, 2=B, usedefault=@]{(#1,#2)}|
% \newcommandx*\test[2][1=A, 2=B, usedefault=@]{(#1,#2)}
% \par\medskip
% \begin{tabular}{ll}
% |\test[b]| & \test[b] \\
% |\test[][b]| & \test[][b] \\
% |\test[@][b]| & \test[@][b] \\
% \end{tabular}
% \end{center}
%
% \subsection{Using a prefix}
%
% Standard |\newcommand| allows you to define so-called ``long'' (i. e.
% the arguments may contain a \cs{par} token) or ``short'' (they
% may not) macros with the optional star. This is part of what \TeX{}
% calls a ``prefix'' for the definition, namely the \cs{long} prefix.
% Other components of the prefix are \cs{global}, \cs{outer}, and
% \eTeX's \cs{protected}. There is no way to use them with
% |\newcommand|, though \cs{global} can be specially interesting in
% order to avoid definitions made inside a group (e. g. an environment)
% ``disappear'' at the end of the group. (For details about the other
% possible components, see the \TeX book and \eTeX's manual.)
%
% With \pf{xargs}, you can use the |addprefix| key, \emph{except} for
% the \cs{outer} prefix, which is not and will not be supported (and not
% used anywhere I know in \LaTeXe, either). Please note that it
% \emph{adds} a prefix to the current one, which by default is \cs{long}
% for the unstarred form, and empty for the starred form. You can also
% use this key many times: all prefixes will be merged together. For
% example, the following two instructions do the exactly the same thing.
%
% \begin{quote}
% |\newcommandx*\foo[0][addprefix=\global, addprefix=\long,|\\
% | addprefix=\protected]{bar}|\\
% |\newcommandx\foo[0][addprefix=\global\protected]{bar}|
% \end{quote}
%
% By the way, macros with at least one optional argument are already
% robust in \LaTeXe's meaning of the word, so I don't know if the
% \cs{protected} prefix is very interesting there. Maybe the ability to
% perform global definitions is the main use of the |addprefix| key.
%
% \subsection{Compatibility and known limitations}
%
% Okay, let's see the bad things (the limitations) first. There is
% essentially one: you cannot use in the \meta{list} some elements,
% because \pf{xkeyval} won't handle them properly. Namely, hash signs
% (tokens with \cs{catcode} $6$), and \cs{par} tokens are forbidden, and
% any part of the list should look properly \cs{if}-balanced to \TeX.
% Only the first limitation is shared by the standard \cs{newcommand}:
% it accepts no hash signs in a default value. Apart from this, you can
% use anything you want, everywhere you want, as far as I know.
%
% Now the ``good'' features. I've tried hard to make macros defined with
% \pf{xargs} as much similar as possible with those defined with
% standard \LaTeX's commands. Actually, when \cs{newcommandx} is asked
% to perform a definition which \cs{newcommand} can do, the resulting
% macro will be defined exactly as the latter would have done. More
% precisely, the following code (and similar tests) issues no warning.
%
% \begin{quote}
% |\newcommandx\foo[2][1=default]{def-foo}|\\
% |\CheckCommand\foo[2][default]{def-foo}|\\
% |\newcommand\baz{def-baz}|\\
% |\CheckCommandx*\baz[0][addprefix=\long]{def-baz}|
% \end{quote}
%
% Moreover, there are only three points (to my knowledge) where
% \pf{xargs}'s commands differ from the kernel ones. The first one was
% already mentioned, it is due to using \pf{xkeyval} for precessing the
% \meta{list}. The second and third points are meant to be good one.
% Second point is: There is a bug\footnote{%
% \url{http://www.latex-project.org/cgi-bin/ltxbugs2html?pr=latex/3971}}
% in the current implementation of \cs{CheckCommand}, that I obviously
% tried to avoid.
%
% Last, I don't use kernel's (nor \pf{amsmath}'s) version of
% \cs{@ifnextchar}. Indeed, a problem arises when the last argument of a
% command is optional: we have to make a choice about what to do with
% spaces while scanning ahead for a left square bracket. I chose to scan
% over them, and the put them back in the text in there were no
% optional argument. I'm no more sure it is the right thing to do, and
% I'll probably make an option to let the user decide in a future
% version.
%
% \fi
%
% \StopEventually{}
%
% \section{Implementation}
%
% First, I'd like to recall the way \LaTeXe{} handles optional
% arguments. For example, a command \cs{foo} defined with
% |\newcommand*\foo[2][bar]{baz}| is implemented as the pair:
% \begin{quote}
% |\foo=macro:->\@protected@testopt\foo\\foo{bar}| \\
% |\\foo=macro:[#1]#2->baz|
% \end{quote}
% There is one ``external'' macro \cs{foo}, which is merely an argument
% grabber or a parser, and an internal macro \cs{\string\foo}, which is
% the ``real'' one. In \pf{xargs} this is quite the same, except that
% the external macro is a bit more sophisticated. This idea of the
% external macro being a parser, giving the arguments to the internal
% one in a standard form, reflects in the name of \LaTeX3's experimental
% package for extended argument syntax: \pf{xparse}.
%
% Here the approach is a bit different. Of course, the idea is still to
% build a parser for the specified syntax, but since \cs{newcommandx}
% user syntax is based on \pf{xkeyval}, we also have to care about keys
% and there default values, and to put the whole thing in the correct
% order before we build up the parser. We also seek for compatibility
% with existing \LaTeXe{} commands, which adds a few tests. The
% organisation is as follows.
%
% \begingroup \def\leaders#1#2{}
% \secttoc[n]
% \endgroup
%
% Before we really begin, just a few preliminaries.
% First, load the \pf{xkeyval} package for it's nice key=value syntax.
% \begin{macrocode}
\RequirePackage{xkeyval}
% \end{macrocode}
%
% \begin{macro}{\xargs@max}
% \begin{macro}{\xargs@temp}
% \begin{macro}{\xargs@toksa}
% \begin{macro}{\xargs@toksb}
% Then allocate a few registers and make sure the name of our private scratch
% macro is free for use. Note that for certain uses, we really need a
% \cs{toks} register because the string used can possibly contain |#|
% characters. Sometimes I also use a \cs{toks} register instead of a macro
% just for ease of use (writing less \cs{expandafter}s).
% \begin{macrocode}
\@ifdefinable\xargs@max{\newcount\xargs@max}
% \end{macrocode}
% \begin{macrocode}
\@ifdefinable\xargs@temp\relax
\@ifdefinable\xargs@toksa{\newtoks\xargs@toksa}
\@ifdefinable\xargs@toksb{\newtoks\xargs@toksb}
% \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \subsection{Parser}
%
% Let's begin with a simple, concrete example. Recall that we defined a
% command \cs{vect} with
% |\newcommandx\vect[3]{1=0,3=n}{(#2_{#1},\ldots,#2_{#3}}| and have a
% look at its implementation.
% \begin{quote}
% |\vect=macro:->\@protected@testopt@xargs\vect\\vect|\\
% \hspace*{1em}|{\xargs@test@opt{0},\xargs@put@arg,\xargs@test@opt{n},}|\\
% |\\vect=macro:[#1]#2[#3]->(#2_{#1},\ldots ,#2_{#3})|
% \end{quote}
%
% As you can see, the parser is stored as a coma-separated list of
% ``actions''. Here the only actions are to grab a mandatory argument or
% to check for the presence of of an optional one. In this case, special
% care is taken about spaces. Actually, there can be one more action,
% associated with the |usedefaut| user key: \cs{xargs@setdefflag}, which
% specifies the flag that says ``use the default value''.
%
% The parsing is done by a loop that read and executes each action from
% the originating list, and concurrently builds an argument list such as
% |[0]{x}[m]| to be passed to |\\vect| for example. All of this happens
% inside a group.
%
% \begin{macro}{\@protected@testop@xargs}
% This first macro closely resembles kernel's \cs{@protected@testopt}
% (similarity in their names is intentional, see \cs{CheckCommandx}). It
% just checks the protection context and call the real argument grabbing
% macro.
% \begin{macrocode}
\newcommand*\@protected@testopt@xargs[1]{%
\ifx\protect\@typeset@protect
\expandafter\xargs@read
\else
\@x@protect#1%
\fi}
% \end{macrocode}
% \end{macro}
% \begin{macro}{\xargs@read}
% Initiate the loop. \cs{xargs@toksa} will become the call to the
% internal macro with all arguments, \cs{xargs@toksb} contains the
% actions list for arguments grabbing.
% \begin{macrocode}
\newcommand*\xargs@read[2]{%
\begingroup
\xargs@toksa{#1}%
\xargs@toksb{#2}%
\xargs@continue}
% \end{macrocode}
% \end{macro}
% \begin{macro}{\xargs@continue}
% \begin{macro}{\xargs@pick@next}
% Each iteration of the loop consist of two steps: pick the next action
% (and remove it from the list), and execute it. When there is no more
% action in the list, it means the arguments grabbing stage is over, and
% it's time to execute the internal macro by expanding the contents of
% \cs{xargs@toksa}.
% \begin{macrocode}
\newcommand\xargs@continue{%
\expandafter\xargs@pick@next\the\xargs@toksb,\@nil
\xargs@temp}
% \end{macrocode}
% \begin{macrocode}
\@ifdefinable\xargs@pick@next{%
\def\xargs@pick@next#1,#2\@nil{%
\def\xargs@temp{#1}%
\xargs@toksb{#2}%
\ifx\xargs@temp\empty
\def\xargs@temp{\expandafter\endgroup\the\xargs@toksa}%
\fi}}
% \end{macrocode}
% \end{macro}
% \end{macro}
% \begin{macro}{\xargs@set@defflag}
% Let's begin with the most simple action.
% \begin{macrocode}
\newcommand*\xargs@set@defflag[1]{%
\def\xargs@default@flag{#1}}
% \end{macrocode}
% \end{macro}
% \begin{macro}{\xargs@put@arg}
% \begin{macro}{\xargs@test@opt}
% \begin{macro}{\xargs@put@opt}
% Now have a look at the argument grabbing macros. The first one,
% \cs{xargs@put@arg}, just reads an undelimited argument in the input stack
% and add it to the arguments list. \cs{xargs@testopt} checks if the next
% non-space token is a square bracket to decide if it have to read an argument
% from the input or use the default value, and takes care to enclose it in
% square brackets.
% \begin{macrocode}
\newcommand\xargs@put@arg[1]{%
\xargs@toksa\expandafter{\the\xargs@toksa{#1}}%
\xargs@continue}
% \end{macrocode}
% \begin{macrocode}
\newcommand*\xargs@test@opt[1]{%
\xargs@ifnextchar[%]
{\xargs@grab@opt{#1}}%
{\xargs@put@opt{#1}}}
% \end{macrocode}
% \begin{macrocode}
\newcommand\xargs@put@opt[1]{%
\xargs@toksa\expandafter{\the\xargs@toksa[{#1}]}%
\xargs@continue}
% \end{macrocode}
% \begin{macrocode}
\@ifdefinable\xargs@grab@opt{%
\long\def\xargs@grab@opt#1[#2]{%
\toks@{#2}\edef\xargs@temp{\the\toks@}%
\ifx\xargs@temp\xargs@default@flag
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi{%
\xargs@put@opt{#1}%
}{%
\xargs@put@opt{#2}}}}
% \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \begin{macro}{\xargs@ifnextchar}
% \begin{macro}{\xargs@ifnch}
% \begin{macro}{\xargs@xifnch}
% Here comes a modified version of \cs{@ifnextchar}, that works like
% kernel's one, except that it remembers how many spaces it gobbles and
% puts them back in case the next non-space character isn't a match. Not
% sure whether this is the better way to do, may change in future
% versions.
% \begin{macrocode}
\newcommand\xargs@ifnextchar[3]{%
\let\xargs@temp\empty
\let\reserved@d=#1%
\def\reserved@a{#2}%
\def\reserved@b{#3}%
\futurelet\@let@token\xargs@ifnch}
% \end{macrocode}
% \begin{macrocode}
\newcommand\xargs@ifnch{%
\ifx\@let@token\@sptoken
\edef\xargs@temp{\xargs@temp\space}%
\let\reserved@c\xargs@xifnch
\else
\ifx\@let@token\reserved@d
\let\reserved@c\reserved@a
\else
\def\reserved@c{\expandafter\reserved@b\xargs@temp}%
\fi
\fi
\reserved@c}
% \end{macrocode}
% \begin{macrocode}
\@ifdefinable\xargs@xifnch{%
\expandafter\def\expandafter\xargs@xifnch\space{%
\futurelet\@let@token\xargs@ifnch}}
% \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \subsection{Keys}
%
% Okay, we are done with the parsing related macros. Now define stuff
% for the definition of macros. In this part we use \pf{xkeyval}. Let's
% start with the particular keys for options |addprefix| and |default|.
% Like all \pf{xargs} key, we use the prefix |xargs| and the familly
% |key|. The |addprefix| key can be used many times : each value is
% appended at the end of the current prefix. Actually, we also construct
% a ``short'' prefix (without any \cs{long}), for the external macro. We
% define them globally, since key processing will happen inside a group,
% and the definition outside.
% \begin{macrocode}
\@ifdefinable\xargs@key@addprefix{%
\define@key[xargs]{key}{addprefix}[]{%
\global\expandafter\def\expandafter\xargs@prefix\expandafter{%
\xargs@prefix#1}%
\xargs@makeshort#1\long\@nil}}
% \end{macrocode}
% The \cs{long} tokens are removed from the prefix in a fast and easy
% way, assuming the input is a correct prefix. (It will crash e.g. if
% the input contains an undefined CS or braces, but this will make all
% crash later anyway. By the way, we also assume the prefix contains no
% macro parameter token\ldots)
% \begin{macrocode}
\@ifdefinable\xargs@makeshort{%
\def\xargs@makeshort#1\long#2{%
\expandafter\gdef\expandafter\xargs@shortpref\expandafter{%
\xargs@shortpref#1}%
\ifx#2\@nil \else
\expandafter\xargs@makeshort\expandafter#2%
\fi}}
% \end{macrocode}
% The initial prefixes will be fixed by \cs{newcommandx} and its friends
% when they check the star: empty in the stared version, \cs{long}
% otherwise. For this, they use \pf{xargs}'s variant or
% \cs{@star@or@long}:
% \begin{macrocode}
\newcommand\xargs@star@or@long[1]{%
\global\let\xargs@shortpref\@empty
\@ifstar{\gdef\xargs@prefix{}#1}{\gdef\xargs@prefix{\long}#1}}
% \end{macrocode}
%
% Now, another particular key is the |usedefault| key. When used, it
% just sets \cs{xargs@default@flag} and the corresponding boolean. Later
% on, this will be used to possibly introduce a \cs{xargs@set@default}
% action at the beginning of the actions list.
% \begin{macrocode}
\define@key[xargs]{key}{usedefault}[]{%
\xargs@toksa{#1}\edef\xargs@default@flag{\the\xargs@toksa}}
% \end{macrocode}
%
% \medskip
%
% Let's continue with the more important keys. We have to collect
% through \pf{xkeyval} at most 9 actions numbered 1 to \cs{xargs@max}
% (the total number of arguments), each of them being
% \cs{xargs@test@opt} or \cs{xargs@put@arg}. Latter, we will use them to
% build up the parser.
%
% \begin{macro}{\@namenewc} \begin{macro}{\xargs@action@1}
% \begin{macro}{\xargs@action@2} \begin{macro}{\xargs@action@3}
% \begin{macro}{\xargs@action@4} \begin{macro}{\xargs@action@5}
% \begin{macro}{\xargs@action@6} \begin{macro}{\xargs@action@7}
% \begin{macro}{\xargs@action@8} \begin{macro}{\xargs@action@9}
% So our first task is to define container macros for the at most nine
% actions which represent arguments parsing, with default value
% \cs{xargs@put@arg} since every argument is mandatory unless specified.
% \begin{macrocode}
\providecommand\@namenewc[1]{%
\expandafter\newcommand\csname #1\endcsname}
% \end{macrocode}
% \begin{macrocode}
\@namenewc{xargs@action@1}{\xargs@put@arg}
\@namenewc{xargs@action@2}{\xargs@put@arg}
\@namenewc{xargs@action@3}{\xargs@put@arg}
\@namenewc{xargs@action@4}{\xargs@put@arg}
\@namenewc{xargs@action@5}{\xargs@put@arg}
\@namenewc{xargs@action@6}{\xargs@put@arg}
\@namenewc{xargs@action@7}{\xargs@put@arg}
\@namenewc{xargs@action@8}{\xargs@put@arg}
\@namenewc{xargs@action@9}{\xargs@put@arg}
% \end{macrocode}
% \end{macro} \end{macro}
% \end{macro} \end{macro}
% \end{macro} \end{macro}
% \end{macro} \end{macro}
% \end{macro} \end{macro}
% \begin{macro}{\xargs@def@key}
% The next macro will define the keys. Its first argument is the key's
% number. The second argument will be discussed later.
% \begin{macrocode}
\newcommand*\xargs@def@key[2]{%
\expandafter\@ifdefinable\csname xargs@key@#1\endcsname{%
\define@key[xargs]{key}{#1}[]{%
% \end{macrocode}
% The first thing do to, before setting any action, is to check whether
% this key can be used for this command, and complain if not.
% \begin{macrocode}
\ifnum\xargs@max<#1
\PackageError{xargs}{%
Illegal argument label in\MessageBreak
optional arguments description%
}{%
You are trying to make optional an argument whose label (#1)
\MessageBreak is higher than the total number (\the\xargs@max)
of parameters. \MessageBreak This can't be done and your
demand will be ignored.}%
\else
% \end{macrocode}
% If the key number is correct, it may be that the user is trying to use
% it twice for the same command. Since it's probably a mistake, issue a
% warning in such case.
% \begin{macrocode}
\expandafter\expandafter\expandafter
\ifx\csname xargs@action@#1\endcsname\xargs@put@arg \else
\PackageWarning{xargs}{%
Argument #1 was allready given a default value.\MessageBreak
Previous value will be overriden.\MessageBreak}%
\fi
% \end{macrocode}
% If everything looks okay, define the action to be \cs{xargs@test@opt}
% with the given value, and execute the (for now) mysterious second
% argument.
% \begin{macrocode}
\@namedef{xargs@action@#1}{\xargs@test@opt{##1}}%
#2%
\fi}}}
% \end{macrocode}
% \end{macro}
% \begin{macro}{\ifxargs@firstopt@}
% \begin{macro}{\ifxargs@otheropt@}
% \begin{macro}{\xargs@key@1}
% \begin{macro}{\xargs@key@2} \begin{macro}{\xargs@key@3}
% \begin{macro}{\xargs@key@4} \begin{macro}{\xargs@key@5}
% \begin{macro}{\xargs@key@6} \begin{macro}{\xargs@key@7}
% \begin{macro}{\xargs@key@8} \begin{macro}{\xargs@key@9}
% The second argument is used to set the value for some \cs{if} which
% will keep track of the existence of an optional argument other than
% the first one, and the of the possibly optional nature of the first.
% Such information will be useful when we will have to decide if we use
% the \LaTeXe{} standard way or \pf{xargs} custom one to define the
% macro.
% \begin{macrocode}
\newif\ifxargs@firstopt@
\newif\ifxargs@otheropt@
% \end{macrocode}
% Now actually define the keys.
% \begin{macrocode}
\xargs@def@key1\xargs@firstopt@true
\xargs@def@key2\xargs@otheropt@true \xargs@def@key3\xargs@otheropt@true
\xargs@def@key4\xargs@otheropt@true \xargs@def@key5\xargs@otheropt@true
\xargs@def@key6\xargs@otheropt@true \xargs@def@key7\xargs@otheropt@true
\xargs@def@key8\xargs@otheropt@true \xargs@def@key9\xargs@otheropt@true
% \end{macrocode}
% \end{macro} \end{macro} \end{macro}
% \end{macro} \end{macro} \end{macro}
% \end{macro} \end{macro} \end{macro}
% \end{macro} \end{macro}
% \begin{macro}{\xargs@setkeys}
% \begin{macro}{\xargs@check@keys}
% We set the keys with the starred version of \cs{setkeys}, so we can
% check if there were some strange keys we cannot handle, and issue a
% meaningful warning if there are some.
% \begin{macrocode}
\newcommand\xargs@setkeys[1]{%
\setkeys*[xargs]{key}{#1}%
\xargs@check@keys}
% \end{macrocode}
% \begin{macrocode}
\newcommand\xargs@check@keys{%
\ifx\XKV@rm\empty \else
\xargs@toksa\expandafter{\XKV@rm}%
\PackageError{xargs}{%
Illegal key or argument label in\MessageBreak
optional arguments description%
}{%
You can only use non-zero digits as argument labels.\MessageBreak
Other allowed keys are usedefault and addprefix.\MessageBreak
You wrote: "\the\xargs@toksa".\MessageBreak
I can't understand this and I'm going to ignore it.}%
\fi}
% \end{macrocode}
% \end{macro}
% \end{macro}
%
% \subsection{Definition}
%
% \begin{macro}{\xargs@add@args}
% Now our goal is to build two lists from our up to nine argument
% grabbers, the special action |\xargs@setdefflag| and not forgetting
% the prefix. The first list is the coma-separated list of actions
% already discussed. The second is the parameter text for use in the
% definition on the internal macro, for example |[#1]#2[#3]|. The next
% macro takes the content of a \cs{xargs@action@X} macro for argument
% and adds the corresponding items to this lists. It checks if the first
% token of its parameter is \cs{xargs@testopt} in order to know if the
% |#n| has to be enclosed in square brackets.
% \begin{macrocode}
\newcommand\xargs@add@args[1]{%
\xargs@toksa\expandafter{\the\xargs@toksa #1,}%
\expandafter
\ifx\@car#1\@nil\xargs@put@arg
\xargs@toksb\expandafter\expandafter\expandafter{%
\the\expandafter\xargs@toksb\expandafter##\the\count@}%
\else
\xargs@toksb\expandafter\expandafter\expandafter{%
\the\expandafter\xargs@toksb\expandafter
[\expandafter##\the\count@]}%
\fi}
% \end{macrocode}
% \end{macro}
% \begin{macro}{\xargs@process@keys}
% Here comes the main input processing macro, which prepares the
% information needed to define the final macro, and expands it to the
% defining macro.
% \begin{macrocode}
\@ifdefinable\xargs@process@keys{%
\long\def\xargs@process@keys#1[#2]{%
% \end{macrocode}
% Some initialisations. We work inside a group so that the default
% values for the \cs{xargs@action@X} macros and the \cs{xargs@XXXopt@}
% be automatically restored for the next time.
% \begin{macrocode}
\begingroup
\xargs@setkeys{#2}%
\xargs@toksa{}\xargs@toksb{}%
% \end{macrocode}
% Let's begin with the |usedefault| part.
% \begin{macrocode}
\@ifundefined{xargs@default@flag}{}{%
\xargs@toksa\expandafter{%
\expandafter\xargs@set@defflag\expandafter{%
\xargs@default@flag}}}
% \end{macrocode}
% Then the main loop actually builds up the two lists in the correct
% order.
% \begin{macrocode}
\count@\z@
\@whilenum\xargs@max>\count@ \do{%
\advance\count@\@ne
\expandafter\expandafter\expandafter\xargs@add@args
\expandafter\expandafter\expandafter{%
\csname xargs@action@\the\count@\endcsname}}%
% \end{macrocode}
% Then we need to address a special case: if only the first argument is
% optional, we use \LaTeXe's standard \cs{newcommand} construct, and we
% dont need an actions list like the one just build, but only the
% default value for the first argument. In this case, we extract this
% value from \cs{xargs@action@1} by expanding it two times with a
% modified \cs{xargs@testopt} (and one more expansion step for the
% |\csname| gives $3$, hence the $2^3-1 = 7$ \cs{expandafter}s).
% \begin{macrocode}
\ifxargs@otheropt@ \else
\ifxargs@firstopt@
\let\xargs@test@opt\@firstofone
\xargs@toksa\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\expandafter{%
\csname xargs@action@1\endcsname}%
\fi
\fi
% \end{macrocode}
% Finally expand the stuff to the next macro and, while we're at it,
% choose the next macro : depending of the existence and place of an
% optional argument, use \LaTeX's or \pf{xargs}'s way. In the \LaTeX{}
% case, however, we don't use \cs{@argdef} or \cs{xargdef} since we want
% to be able to use a prefix (and we have more work done allready, too).
% \begin{macrocode}
\edef\xargs@temp{%
\ifxargs@otheropt@ \noexpand\xargs@xargsdef \else
\ifxargs@firstopt@ \noexpand\xargs@xargdef \else
\noexpand\xargs@argdef
\fi\fi
\noexpand#1%
\expandafter\noexpand\csname\string#1\endcsname
{\the\xargs@toksa}{\the\xargs@toksb}}%
% \end{macrocode}
% Now we can close the group and forget all about key values, etc. Time
% to conclude and actually define the macro. (The only thing not passed
% as an argument is the prefix, which is globally set.) We also take
% care to execute \cs{xargs@drc@hook} just outside the group.
% \begin{macrocode}
\expandafter\endgroup
\expandafter\xargs@drc@hook
\xargs@temp}}
% \end{macrocode}
% \end{macro}
% \begin{macro}{\xargs@argdef}
% \begin{macro}{\xargs@xargdef}
% \begin{macro}{\xargs@xargsdef}
% The first two next macros are modified versions of kernel's
% \cs{@argdef} and \cs{@xargdef}, that do the same work, but use the
% prefix we built, and also are simpler since they get the internal name
% as an argument. The last one is the only new macro.
% \begin{macrocode}
\newcommand\xargs@argdef[5]{%
\@ifdefinable#1{%
\xargs@prefix\def#1#4{#5}}}
% \end{macrocode}
% \begin{macrocode}
\newcommand\xargs@xargdef[5]{%
\@ifdefinable#1{%
\xargs@shortpref\def#1{\@protected@testopt#1#2{#3}}%
\xargs@prefix\def#2#4{#5}}}
% \end{macrocode}
% \begin{macrocode}
\newcommand\xargs@xargsdef[5]{%
\@ifdefinable#1{%
\xargs@shortpref\def#1{\@protected@testopt@xargs#1#2{#3}}%
\xargs@prefix\def#2#4{#5}}}
% \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \subsection{User macros}
%
% \begin{macro}{\newcommandx}
% \begin{macro}{\xargs@newc}
% All the internal macros are ready. It's time to define the user
% commands, beginning with \cs{newcommandx}. Like its standard version,
% it just checks the star and call the next macro wich grabs the number
% of arguments.
% \begin{macrocode}
\newcommand\newcommandx{%
\xargs@star@or@long\xargs@newc}
% \end{macrocode}
% \begin{macrocode}
\newcommand*\xargs@newc[1]{%
\@testopt{\xargs@set@max{#1}}{0}}
% \end{macrocode}
% \end{macro}
% \end{macro}
% \begin{macro}{\xargs@set@max}
% Set the value of \cs{xargs@max}. If no optional arguments description
% follows, simply call \cs{argdef} because all the complicated stuff is
% useless here.
% \begin{macrocode}
\@ifdefinable\xargs@set@max{%
\def\xargs@set@max#1[#2]{%
\kernel@ifnextchar[%]
{\xargs@max=#2 \xargs@check@max{#1}}%
{\@argdef#1[#2]}}}
% \end{macrocode}
% \end{macro}
% \begin{macro}{\xargs@check@max}
% To avoid possible problems later, check right now that \cs{xargs@max}
% value is valid. If not, warn the user and treat this value as zero.
% Then begin the key processing.
% \begin{macrocode}
\newcommand\xargs@check@max{%
\ifcase\xargs@max \or\or\or\or\or\or\or\or\or\else
\PackageError{xargs}{Illegal number, treated as zero}{The total
number of arguments must be in the 0..9 range.\MessageBreak
Since your value is illegal, i'm going to use 0 instead.}
\xargs@max0
\fi
\xargs@process@keys}
% \end{macrocode}
% \end{macro}
%
% \medskip
%
% The other macros (\cs{renewcommandx} etc.) closely resemble their kernel
% homologues, since they are mostly wrappers around some call to
% \cs{xargs@newc}. There is however two exceptions: \cs{CheckCommand}
% and \cs{DeclareRobustCommandx}. Indeed, the current implementation of
% \cs{CheckCommand} in the kernel suffers from two bugs (see
% \href{http://www.latex-project.org/cgi-bin/ltxbugs2html?pr=latex/3971}
% {PR/3971}) which I'm trying to avoid. For \cs{DeclareRobustCommandx},
% the problem is to handle the prefix correctly: for that we use a hook,
% in order to delay the external macro's definition until we get the
% prefix right. So, let's see those two commands first.
%
% \begin{macro}{\CheckCommandx}
% We begin as usual detecting the possible star.
% \begin{macrocode}
\newcommand\CheckCommandx{%
\xargs@star@or@long\xargs@CheckC}
\@onlypreamble\CheckCommandx
% \end{macrocode}
% \end{macro}
% \begin{macro}{\xargs@CheckC}
% \begin{macro}{\xargs@check@a}
% \begin{macro}{\xargs@check@b}
% First, we don't use the |#2#| trick from the kernel, since it can fail
% if there are braces in the default values. Instead, we follow the
% argument grabing method used for \cs{new@environment}, ie calling
% \cs{kernel@ifnextchar} explicitly.
% \begin{macrocode}
\newcommand\xargs@CheckC[1]{%
\@testopt{\xargs@check@a#1}0}
\@onlypreamble\xargs@CheckC
% \end{macrocode}
% \begin{macrocode}
\@ifdefinable\xargs@check@a{%
\def\xargs@check@a#1[#2]{%
\kernel@ifnextchar[%]
{\xargs@check@b#1[#2]}%
{\xargs@check@c#1{[#2]}}}}
\@onlypreamble\xargs@check@a
% \end{macrocode}
% \begin{macrocode}
\@ifdefinable\xargs@check@b{%
\def\xargs@check@b#1[#2][#3]{%
\xargs@check@c{#1}{[#2][{#3}]}}}
\@onlypreamble\xargs@check@b
% \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \begin{macro}{\xargs@CheckC}
% Here comes the major difference with the kernel version. If
% |\\reserved@a| is defined, we not only check that it is equal to
% |\\foo| (assuming \cs{foo} is the macro being tested), we also check
% that \cs{foo} makes something sensible, with \cs{xargs@check@d}.
% \begin{macrocode}
\newcommand\xargs@check@c[3]{%
\xargs@toksa{#1}%
\expandafter\let\csname\string\reserved@a\endcsname\relax
\xargs@renewc\reserved@a#2{#3}%
\@ifundefined{\string\reserved@a}{%
\ifx#1\reserved@a \else
\xargs@check@complain
\fi
}{%
\expandafter
\ifx\csname\string#1\expandafter\endcsname
\csname\string\reserved@a\endcsname
\xargs@check@d
\else
\xargs@check@complain
\fi}}
\@onlypreamble\xargs@check@c
% \end{macrocode}
% \end{macro}
% So, what do we want \cs{foo} to do? If |\\foo| is defined, \cs{foo}
% should begin with one of the followings:
% \begin{quote}
% |\@protected@testopt \foo \\foo| \\
% |\@protected@testopt@xargs \foo \\foo|
% \end{quote}
% Since I'm to lazy to really check this, the \cs{xargs@check@d} macro
% only checks if the \cs{meaning} of \cs{foo} begins with
% \cs{@protected@test@opt} (without a space after it). It does this
% using a macro with delimited argument. Here are preliminaries to this
% definition: We need to have this string in \cs{catcode} 12 tokens.
% \begin{macrocode}
\def\xargs@temp{\@protected@testopt}
\expandafter\xargs@toksa\expandafter{\meaning\xargs@temp}
\def\xargs@temp#1 {\def\xargs@temp{#1}}
\expandafter\xargs@temp\the\xargs@toksa
% \end{macrocode}
% \begin{macro}{\xargs@check@d}
% \begin{macro}{\xargs@check@e}
% Now, \cs{xargs@check@c} just pass the \cs{meaning} of the command
% \cs{foo} being checked to the allready mentionned macro with delimited
% arguments, which will check if its first argument is empty (ie, if
% \cs{foo}'s \cs{meaning} starts with what we want) and complain
% otherwise.
% \begin{macrocode}
\expandafter\newcommand\expandafter\xargs@check@d\expandafter{%
\expandafter\expandafter\expandafter\xargs@check@e
\expandafter\meaning\expandafter\reserved@a\xargs@temp\@nil}
\@onlypreamble\xargs@check@d
% \end{macrocode}
% \begin{macrocode}
\@ifdefinable\xargs@check@e{%
\expandafter\def\expandafter\xargs@check@e
\expandafter#\expandafter1\xargs@temp#2\@nil{%
\ifx\empty#1\empty \else
\xargs@check@complain
\fi}}
\@onlypreamble\xargs@check@e
% \end{macrocode}
% \end{macro}
% \end{macro}
% \begin{macro}{\xargs@check@complain}
% The complaining macro uses the name saved by \cs{xargs@check@c} in
% \cs{xargs@toksa} in order to complain about the correct macro.
% \begin{macrocode}
\newcommand\xargs@check@complain{%
\PackageWarningNoLine{xargs}{Command \the\xargs@toksa has changed.
\MessageBreak Check if current package is valid}}
\@onlypreamble\xargs@check@complain
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\DeclareRobustCommandx}
% \begin{macro}{\xargs@DRC}
% The \pf{xargs} version of \cs{DeclareRobustCommand}, and related
% internal macros.
% \begin{macrocode}
\newcommand\DeclareRobustCommandx{%
\xargs@star@or@long\xargs@DRC}
% \end{macrocode}
% \begin{macrocode}
\newcommand*\xargs@DRC[1]{%
\ifx#1\@undefined\else\ifx#1\relax\else
\PackageInfo{xargs}{Redefining \string#1}%
\fi\fi
\edef\reserved@a{\string#1}%
\def\reserved@b{#1}%
\edef\reserved@b{\expandafter\strip@prefix\meaning\reserved@b}%
% \end{macrocode}
% Here is the difference from kernel's code: instead of doing the
% definition of the user macro now, we just set the hook to do it
% latter, when the correct prefix will be set, then disable itself for
% next time.
% \begin{macrocode}
\edef\xargs@drc@hook{%
\noexpand\xargs@shortpref\def\noexpand#1{%
\ifx\reserved@a\reserved@b
\noexpand\x@protect
\noexpand#1%
\fi
\noexpand\protect
\expandafter\noexpand\csname
\expandafter\@gobble\string#1 \endcsname}%
\expandafter\let\noexpand\xargs@drc@hook\relax}%
\let\@ifdefinable\@rc@ifdefinable
\expandafter\xargs@newc\csname
\expandafter\@gobble\string#1 \endcsname}
% \end{macrocode}
% And finally set a default empty hook.
% \begin{macrocode}
\let\xargs@drc@hook\relax
% \end{macrocode}
% \end{macro}
% \end{macro}
%
% \medskip
%
% From now on, there is absolutely nothing to comment, since the next
% macros are mainly wrappers around \cs{xargs@newc}, just as kernel's
% ones are wrappers around \cs{new@command}. So the code below is only
% copy/paste with search\&replace from the kernel code.
%
% \begin{macro}{\renewcommandx}
% \begin{macro}{\xargs@renewc}
% The \pf{xargs} version of \cs{renewcommand}, and it's related internal
% macro.
% \begin{macrocode}
\newcommand\renewcommandx{%
\xargs@star@or@long\xargs@renewc}
% \end{macrocode}
% \begin{macrocode}
\newcommand*\xargs@renewc[1]{%
\begingroup\escapechar\m@ne
\xdef\@gtempa{{\string#1}}%
\endgroup
\expandafter\@ifundefined\@gtempa{%
\PackageError{xargs}{\noexpand#1undefined}{%
Try typing \space <return> \space to proceed.\MessageBreak
If that doesn't work, type \space X <return> \space to quit.}}%
\relax
\let\@ifdefinable\@rc@ifdefinable
\xargs@newc#1}
% \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\providecommandx}
% \begin{macro}{\xargs@providec}
% The \pf{xargs} version of \cs{providecommand}, and the related
% internal macro.
% \begin{macrocode}
\newcommand\providecommandx{%
\xargs@star@or@long\xargs@providec}
% \end{macrocode}
% \begin{macrocode}
\newcommand*\xargs@providec[1]{%
\begingroup\escapechar\m@ne
\xdef\@gtempa{{\string#1}}%
\endgroup
\expandafter\@ifundefined\@gtempa
{\def\reserved@a{\xargs@newc#1}}%
{\def\reserved@a{\renew@command\reserved@a}}%
\reserved@a}
% \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\newenvironment}
% \begin{macro}{\xargs@newenv}
% \begin{macro}{\xargs@newenva}
% \begin{macro}{\xargs@newenvb}
% \begin{macro}{\xargs@new@env}
% The \pf{xargs} version of \cs{newenvironment}, and related internal
% macros.
% \begin{macrocode}
\newcommand\newenvironmentx{%
\xargs@star@or@long\xargs@newenv}
% \end{macrocode}
% \begin{macrocode}
\newcommand*\xargs@newenv[1]{%
\@testopt{\xargs@newenva#1}0}
% \end{macrocode}
% \begin{macrocode}
\@ifdefinable\xargs@newenva{%
\def\xargs@newenva#1[#2]{%
\kernel@ifnextchar[%]
{\xargs@newenvb#1[#2]}%
{\xargs@new@env{#1}{[#2]}}}}
% \end{macrocode}
% \begin{macrocode}
\@ifdefinable\xargs@newenvb{%
\def\xargs@newenvb#1[#2][#3]{%
\xargs@new@env{#1}{[#2][{#3}]}}}
% \end{macrocode}
% \begin{macrocode}
\newcommand\xargs@new@env[4]{%
\@ifundefined{#1}{%
\expandafter\let\csname#1\expandafter\endcsname
\csname end#1\endcsname}%
\relax
\expandafter\xargs@newc
\csname #1\endcsname#2{#3}%
\xargs@shortpref\expandafter\def\csname end#1\endcsname{#4}}
% \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\renewenvironment}
% \begin{macro}{\xargs@renewenv}
% The \pf{xargs} version of \cs{renewenvironment}, and the related
% internal macro.
% \begin{macrocode}
\newcommand\renewenvironmentx{%
\xargs@star@or@long\xargs@renewenv}
% \end{macrocode}
% \begin{macrocode}
\newcommand*\xargs@renewenv[1]{%
\@ifundefined{#1}{%
\PackageError{xargs}{\noexpand#1undefined}{%
Try typing \space <return> \space to proceed.\MessageBreak
If that doesn't work, type \space X <return> \space to quit.}}%
\relax
\expandafter\let\csname#1\endcsname\relax
\expandafter\let\csname end#1\endcsname\relax
\xargs@newenv{#1}}
% \end{macrocode}
% \end{macro}
% \end{macro}
%
% \bigskip
% \begin{center}\Large
% That's all folks!\\
% Happy \TeX ing!
% \end{center}
%
% \Finale
%
% \iffalse
%</package>
%<*batchfile>
% \fi
% \typeout{**************************************************}
% \typeout{*}
% \typeout{* To finish the installation you have to move the}
% \typeout{* following file into a directory searched by TeX:}
% \typeout{*}
% \typeout{* \space\space\space\space xargs.sty}
% \typeout{*}
% \typeout{* Documentation is in xargs.dvi or xargs.pdf}
% \typeout{*}
% \typeout{* To produce french documentation, run}
% \typeout{* \space\space \space\space (pdf)latex xargs-fr.drv}
% \typeout{*}
% \typeout{* Happy TeXing!}
% \typeout{*}
% \typeout{**************************************************}
% \iffalse
%</batchfile>
% \fi
\endinput