Comment obtenir une commande ayant plus d’un argument optionnel ?#

Vous savez sans doute qu’on ne peut définir (au plus) qu’un argument optionnel et que celui-ci est nécessairement le premier. L’objet de la présente astuce est de contourner cette limitation.

Toutefois, il faut faire ici attention : une commande avec deux arguments optionnels semble la limite de ce qui est raisonnable en la matière. Si vous souhaitez avoir plus d’arguments optionnels, vous devriez plutôt considérer la méthode décrite à la question « Comment définir des arguments de forme « clé-valeur » ? » pour disposer d’une méthode bien plus pratique à programmer et à utiliser.

1.  Avec les commandes de base#

1.1.  Commandes enchaînées#

Commençons par une remarque assez fondamentale sur la façon dont gère les commandes. D’abord, il faut bien comprendre qu’une commande n’est pas une fonction : il ne s’agit pas d’exécuter à part le code de la commande et de renvoyer un résultat, mais juste de remplacer le nom de la commande par son texte de définition. En particulier, n’opère aucun contrôle sur le texte de définition d’une commande, qui peut contenir des commandes non définies ou n’ayant pas le bon nombre d’arguments.

On peut alors méditer sur le cas d’une commande définie comme \newcommand\latin{\textit}. Techniquement, elle semble être une commande sans argument. En pratique, l’utilisateur écrira \latin{id est} comme si la commande admettait un argument : celui-ci sera en fait passé à \textit. Vous êtes maintenant prêts à comprendre l’exemple suivant illustrant des commandes enchaînées.

\documentclass{article}
  \usepackage{lmodern}   % Caractères plus lisibles
  \pagestyle{empty}      % N'affiche pas de numéro de page

  \newcommand*\xvec[1][0]{x_{#1},\ldots,\xvecint}
  \newcommand*\xvecint[1][n]{x_{#1}}

\begin{document}
\begin{enumerate}
\item $\xvec$       % donne x_0,\ldots,x_n
\item $\xvec[1]$    % donne x_1,\ldots,x_n
\item $\xvec[1][m]$ % donne x_1,\ldots,x_m
\item $\xvec[m]$    % donne x_m,\ldots,x_n (attention)
\end{enumerate}
\end{document}

Si le dernier argument est optionnel et que vous ne l’utilisez pas, votre commande va manger les espaces qui la suivent, soyez prudent hors du mode mathématique ;

1.2.  Commandes emboîtées#

Si vous avez déjà lu la question « Comment dépasser la limite des 9 arguments pour une commande ? », vous pouvez probablement deviner la solution un peu plus générale à ce problème : les commandes emboîtees (ou relais de commande). Voici un exemple de cette technique :

\newcommand{\maCommande}[1][défaut1]{%
  \def\ArgI{{#1}}%
  \maCommandeRelais
}
\newcommand\maCommandeRelais[1][défaut2]{%
  % le premier argument optionnel est maintenant dans \ArgI
  % le second est dans #1
  ... %
}

Bien sûr, \maCommandeRelais peut avoir autant d’arguments obligatoires qu’autorisé, après avoir pris en compte celui qui est pris avec son propre argument optionnel, autrement dit jusqu’à 8 arguments.

Notez également que vous pouvez évidemment étendre la technique pour fournir autant d’arguments optionnels que votre imagination enfiévrée le permet… Mais, c’est à vos risques et périls et, surtout, à ceux de vos utilisateurs.

2.  Avec l’extension twoopt#

Des variantes de \newcommand (et proches parents), avec des noms comme \newcommandtwoopt, sont disponibles dans l’extension twoopt. Cependant, si vous le pouvez, il est probablement préférable d’apprendre à écrire les commandes vous-même, juste pour voir pourquoi ce n’est pas forcément une bonne idée du point de vue de la programmation.

3.  Avec l’extension optparams#

L’extension optparams, de Jonathan Sauer, fournit une commande \optparams que vous utilisez comme intermédiaire pour définir des commandes avec jusqu’à neuf arguments optionnels. Sa documentation montre des exemples de commandes avec quatre arguments optionnels (alors que cet auteur a créé sa propre extension « clé-valeur »!).

4.  Avec l’extension xargs#

L’extension xargs, de Manuel Pégourié-Gonnard, utilise une extension clé-valeur (xkeyval) pour définir la disposition des arguments optionnels. En voici un exemple :

\usepackage{xargs}
...
\newcommandx{\maCommande}[3][1=1, 3=n]{...}

Ce code définit une commande \maCommande qui a un premier argument optionnel (par défaut 1), un deuxième argument obligatoire, et un troisième argument optionnel (par défaut n).

5.  Avec le programme newcommand#

Une approche alternative est proposée par le programme newcommand de Scott Pakin : il prend un nom de commande et une définition d’un ensemble d’arguments de commande (dans un langage assez facilement compréhensible) et restitue des macros qui permettent à la commande d’être définie. La commande nécessite qu’un interpréteur Python soit installé sur votre ordinateur.