Comment définir une commande ou un environnement étoilé ?#

Vous l’avez sans doute remarqué, beaucoup d’environnements ou commandes standard de existent sous une variante étoilée : par exemple, \newcommand et \newcommand*. Vous pouvez avoir envie de reprendre cette idée quand vous définissez vos commandes et arguments. Voyons ici comment la mettre en oeuvre.

1.  Cas des commandes#

Ce cas pose des difficultés car l’étoile ne peut pas faire partie du nom de la commande. Il faut donc créer une commande qui devra être capable de regarder si elle est suivie ou pas d’une étoile et d’adapter son comportement en conséquence. Pour des raisons techniques, cette commande ne pourra pas accepter d’argument, mais pourra faire appel à des commandes qui en acceptent (voir le début de « Comment obtenir une commande ayant plus d’un argument optionnel ? »).

1.1.  Avec l’extension ifthen#

La façon la plus simple pour un utilisateur d’écrire une telle commande consiste à utiliser l’extension ifthen :

\newcommand{\maCommande}[1]{\ifthenelse{\equal{#1}{*}}%
  {\maCommandeAvecEtoile}%
  {\maCommandeSansEtoile{#1}}%
}
\newcommand{\maCommandeAvecEtoile}{version étoilée}
\newcommand{\maCommandeSansEtoile}[1]{version normale}

Cela fait l’affaire mais uniquement pour des commandes suffisamment simples (la gestion des erreurs pouvant être compliquée et la méthode implique que la commande \maCommandeSansEtoile doit avoir au moins un argument).

1.2.  Avec la commande \@ifstar#

La commande interne de \@ifstar permet d’appeler une commande ou sa version étoilée en fonction du contexte. Elle figure au début de la définition de la commande et est suivie immédiatement par deux noms de commande : celle implémentant la version étoilée, puis celle implémentant la version non étoilée.

Voici un exemple illustrant cette utilisation :

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

  \newcommand{\maCommandeAvecEtoile}[1]{J'ai une étoile et le paramètre #1.}
  \newcommand{\maCommandeSansEtoile}[1]{Je n'ai pas d'étoile et le paramètre #1.}
  \makeatletter
  \newcommand{\maCommande}{\@ifstar\maCommandeAvecEtoile\maCommandeSansEtoile}
  \makeatother

\begin{document}
\maCommande{42}
\maCommande*{7*9}
\end{document}

Notez que :

  • les arguments de \maCommandeAvecEtoile et \maCommandeSansEtoile sont indépendants : chaque commande peut avoir ses propres arguments, sans être contraint par la technique que nous utilisons, contrairement à l’astuce décrite ci-dessus ;

  • la commande \@ifstar est efficace mais elle nécessite que la définition soit encadrée par les commandes \makeatletter et \makeatletter, comme le détaille la question « Que font \makeatletter et \makeatother ? », à moins de les placer dans un fichier sty définissant une extension.

1.3.  Avec l’extension suffix#

Une alternative intéressante est l’extension suffix (qui nécessite , présent par défaut de nos jours). Elle vous permet de définir des variantes de vos commandes de façon assez élégante :

\newcommand\maCommande{version normale}
\WithSuffix\newcommand\maCommande*{version étoilée}

Les arguments des commandes peuvent être spécifiés de manière normale, dans les deux définitions de commandes (après le * dans la version \WithSuffix). Vous pouvez également utiliser les commandes primitives de en créant une définition comme :

\WithSuffix\gdef\maCommande*{version étoilée}

1.4.  Avec l’extension xparse#

Une autre option consiste à utiliser l’extension xparse de l’ensemble l3packages. Cette extension définit un ensemble de commandes (telles que \NewDocumentCommand) assez similaires \newcommand et autres. La grande différence réside dans la spécification des arguments de la commande. Ainsi, pour chaque argument, vous devez choisir parmi différents spécificateurs. Ainsi, pour créer une commande étoilée (dans le style on peut écrire :

\NewDocumentCommand \maCommande { s m } {%
  % #1 est le spécificateur de l'étoile
  % #2 est l'argument obligatoire
  ...
}

Le spécificateur de l’étoile,s (pour star), apparaît comme #1 et prend les valeurs \BooleanTrue (s’il y a une étoile) ou \BooleanFalse (sinon). L’autre spécificateur,m (pour mandatory), signale un argument obligatoire normal de style et apparaît comme #2.

Bien que xparse fournisse des spécifications agréables pour les arguments de commande, il fait partie du . Le charger pour obtenir \DeclareDocumentCommand conduit à charger tout le noyau (un grand nombre d’extensions) via l’extension expl3.

2.  Cas des environnements#

Si vous avez lu la question « Comment bien nommer ses commandes et environnements ? », vous saurez déjà que c’est immédiat pour les environnements car l’étoile est un caractère autorisé dans les noms d’environnements. Il vous suffit donc de faire \newenvironment{myenv} et \newenvironment{myenv*} avec les définitions souhaitées.