Codes de catégorie et \makeatletter

Quand TeX lit votre source, pourquoi \ commence-t-il une commande et { ouvre-t-il un groupe ? La réponse est le code de catégorie (catcode) : un numéro attribué à chaque caractère d’entrée qui indique au tokenizer le rôle de ce caractère. Le même mécanisme explique le mystérieux @ dans les commandes internes de LaTeX, et pourquoi il faut les entourer de \makeatletter\makeatother lorsqu’on les utilise dans le préambule. Cette page couvre ces deux points.

Ce que sont les codes de catégorie

Le traitement de TeX commence par la tokenisation : transformer un flux de caractères en flux de tokens. Pour chaque caractère lu, TeX consulte son code de catégorie (catcode), un nombre de 0 à 15 qui détermine son rôle typographique. Par exemple, \ a le catcode 0 (escape, début d’une commande), { le catcode 1 (début de groupe), $ le catcode 3 (bascule mathématique). L’idée clé est que le rôle dépend du catcode, pas du caractère lui-même. $ passe en mode math non parce que c’est un dollar, mais parce qu’il a le catcode 3.

Le tableau donne l’ensemble des codes par défaut. Au quotidien, on remarque surtout 0 (début de commande), 1/2 (groupement), 3 (math), 4 (séparateur de colonne), 5 (fin de ligne pour les paragraphes), 6 (marqueur d’argument), 7/8 (exposants et indices), les catégories de texte 10/11/12, et 14 (commentaires).

catcodeRôleCaractère par défaut
0Escape (débute une commande)Antislash \
1Début de groupeAccolade gauche {
2Fin de groupeAccolade droite }
3Bascule mathématiqueSigne dollar $
4Tabulation d’alignementEsperluette &
5Fin de ligneRetour / saut de ligne
6Paramètre (argument de macro)Dièse #
7ExposantAccent circonflexe ^
8IndiceSouligné _
9Caractère ignoréCaractère nul
10EspaceEspace et tabulation
11Lettre (forme les noms de commandes)a–z, A–Z
12AutreChiffres, ponctuation et tout le reste
13Caractère actif (agit comme une commande)Tilde ~
14CommentairePourcent %
15Caractère invalideCaractère delete

Catcode 11 (lettre) et noms de commandes

Parmi les catégories, 11 (lettre) est spéciale parce qu’elle est directement liée aux commandes. Un mot de contrôle TeX, une commande nommée comme \section, est reconnu comme un caractère de catcode 0, généralement \, suivi d’une suite de caractères catcode 11. Autrement dit, seuls les caractères de catcode 11 peuvent normalement former un nom de commande. \section s’arrête à section parce que le caractère suivant, espace ou {, n’est pas catcode 11. Les conséquences utilisateur — espace avalé après un mot de contrôle, \LaTeXlogo lu comme une autre commande — ont été traitées sur la page de syntaxe ; ici, on observe le mécanisme catcode qui les fonde.

Le fait que chiffres et ponctuation soient catcode 12 (autre) compte aussi. Dans a2b, seules les lettres peuvent appartenir au nom de commande ; \a2 se lit donc comme la commande \a suivie du caractère 2. Inversement, si l’on change le catcode d’un caractère en 11, ce caractère peut faire partie des noms de commandes. C’est la clé de l’histoire de @.

Changer les catégories avec \catcode

La correspondance entre caractères et catégories n’est pas fixe : la primitive \catcode peut la réécrire. La syntaxe est ` \catcode⟨char⟩=⟨number⟩ ` : un accent grave ` suivi du caractère cible, puis = et le nouveau catcode. Par exemple, \catcode@=11 ` signifie : « à partir d’ici, traiter @` comme une lettre (catcode 11) ».

latex
% catcode を直接いじる(上級・壊れやすい)/ Touching catcodes directly (advanced, fragile)
\catcode`@=11   % @ を英字に / make @ a letter
\catcode`@=12   % @ を「その他」に戻す / put @ back to “other”

C’est puissant mais fragile, et l’utiliser brut s’adresse aux utilisateurs avancés. Changer une catégorie modifie toute l’interprétation qui suit ; oublier de restaurer casse des choses inattendues. Le même mécanisme sous-tend pourtant des fonctions familières : \verb et l’environnement verbatim peuvent imprimer du code source tel quel parce qu’ils abaissent temporairement les catcodes des caractères spéciaux (\, {, $, etc.) à 12 (autre), afin qu’ils ne soient plus lus comme commandes ou groupements. Le \makeatletter de la section suivante est une enveloppe sûre et nommée autour de ce geste \catcode.

\makeatletter et \makeatother

Beaucoup de commandes internes du noyau LaTeX et des packages contiennent @ : \@startsection, qui assemble les titres de section ; \@ifnextchar, qui regarde le token suivant pour brancher ; \p@, la longueur 0pt ; etc. Elles se définissent et s’utilisent sans problème dans les fichiers .sty/.cls parce que @ y a le catcode 11 (lettre) et compte donc dans les noms de commandes. En fait, pendant que \usepackage ou \documentclass lit un package ou une classe, LaTeX passe @ en catcode 11.

Dans le corps d’un document ordinaire, en revanche, @ a le catcode 12 (autre). Si vous écrivez directement \p@ dans le texte ou le préambule, TeX lit la commande \p suivie du caractère @, et n’atteint jamais la commande interne voulue. La déclaration \makeatletter remet @ en lettre uniquement pour la zone où vous utilisez ou redéfinissez des commandes internes ; son pendant \makeatother restaure le catcode 12. Les noms le disent : « make @ a letter » et « make @ other » ; en interne, c’est exactement ` \catcode@=11 ` et \catcode@=12 ``.

Pourquoi cette convention ? Pour tenir les commandes internes à l’écart des utilisateurs ordinaires. Avec @ en catcode 12 par défaut, quelqu’un qui écrit seulement un document ne peut pas écraser par accident un nom comme \@startsection. Un nom contenant @ signale « usage interne », et pour le toucher il faut explicitement ouvrir la porte avec \makeatletter.

Exemple et pièges

L’usage typique consiste à ajuster légèrement dans le préambule une commande interne définie par une classe ou un package. Dans l’exemple, la macro interne \@maketitle, qui compose la zone de titre, est redéfinie entre \makeatletter et \makeatother. À l’intérieur seulement, @ est une lettre, donc \@maketitle est reconnu comme une seule commande.

document.tex
\documentclass{article}

\makeatletter
% 内部命令 \@maketitle を再定義する / redefine the internal \@maketitle
\renewcommand{\@maketitle}{%
  \begin{center}
    {\LARGE\bfseries \@title}\par
    \vspace{1ex}{\large \@author}\par
  \end{center}%
}
\makeatother

\title{カテゴリコード入門}
\author{名前}
\begin{document}
\maketitle
\end{document}

Le plus gros piège est d’oublier \makeatother. Si vous ne le fermez pas, @ reste lettre pour la suite, ce qui peut casser du texte ultérieur contenant @, comme une adresse mail, ou des packages qui traitent @ spécialement. Ouvrir avec \makeatletter implique toujours de fermer avec \makeatother ; considérez-les comme une paire.

Une autre erreur est d’écrire \makeatletter dans un fichier .sty/.cls. Comme dit plus haut, pendant la lecture d’un package ou d’une classe, @ est déjà catcode 11 ; c’est donc inutile, et un \makeatother superflu peut perturber la suite. \makeatletter\makeatother s’utilise dans un document .tex, typiquement le préambule, quand on touche des commandes internes. Si vous pouvez éviter ces commandes internes, par exemple en redéfinissant une commande publique avec \renewcommand ou en utilisant un package prévu pour l’effet voulu, c’est plus sûr. La création sérieuse de macros et packages est traitée ailleurs.