Comment définir des arguments optionnels comme ceux de \section
?#
Sont présentées quelques méthodes traditionnelles, avant de se tourner vers la commande \NewDocumentCommand
désormais incluse dans le noyau de LaTeX, qui fournit une syntaxe ad hoc.
1. Avec les commandes de base#
Les arguments optionnels des commandes définies avec \newcommand
ne fonctionnent pas vraiment comme l’argument optionnel de \section
. En effet, la valeur par défaut de l’argument optionnel de \section
est celle de l’argument obligatoire donnée par l’utilisateur ; au contraire, \newcommand
exige que vous déterminiez la valeur de l’argument par défaut au moment où vous définissez la commande.
L’astuce requise consiste à utiliser une commande dans l’argument optionnel :
\documentclass{article}
\usepackage{lmodern} % Caractères plus lisibles
\pagestyle{empty} % N'affiche pas de numéro de page
\newcommand\exemple[2][\DefaultOpt]{%
\def\DefaultOpt{#2}%
argument optionnel : #1, argument obligatoire : #2%
}
\begin{document}
\exemple{oblig}% #1=#2
\exemple[opti]{oblig}% #1="opti
\end{document}
Le code source de LaTeX recourt à une méthode plus subtile : il utilise une commande \@dblarg
. Voici comment l’exemple précédent aurait été écrit dans LaTeX :
\makeatletter
\newcommand\exemple{\@dblarg\@exemple}
\newcommand\@exemple[2][\@error]{%
argument optionnel : #1, argument obligatoire : #2%
}
\makeatother
Dans ce code, \@exemple
n’est jamais appelé qu’avec un argument optionnel et un argument obligatoire ; si la valeur par défaut de la \newcommand
est appelée, un bug apparaît dans le code utilisateur.
2. Avec \NewDocumentCommand
#
La commande \NewDocumentCommand
, autrefois fournie par l’extension xparse et intégrée dans le cœur de LaTeX depuis 2020, fournit une syntaxe qui permet de définir les commandes de manière flexible. On peut ainsi redéfinir la commande \exemple
ci-dessus :
\NewDocumentCommand\exemple{o m}{%
argument optionnel entre crochets : #1, argument obligatoire : #2%
}
Ici, o
indique un argument optionnel et m
un argument obligatoire (mandatory). Chaque argument peut être rendu long en préfixant le caractère d’un +
.
On peut indiquer une valeur par défaut de la manière suivante :
\NewDocumentCommand\exemple{O{valeur par défaut} m}{%
argument optionnel entre crochets : #1, argument obligatoire : #2%
}
Il est même possible d’indiquer plus d’un argument entre crochets, auquel cas l’utilisateur ne pourra pas définir le second sans avoir défini le premier (noter que []
produit un argument vide, pas l’argument par défaut) :
\documentclass{article}
\usepackage{lmodern} % Caractères plus lisibles
\pagestyle{empty} % N'affiche pas de numéro de page
\NewDocumentCommand\exemple{
O{valeur par défaut}
O{un autre défaut}
+m
}{%
\begin{description}
\item[Premier argument optionnel entre crochets :] #1
\item[Second argument optionnel entre crochets :] #2
\item[Argument obligatoire :] #3
\end{description}
}
\begin{document}
\section{Premier test}
\exemple[le premier argument]{%
j'ai défini le premier argument entre crochets mais
pas le second}
\section{Deuxième test}
\exemple[le premier argument][le second argument]{%
j'ai défini les deux arguments optionnels}
\section{Troisième test}
\exemple[][le second argument]{le premier argument
est vide}
\section{Dernier test}
\exemple[valeur par défaut][le second argument]{%
pour obtenir la valeur par défaut du premier
argument et définir le second argument, j'ai
dû indiquer explicitement la valeur par défaut}
\end{document}
Sources
Joseph Wright,
\NewDocumentCommand
versus\newcommand
versus …, TUGboat 42-1, 2021.