Kategoriecodes und \makeatletter

Wenn TeX Ihre Quelle liest, warum beginnt \ einen Befehl und warum öffnet { eine Gruppe? Die Antwort sind Kategoriecodes (catcodes): Zahlen, die jedem Eingabezeichen zugewiesen sind und dem Tokenizer sagen, welche Rolle das Zeichen spielt. Derselbe Mechanismus erklärt das geheimnisvolle @ in internen LaTeX-Befehlen und warum man solche Befehle in der Präambel mit \makeatletter\makeatother umschließen muss. Diese Seite behandelt beides.

Was Kategoriecodes sind

TeXs Verarbeitung beginnt mit Tokenisierung: Aus einem Zeichenstrom wird ein Strom von Tokens. Für jedes gelesene Zeichen betrachtet TeX dessen Kategoriecode (catcode), eine Zahl von 0 bis 15, die seine Rolle beim Satz bestimmt. \ hat etwa catcode 0 (Escape, Beginn eines Befehls), { catcode 1 (Gruppenbeginn), $ catcode 3 (Mathematikwechsel). Entscheidend ist: Die Rolle hängt vom catcode ab, nicht vom Zeichen selbst. $ schaltet nicht wegen des Dollarzeichens in den Mathemodus, sondern weil es catcode 3 hat.

Die Tabelle zeigt die Standard-Kategoriecodes. Im Alltag fallen vor allem 0 (Befehlsbeginn), 1/2 (Gruppierung), 3 (Mathematik), 4 (Spaltentrenner in Tabellen), 5 (Zeilenende für Absätze), 6 (Makroargumentmarker), 7/8 (Hoch- und Tiefstellung), die Textkategorien 10/11/12 und 14 (Kommentare) auf.

catcodeRolleStandardzeichen
0Escape (beginnt einen Befehl)Backslash \
1GruppenbeginnLinke geschweifte Klammer {
2GruppenendeRechte geschweifte Klammer }
3MathematikwechselDollarzeichen $
4AusrichtungstabulatorAmpersand &
5ZeilenendeReturn / Zeilenumbruch
6Parameter (Makroargument)Raute #
7HochstellungZirkumflex ^
8TiefstellungUnterstrich _
9Ignoriertes ZeichenNullzeichen
10LeerzeichenLeerzeichen und Tab
11Buchstabe (bildet Befehlsnamen)a–z, A–Z
12SonstigesZiffern, Satzzeichen und alles andere
13Aktives Zeichen (wirkt als Befehl)Tilde ~
14KommentarProzent %
15Ungültiges ZeichenLöschzeichen

catcode 11 (Buchstabe) und Befehlsnamen

Unter den Kategorien ist 11 (Buchstabe) besonders, weil sie direkt mit Befehlen verbunden ist. Ein TeX-Kontrollwort, also ein benannter Befehl wie \section, wird als catcode-0-Zeichen, gewöhnlich \, gefolgt von einer Folge catcode-11-Zeichen erkannt. Normalerweise können also nur Zeichen mit catcode 11 Teil eines Befehlsnamens sein. \section endet bei section, weil das nächste Zeichen, ein Leerzeichen oder {, nicht catcode 11 hat. Die Folgen auf Nutzerebene — verschlucktes Leerzeichen nach Kontrollwörtern, \LaTeXlogo als anderer Befehl — stehen auf der Syntaxseite; hier geht es um die catcode-Basis.

Auch dass Ziffern und Satzzeichen catcode 12 (sonstiges) haben, wirkt hier. In a2b können nur die Buchstaben zum Befehlsnamen gehören, also liest sich \a2 als Befehl \a gefolgt vom Zeichen 2. Umgekehrt: Wenn man den catcode eines Zeichens auf 11 setzt, kann dieses Zeichen Teil von Befehlsnamen werden. Das ist der Schlüssel zur Geschichte von @.

Kategorien mit \catcode ändern

Die Zuordnung von Zeichen zu Kategorien ist nicht fest; das Primitiv \catcode kann sie ändern. Die Syntax ist ` \catcode⟨char⟩=⟨number⟩ `: ein Backtick ` vor dem Zielzeichen, dann = und der neue catcode. So bedeutet \catcode@=11 `: Ab hier wird @` als Buchstabe, catcode 11, behandelt.

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

Das ist mächtig, aber fragil und roh nur etwas für Fortgeschrittene. Eine geänderte Kategorie verändert die gesamte spätere Interpretation; vergisst man die Rückstellung, bricht Unerwartetes. Zugleich steckt derselbe Mechanismus in vertrauten Funktionen: \verb und die Umgebung verbatim können Quelltext wörtlich ausgeben, weil sie intern die catcodes der Sonderzeichen (\, {, $ usw.) vorübergehend auf 12 (sonstiges) senken, sodass diese nicht als Befehle oder Gruppierung gelesen werden. \makeatletter ist im Grunde ein sicher benannter Standardumschlag für genau diesen \catcode-Schritt.

\makeatletter und \makeatother

Viele interne Befehle des LaTeX-Kernels und von Paketen enthalten @: \@startsection baut Abschnittsüberschriften, \@ifnextchar schaut auf das nächste Token, \p@ steht für die Länge 0pt usw. In .sty- und .cls-Dateien können sie problemlos definiert und benutzt werden, weil dort @ catcode 11 (Buchstabe) hat und somit Teil des Befehlsnamens ist. Tatsächlich schalten \usepackage und \documentclass beim Einlesen von Paketen und Klassen den catcode von @ auf 11.

Im normalen Dokumentkörper hat @ dagegen catcode 12 (sonstiges). Schreiben Sie also direkt \p@ in Text oder Präambel, liest TeX den Befehl \p gefolgt vom Zeichen @ und erreicht den gemeinten internen Befehl nicht. Die Deklaration \makeatletter macht @ genau für den Bereich, in dem Sie interne Befehle verwenden oder neu definieren, wieder zum Buchstaben; \makeatother setzt es auf den Standard-catcode 12 zurück. Die Namen sagen es: „make @ a letter“ und „make @ other“, intern genau ` \catcode@=11 ` und \catcode@=12 ``.

Warum diese Konvention? Um interne Befehle von normalen Nutzern abzuschirmen. Mit @ als catcode 12 kann jemand, der nur ein Dokument schreibt, nicht versehentlich einen Namen wie \@startsection mit einem eigenen Befehl überschreiben. Ein Name mit @ bedeutet „intern“; wer ihn anfassen will, muss mit \makeatletter ausdrücklich aufschließen.

Beispiel und Fallstricke

Typisch ist, einen internen Befehl einer Klasse oder eines Pakets in der Präambel leicht anzupassen. Im Beispiel wird das interne Makro \@maketitle, also der Aufbau des Titelblocks, innerhalb von \makeatletter\makeatother neu definiert. Nur dort ist @ ein Buchstabe, sodass \@maketitle korrekt als ein Befehl erkannt wird.

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}

Der größte Fallstrick ist vergessenes \makeatother. Dann bleibt @ für alles Folgende ein Buchstabe und kann späteren Text mit @, etwa E-Mail-Adressen, oder Pakete stören, die @ besonders behandeln. Wer mit \makeatletter öffnet, schließt immer mit \makeatother; die beiden gehören zusammen.

Ein zweites Missverständnis ist \makeatletter in einer .sty- oder .cls-Datei. Wie gesagt, beim Einlesen von Paketen und Klassen ist @ bereits catcode 11, also unnötig; ein überflüssiges \makeatother kann sogar spätere Verarbeitung stören. \makeatletter\makeatother ist für .tex-Dokumente, typischerweise die Präambel, wenn interne Befehle berührt werden. Wenn sich interne Befehle vermeiden lassen, etwa durch Überschreiben öffentlicher Befehle mit \renewcommand oder durch ein dafür vorgesehenes Paket, ist das sicherer. Ernsthaftes Makro- und Paketautorenhandwerk steht auf einer eigenen Seite.