Comment mettre des caractères autres que des lettres dans les noms de commande ?#

Les utilisateurs débutants avec sont souvent étonnés de voir que des commandes contenant des caractères autres que des lettres ne fonctionnent pas. Par exemple :

\newcommand{\a2main}{À demain !}

En effet, contrairement à d’autres langages de programmation, n’autorise que des lettres dans les noms de commandes. Il existe cependant des techniques pour contourner cette limitation mais… à vos risques et périls !

1.  Utilisation de \csname et \endcsname#

Voici un exemple de la méthode utilisant les commandes \csname et \endcsname qui vont encadrer le nom de la notre commande.

\expandafter\newcommand\csname a2main\endcsname{À demain !}
Je vous dis « \csname a2main\endcsname ».

Cette technique a l’unique désavantage de demander bien trop de texte et rend l’utilisation des chiffres finalement peu intéressante.

2.  Définition d’un générateur de commande spéciale#

En retenant la logique précédente, nous définissons ici une fonction particulière pour un peu plus d’automatisation :

\newcommand{\DefCommande}[2]{%
  \expandafter\newcommand\csname defcomm-#1\endcsname{#2}%
}
\newcommand{\Commande}[1]{\csname defcomm-#1\endcsname}
 ...
\DefineRemark{a2main}{À demain !}
 ...
Je vous dis « \Commande{a2main} ».

C’est toutefois une solution indirecte car la commande \a2main n’est pas accessible.

3.  Définition avec la commande \def#

nous permet, avec la commande \def, de définir \a2main comme la commande \a toujours suivie de 2main.

\def\a2main{À demain !}
Je vous dis « \a2main ».

Ici, \a2main est directement utilisatble mais cette solution pose deux problèmes :

  • elle crée une source d’erreur : si \a est suivi d’autre chose que 2main, une erreur se déclenche (Use of \a doesn’t match its definition), par exemple avec \a4mains. Ceci perturberait quelqu’un qui n’aurait pas réalisé qu’il y a une définition subtile de \a dans le document.

  • elle redéfinit discrètement la commande \a, si elle existe. Par conséquent, cette technique ne peut pas être utilisée pour définir à la fois une commande\a2main et, par exemple, une commande \a2mimot dans le même document.

4.  Définition en modifiant un code de catégorie#

Nous allons ici indiquer à que 2 est une lettre en changeant le code de catégorie, ou catcode, de ce caractère :

\catcode`2 = 11
\newcommand{\a2main}{À demain !}
Je vous dis « \a2main ».

Si \a2main est maintenant utilisable directement, cette manipulation casse toute autre utilisation de 2, en particulier comme valeur numérique. La commande \setlength{\paperwidth}{2cm} va en conséquence générer une erreur indiquant qu’il ne comprend plus de valeur intégrant un 2 (Missing number, treated as zero.).

En règle générale, la modification des catcodes doit être utilisée en dernier recours, après un examen détaillé des autres options. Pour un utilisateur peu expérimenté, il est concevable que cette solution puisse être utile mais elle doit rester l’exception.

Il faut noter que cette technique est couramment utilisée — sous une forme légèrement différente — dans la plupart des extensions et dans lui-même. La convention est d’utiliser @ dans les noms des commandes internes pour les cacher à l’utilisateur et ainsi éviter les conflits de noms. À cette fin, traite automatiquement @ comme une lettre lors du traitement des classes et des extensions et comme une non-lettre lors du traitement du document de l’utilisateur. Sur ce point, la question « Que font \makeatletter et \makeatother ? » fournit plus d’informations.

Notez qu’une utilisation de cette technique pourrait nous donner une autre proposition de solution :

\begingroup
  \catcode`2 = 11
  \gdef\a2main{À demain !}
  \gdef\ademain{\a2main}
\endgroup
Je vous dis « \ademain ».

Si cette solution fonctionne, elle va à l’encontre de l’objectif intial. Toutefois, la commande \ademain utilise bien un catcode modifié pour 2, même si il est redevenu normal au moment où il est utilisé. Notez également l’utilisation de la commande primitive \gdef car \newcommand ne peut pas faire une commande disponible en dehors de son groupe.

5.  Recommandation#

Il est recommandé de choisir des mécanismes hors modification de catcode (comme celui faisant intervenir \DefCommande ci-dessus) ou de choisir un nom de commande ne contenant que des lettres ordinaires. Une approche courante consiste à utiliser des chiffres romains à la place des chiffres arabes :

\newcommand{\aIImain}{À demain !}

Mais convenons que la blague marche ici beaucoup moins bien, forcément…