Que sont les catcodes ?#

Plutôt que de définir des primitives pour des tâches aussi courantes que le passage en mode mathématique ou la mise en exposant ou en indice, Donald Knuth a préféré réserver certains caractères à ces tâches. Par exemple le dollar $ pour passer en mode mathématique, l’underscore _ pour passer en indice. D’autres caractères ont des significations particulières lorsqu’on écrit un document les accolades et crochets pour délimiter les arguments des commandes, ou simplement l’antislash \ pour appeler les commandes. Certains caractères sont différents des autres pour

1.  Principe#

Lorsque le moteur lit un fichier, il associe à chaque caractère deux numéros : un « code de caractère » et un « code de catégorie ». PAr exemple, le % correspond au code ASCII 37 et au code de catégorie 14.

ne connaît rien des glyphes, il travaille uniquement avec des nombres, et cela fait partie de ses points forts. Si vous lui donnez un code de caractère, il ira le chercher dans la table de la police en cours, puis imprimera le glyphe qu’il y aura trouvé à cette position.

En ce qui concerne le code de catégorie, ou catcode, l’utilise pour analyser intelligemment l’entrée. Ça lui permet par exemple, si une accolade ouvrante { apparaît dans une partie particulière du document, de chercher l’accolade fermante correspondante, etc. Cela aurait pu être écrit en dur (« l’accolade ouvrante sert toujours à faire ceci ou cela »), mais Knuth a choisi d’introduire un niveau d’abstraction, de sorte que n’importe quel caractère peut avoir n’importe quel rôle à condition qu’il ait le catcode approprié, ce qui donne une grande souplesse au moteur.

Donc quand analyse un fichier, il attribue à chaque caractère lu un catcode. La façon dont interprète ensuite l’entrée dépend à la fois du caractère et de son catcode. Il y a 16 catcodes qui peuvent être utilisés par le programmeur, plus un code interne spécial. Les 16 codes standards sont numérotés de 0 à 15 :

Code

Signification

Exemple typique

0

Caractère d’échappement

\

1

Début de groupe

{

2

Fin de groupe

}

3

Passage en mode mathématique

$

4

Alignement

&

5

Fin de ligne

^^M

6

Paramètre de commande

#

7

Exposant mathématique

^

8

Indice mathématique

_

9

Caractère ignoré

10

Espace

11

Lettre

A,…, Z, a, …,z

12

« Autre » caractère

tout le reste : ., 1, :, etc

13

Caractère actif, à interpréter comme une commande

~

14

Début de commentaire

%

15

Caractère invalide

[backspace]

Dans le tableau, ^^M représente le carctère invisible que met à la fin de chaque ligne d’entrée, à la place du caractère de fin de ligne éventuellement déjà présent, qui dépend du système d’exploitation.

2.  Découpage en unités lexicales (ou tokens)#

En même temps que attribue un catcode à chaque caractère, il découpe les unités lexicales (tokens). Par exemple s’il lit :

$ 1^{23}_a $

il va interpréter :

  • Un token de passage en mode mathématique, donc il passe en mode mathématique

  • Une espace, qui est ignorée en mode mathématique

  • Un token « autre » 1, qui est donc simplement imprimé

  • Un token de mise en exposant mathématique, ce qui signifie que le prochain élément sera en exposant

  • Un token de début de groupe {,

  • Les tokens « autre », 2 et 3, qui ne peuvent pas être imprimés avant la fin du groupe

  • Le token de fin de groupe }, qui autorise à imprimer l’exposant

  • Un token de mise en indice mathématique, donc prochain élément sera en indice

  • La lettre a, qui n’a pas de signification particulière, est simplement imprimée

  • Une espace, encore une fois ignorée

  • Un token de passage en mode mathématique (ces tokens ont un effet de bascule : on entre dans le mode maths si on n’y était pas, on en sort si on y était), donc retourne en mode horizontal

3.  Changement de catcode#

Les catcodes deviennent souvent importants lorsque décide de ce qui est ou n’est pas une commande. Voici un exemple :

\salut@

Avec seulement l’alphabet comme « lettres », le code ci-dessus est compris comme la commande \salut suivie de l’élément « autre » @. Faisons maintenant de @ une lettre en utilisant la commande \catcode (qui change le code de catégorie d’un caractère) :

\catcode`\@=11\relax
\salut@

Alors, cherchera ici une commande appelée \hello@. Ce type de modification, pouvant inclure d’autres catcodes, peut être d’une grande valeur pour les développeurs d’extension. D’autres exemples sont données lors de la description des différents catcodes dans cette page.

3.1.  Préservation de code#

L’exemple ci-dessus est loin d’être innocent. Le code de fourmille de commandes telles que \@for. Sans modifier le code de la catégorie, ces commandes sont utilisables comme non redéfinissables pour l’utilisateur. L’idée est ici de « protéger l’utilisateur contre lui-même » : il est difficile de casser le code si on ne peut même pas y accéder ! Ce principe a conduit aux commandes \makeatletter et ``makeatotherévoquées à la question "[](../../macros/makeatletter_et_makeatother.md)" : la première met@` dans la catégorie 11, pour qu’il puisse apparaître dans les noms de commandes, la seconde revient sur cette assignation.

Si et utilisent @ comme une « lettre » supplémentaire, utilise : et _. Cela permet d’isoler efficacement le code interne de de celui de lorsque les deux sont utilisés ensemble (comme c’est le cas actuellement).

3.2.  Mode verbatim#

Le texte mis en verbatim est un autre domaine où les codes de catégorie sont essentiels (bien que complexes !).

Ainsi, pour citer du code dans un document, de nombreux caractères spéciaux se voient attribuer le code de catégorie 12. Lorsque nous tapons \verb+\xyz+, lit \verb et prépare tout pour la composition mot à mot et démarre un groupe ; le premier + est avalé et se voit attribuer la catégorie 2, de sorte que lorsqu’il trouve le deuxième +, le groupe se termine et toutes les attributions sont ramenées aux normales (y compris l’attribution de la catégorie 2 à +) : c’est un peu magique, mais ça marche, à condition que \verb+\xyz+ n’apparaisse pas dans l’argument d’une commande.

La raison pour laquelle il n’est pas possible d’imbriquer un texte in extenso dans un autre texte est qu’une fois que les codes de catégorie ont été attribués, cette opération n’est que partiellement réversible (\scantokens pourrait aider mais cela demanderait bien plus d’explications). Tout ce qui est « à ignorer » ou « un commentaire » est jeté : vous ne pouvez pas le récupérer. Avec vous pouvez réassigner des codes de catégorie, mais tout ce qui a déjà disparu reste « perdu ».

4.  Compléments sur les différents catcodes#

En général, pour les catcodes 0 à 8, il n’y a qu’un seul caractère par catégorie :

\  {  }  $  &  ^^M  #  ^  _

Cette unicité n’est pas obligatoire, mais assez naturelle : pourquoi aurait-on besoin de plusieurs caractères d’échappement qui auraient exactement le même effet ? Ce serait souvent du gaspillage de caractères.

4.1.  Catcode 0#

Le seul caractère avec le catcode 0 est \, la contre-oblique. Ce catcode est utilisé pour construire les noms de commandes. Le nom de la commande est créé comme suit :

  • si le caractère suivant n’est pas de la catégorie 11, le nom est constitué du seul caractère courant ;

  • si le caractère est de la catégorie 11, le nom est constitué de tous les caractères de la catégorie 11 en commençant par le caractère courant.

Le premier caractère non utilisé sera relu ultérieurement et un code de catégorie lui sera attribué. Normalement, les espaces après les noms de commande sont ignorés parce que l’état actuel est S et que le code de catégorie du caractère espace est 10. Mais la commande peut modifier le code de catégorie du caractère qui suit.

\documentclass{article}
  \usepackage{lmodern}   % Caractères plus lisibles
  \pagestyle{empty}      % N'affiche pas de numéro de page
  
  \catcode `*=0
  *newcommand{*test}{Ceci est un test.} % Du jamais vu...

\begin{document}
\test Un test *emph{jamais} vu.
\end{document}

4.2.  Catcode 1#

Initialement, le seul caractère de catégorie 1 est l’accolade ouvrante. Cette catégorie marque le début d’un groupe dans

4.3.  Catcode 2#

Initialement, le seul caractère du catégorie 2 est l’accolade fermante. Cette catégorie marque le début d’un groupe dans

L’exemple suivant montre qu’il est possible d’utiliser d’autres caractères (mais ce n’est pas recommandé dans l’usage courant).

\documentclass{article}
  \usepackage{lmodern}   % Caractères plus lisibles
  \pagestyle{empty}      % N'affiche pas de numéro de page
  
  \catcode `[=1
  \catcode `]=2
  \newcommand[\test][Ceci est un test.] % Du jamais vu...

\begin{document}
\test On notera que les \textit[crochets] disparaissent du [texte], car 
ils sont désormais actifs, à l'image des accolades.
\[ A+B \]
\end{document}

4.4.  Catcode 3#

Initialement, le seul caractère de catégorie 3 est $. Il est historiquement fait pour entrer et sortir du mode mathématique (qu’il soit en ligne ou hors-texte). Voici un exemple où les lettres x et y sont passées dans cette catégorie (et sont donc interchangeables pour ce rôle).

\documentclass{article}
  \pagestyle{empty}      % N'affiche pas de numéro de page
  
\begin{document}
Voici un {\catcode `x=3 \catcode `y=3 x \sin x mis en ligne : xy \sin yy }
Ce $\sin$ est équivalent à :
\[\sin \]
\end{document}

Dans l’exemple ci-dessus, on ne fait pas appel à lmodern car il appelle une commande finissant par un y, \DeclareFontFamily, qui n’est plus interprétable par (qui cherche la définition de la commande \DeclareFontFamil), ce qui génère une erreur.

4.5.  Catcode 4#

Le seul caractère de catégorie 4 est &. Il sert à faire des alignements dans les tableaux.

Le fait que différents caractères partagent le même code de catégorie 4 peut s’avérer utile pour aligner les nombres décimaux au niveau du séparateur décimal dans un tableau. Si nous attribuons à . le code de catégorie 4, nous pouvons taper un nombre décimal comme 123.456 et l’interprétera comme s’il s’agissait de 123&456, produisant ainsi deux cellules de tableau qui, pour l’utilisateur final, semblent n’en former qu’une seule ; il faut cependant un peu d’astuce dans la définition de la structure des colonnes du tableau.

4.6.  Catcode 5#

Le seul caractère de catégorie 5 est le caractère de fin de ligne (ou « retour chariot », code ASCII 13). La catégorie 5 (fin de ligne) est très particulière : elle se transforme en espace à moins qu’elle ne soit suivie d’un autre caractère de catégorie 5, auquel cas elle devient la commande \par (c’est l’astuce qui permet de laisser une ligne blanche pour terminer un paragraphe).

4.7.  Catcode 6#

Le seul caractère avec le catcode 6 est #. Ce caractère est utilisé comme délimiteur de paramètre ou référence de paramètre dans les définitions de commandes. Il est également utilisé dans les préambules de tableaux (mais pas dans ).

4.8.  Catcode 7#

Le seul caractère avec le catcode 7 est ^. Ce caractère est utilisé en mode mathématique pour les exposants.

Il est également utilisé dans une construction spécifique: si un caractère de code 7 est doublé et suivi de deux chiffres en base 16, comme dans ^^13 et ^^ab, comprend qu’on appelle le caractère dont le code a été donné (ici, le code 19, et 171).

À faire

A expliciter (semble être valable en uniquement)

4.9.  Catcode 8#

Le seul caractère de catégorie 8 est _. Il est utilisé pour les indices en mode mathématique. En dehors du mode mathématique, il génère une erreur.

4.10.  Catcode 9#

Les caractères de catégorie 9 sont ignorés.

Les catégories 9 et 15 ont été introduites dans parce qu’elles contiennent des caractères « dangereux » (ASCII « null » pour la 9 et ASCII « delete » pour la 15) qui pourraient être mal interprétés par les éditeurs. Pour être tout à fait exact, la catégorie 9 a d’autres usages : dans les fichiers de style l’espace est affecté à la catégorie 9, pour aider les programmeurs à éviter les redoutables « espaces parasites ».

4.11.  Catcode 10#

Un caractère du catcode 10 se comporte comme un espace. Par défaut, l’espace et la tabulation sont de catégorie 10. Si voit un caractère de catégorie 10, l’action dépend de l’état actuel de

  • si sont état est N ou S, le caractère est ignoré ;

  • sinon, est dans l’état M et passe à l’état S : le résultat est un token d’espace (caractère 32, catégorie 10).

Ceci contribue à deux effets (sauf cas peu ordinaires) :

  • les espaces sont ignorés en début de ligne, car est dans l’état M.

  • toute série continue de caractères de catégorie 10 est réduite à un seul, peu importe qu’il s’agisse d’espaces, de tabulations ou de caractères de fin de ligne convertis. En mode verbatim, le catcode de l’espace est modifié, et les espaces sont donc conservés.

4.12.  Catcode 11#

Les caractères de catégorie 11 sont des « lettres » dans le sens où ils peuvent être utilisés pour créer des noms de commandes (sans utiliser \csname). Seules les lettres ASCII (entre a et z, ou entre A et Z) sont par défaut dans cette catégorie.

Les caractères des catégories 11 et 12, lorsqu’ils ne font pas partie d’un nom de commande, peuvent être imprimés ; ce n’est pas le cas pour tous les autres codes de catégorie. Toutefois, un caractère de catégorie 11 ou 12 peut également ne pas apparaître à l’impression, parce qu’il est éliminé au cours du traitement (par exemple des mots-clés ou des options d’extension, des noms d’extension ou de fichier…).

4.13.  Catcode 12#

Les caractères de catégorie 12 ne peuvent pas être utilisés pour créer des noms de commandes de plusieurs caractères. Tous les caractères non répertoriés ailleurs sont de catégorie 12 (en particulier, tous les caractères 8 bits). Ainsi, les caractères de ponctuation tels que ?, (, ) et autres appartiennent à la catégorie 12.

4.14.  Catcode 13#

Les caractères de catégorie 13 sont actifs et ne peuvent être utilisés que si une définition leur est associée. Seul le caractère ~ est de catégorie 13. Ce dernier se développe en :

  • \penalty \@M \ (il y a un espace à la fin de la commande) en Plain

  • \nobreakspace{} en (ce qui revient au même que Plain avec un \leavevmode devant).

D’autres caractères actifs sont également utilisés par l’extension inputenc, de telle sorte que, par exemple, ü est traduit en \"u.

4.15.  Catcode 14#

Les caractères de catégorie 14 agissent comme un caractère de début de commentaire : ignore tout ce qui suit sur la ligne (y compris le caractère de fin de ligne). Le seul caractère avec le catcode 14 est le caractère %.

4.16.  Catcode 15#

Les caractères de catégorie 15 ne sont pas valides.

4.17.  Catcode 16#

Il existe un code de catégorie « spécial », le 16, notamment utilisé dans le test \ifcat. Il est attribué aux commandes non développables dans cette situation, afin qu’elles ne correspondent à rien d’autre qu’aux commandes non développables.