--- myst: html_meta: keywords: LaTeX, programmation, commandes, macros, nom de commande, définition, catcode, code de catégorie, \def, \gdef --- # Comment mettre des caractères autres que des lettres dans les noms de commande ? Les utilisateurs débutants avec LaTeX sont souvent étonnés de voir que des commandes contenant des caractères autres que des lettres ne fonctionnent pas. Par exemple : ```{noedit} \newcommand{\a2main}{À demain !} ``` En effet, contrairement à d'autres langages de programmation, TeX n'autorise que [des lettres dans les noms de commandes](/2_programmation/macros/que_sont_les_macros). Il existe cependant des techniques pour contourner cette limitation mais... à vos risques et périls ! ## 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. ```{noedit} \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. ## 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 : ```{noedit} \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. ## Définition avec la commande `\def` TeX nous permet, avec la commande `\def`, de définir `\a2main` comme la commande `\a` toujours suivie de `2main`. ```{noedit} \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. ## Définition en modifiant un code de catégorie Nous allons ici indiquer à TeX que `2` est une lettre en changeant le code de catégorie, ou *catcode*, de ce caractère : ```{noedit} \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 LaTeX et dans LaTeX 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, LaTeX 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 "[](makeatletter_et_makeatother.md)" fournit plus d'informations. Notez qu'une utilisation de cette technique pourrait nous donner une autre proposition de solution : ```{noedit} \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. ## 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 : ```{noedit} \newcommand{\aIImain}{À demain !} ``` Mais convenons que la blague marche ici beaucoup moins bien, forcément... :::{sources} [Non-letters in macro names](faquk:FAQ-linmacnames) :::