Accueil > TeX et compagnie > Tester si une commande est définie en (La)TeX

Tester si une commande est définie en (La)TeX

14/07/2008

Reprise d’un de mes articles récents sur fctt, qui fait le point sur les mille-et-une (en fait, un peu moins) façons de savoir si une séquence de contrôle est définie ou non : en TeX pur, en LaTeX, en e-TeX, en distinguant ou pas \relax de undefined

Pour commencer, précisons que « non défini » et \relax c’est pas pareil en général :

This is TeX, Version 3.1415926 (Web2C 7.5.7)
**\show\relax
> \relax=\relax.
<*> \show\relax
 
? 
 
*\show\cettecommandenexistepas
> \cettecommandenexistepas=undefined.
<*> \show\cettecommandenexistepas
 
? x
No pages of output.
Transcript written on texput.log.

\ifx compare toujours les significations (« meaning ») des trucs : deux trucs sont \ifx-égaux si et seulement si il ont la même signification. La signification est à peu près ce qui est affiché par \show, sauf qu’avec \show on perd les catcodes alors que bien sûr en vrai ils comptent.

Deuxième point : quand on forme avec \csname une séquence de contrôle dont la signification était précedemment undefined, la séquence est immédiatement rendue \let-égale à \relax. La porté de cette opération est limité comme celle de toute assignation. Exemple :

\begingroup
\show\undefined     % \undefined=undefined
\csname undefined\endcsname
\show\undefined     % \undefined=\relax
\endgroup
\show\undefined     % \undefined=undefined

Application, extraite de latex.ltx (ou de source2e) :

\def\@ifundefined#1{%
  \expandafter\ifx\csname#1\endcsname\relax
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi}

Usage :

\@ifundefined{newcommand}{Pas LaTeX}{LaTeX}

Particularité : \@ifundefined{relax}{Non}{Oui} répond non. En LaTeX, on met donc dans le même sac \relax et undefined, mais c’est un choix propre à LaTeX. (Autre) inconvénient : dans le cas où on exécute la ligne ci-dessus en Plain, c’est comme si on avait aussi fait \let\newcommand\relax.

Autres tests qui ne présentent pas ces inconvénients :

\ifx\truc\undefined % par convention, on suppose que \undefined est non
% définie, mais rien ne le garantit (on utilise aussi \@undefined)
 
\ifx\truc\undefined
  non def
\else
  \ifx\truc\relax
    non def % au sens de LaTeX
  \else  
    def
  \fi
\fi

Le deuxième est vachement préférable dans un milieu plus ou moins LaTeXien, car il y a vraiment un risque que quelqu’un ait fait un \@ifundefined avant… Ces deux tests ne marchent que si on peut écrire la séquence de contrôle sans problème (pas de caractères zarbis dans le nom). Sinon, on peut utiliser :

\begingroup\expandafter\expandafter\expandafter\endgroup
\expandfater\ifx\csname nom+bien/chelou\endcsname\relax

qui a l’avantage de ne pas faire passer à \relax un truc qui était undefined, mais l’inconvénient de ne plus être développable. En TeX Knuthien, on ne peut pas faire mieux. En e-TeX, si.

On a d’abord \ifdefined\truc qui est l’exact équivalent de \ifx\truc\undefined sauf qu’on a plus besoin de supposer que \undefined est vraiment non définie. Ensuite, on a \ifcsname truc+che/lou\endcsname qui fonctionne pareil et ne présente pas l’inconvénient de rendre \truc égal à \relax s’il était précédemment non défini. Bref, le pied. (Le tout était bien sûr développable, cela va sans dire.)

Comme souvent, la solution e-TeX est la meilleure techniquement, mais elle n’etre pas très vite dans les mœurs, en particulier elle n’entrera pas dans le noyau LaTeX avant la sortie de LaTeX3 (c’est-à-dire pas tout de suite). Pour une interface LaTeXienne aux fonctionnalités d’e-TeX (et bien d’autres choses), je recommande le paquet etoolbox. Voir par exemple la section 3.5.1 de son manuel, concernant des points discutés ici.

Categories: TeX et compagnie Tags: ,
Les commentaires sont fermés.