TeX が原稿を読むとき、\ はなぜ命令の始まりになり、{ はなぜグループを開くのか――その答えが カテゴリコード(catcode) です。一文字ごとに割り当てられたこの番号が、トークナイザに「その文字の役割」を教えます。そして LaTeX の内部命令に現れる @ の正体も、この仕組みで説明できます。プリアンブルで内部命令を呼び出すときに必要な \makeatletter … \makeatother の意味と、その使いどころをここで押さえます。
カテゴリコードとは
TeX の処理は、入力を文字の列から トークン の列へ変換する 字句解析(トークン化) から始まります。このとき TeX は、読み込んだ一文字ずつに カテゴリコード(catcode) という 0〜15 の番号を見て、その文字が組版上どんな役割を担うかを決めます。たとえば \ は catcode 0(エスケープ=命令の開始)、{ は catcode 1(グループ開始)、$ は catcode 3(数式モードの切り替え)です。重要なのは、この役割は文字そのものではなく catcode によって決まる という点。$ が数式を切り替えるのは「ドル記号だから」ではなく「catcode 3 だから」です。
次の表が、既定のカテゴリコードの全体像です。日常的に意識するのは、命令を始める 0、グループの 1・2、数式の 3、表の桁区切りの 4、段落の改行となる 5、マクロの引数を表す 6、上付き・下付きの 7・8、そして地の文を構成する 10・11・12、コメントの 14 あたりでしょう。
| catcode | 役割 | 既定の文字 |
|---|---|---|
0 | エスケープ(命令の開始) | バックスラッシュ \ |
1 | グループ開始 | 左波括弧 { |
2 | グループ終了 | 右波括弧 } |
3 | 数式モードの切り替え | ドル記号 $ |
4 | 桁揃え(表のセル区切り) | アンパサンド & |
5 | 行末(空行で改段落) | 改行(リターン) |
6 | パラメータ(マクロの引数) | ハッシュ # |
7 | 上付き文字 | キャレット ^ |
8 | 下付き文字 | アンダースコア _ |
9 | 無視される文字 | ヌル文字 |
10 | スペース | 空白・タブ |
11 | 英字(命令名を構成) | a–z, A–Z |
12 | その他 | 数字・句読点など残り全部 |
13 | アクティブ文字(それ自体が命令) | チルダ ~ |
14 | コメント | パーセント % |
15 | 無効な文字 | デリート文字 |
catcode 11(英字)と命令名
カテゴリコードの中でも 11(英字) は、命令の仕組みに直結する特別な存在です。TeX の 制御語(control word) ――\section のような名前付きの命令――は、**catcode 0 の文字(ふつう \)に続く catcode 11 の文字の並び** として認識されます。つまり命令の名前を作れるのは、原則として catcode 11 の文字だけ。\section の名前が section で終わるのは、その次の文字(空白や {)が catcode 11 ではないからです。記法の細かな帰結――制御語の直後の空白が消えること、\LaTeXlogo が別の命令と見なされること――は「記法のルール」のページで扱いました。ここではその土台にある catcode を見ています。
数字や句読点が catcode 12(その他) であることも、ここで効いてきます。a2b のうち命令名に使えるのは英字だけなので、\a2 は \a という命令に文字 2 が続いたものと解釈されます。逆に言えば、ある文字の catcode を 11 に変えれば、その文字を 命令名の一部として使えるようになる ――この一手が、次に見る @ の物語の鍵です。
`\catcode` でカテゴリを変える
文字とカテゴリの対応は固定ではなく、プリミティブ **\catcode** で書き換えられます。構文は ` \catcode⟨文字⟩=⟨番号⟩ ` で、左引用符 ` に続けて対象の文字を、= の右に新しい catcode を指定します。たとえば \catcode@=11 ` は「@` をこれ以降、英字(catcode 11)として扱え」という指示です。
% catcode を直接いじる(上級・壊れやすい)/ Touching catcodes directly (advanced, fragile)
\catcode`@=11 % @ を英字に / make @ a letter
\catcode`@=12 % @ を「その他」に戻す / put @ back to “other”これは強力ですが 壊れやすい(fragile) 操作で、生のまま使うのは上級者向けです。カテゴリを書き換えると以降の解釈がまるごと変わるため、戻し忘れると思わぬ箇所が壊れます。一方で、この仕組みは身近な機能の土台でもあります。\verb や verbatim 環境がソースをそのまま出力できるのは、内部で **特殊文字(\・{・$ など)の catcode を一時的に 12(その他)へ落として**、命令やグループとして解釈されないようにしているからです。次節の \makeatletter は、この \catcode 操作に 安全な名前を付けた定番の包み だと考えると分かりやすいでしょう。
`\makeatletter` と `\makeatother`
LaTeX のカーネルやパッケージの 内部命令 には、名前に @ を含むものが数多くあります。節見出しを組み立てる \@startsection、次のトークンを覗いて分岐する \@ifnextchar、長さ 0pt を表す \p@ などです。これらが .sty/.cls ファイルの中で問題なく定義・使用できるのは、そこでは @ が catcode 11(英字) になっていて、命令名の一部として扱えるからです。実際、\usepackage や \documentclass がパッケージ・クラスを読み込む間、@ の catcode を 11 に切り替えてくれています。
ところが、ふつうの文書本体では @ は catcode 12(その他) です。だから本文やプリアンブルにそのまま \p@ と書いても、TeX はそれを \p という命令に文字 @ が続いたものと読んでしまい、目当ての内部命令には届きません。そこで、内部命令を 使ったり再定義したりする区間だけ @ を英字に戻す宣言が **\makeatletter です。対になる \makeatother** が、@ の catcode を既定値の 12 に戻します。名前のとおり「@ を letter にする/other にする」という意味で、中身はまさに ` \catcode@=11 ` と \catcode@=12 `` です。
なぜこんな約束事があるのか。それは 内部命令を一般利用者の手の届かない場所に隔離する ためです。@ が既定で catcode 12 なら、ただ文書を書いているだけの人が \@startsection のような名前をうっかり自分の命令で上書きしてしまう事故が起きません。@ を含む名前は「これは内部用です」という標識であり、それを触るには \makeatletter で明示的に「鍵を開ける」必要がある、というわけです。
実例と落とし穴
典型的な用途は、クラスやパッケージが定義した内部命令を、プリアンブルで 少しだけ手直しする ことです。次の例では、内部マクロ \@maketitle(タイトル領域の組み方)を \makeatletter … \makeatother で包んで再定義しています。包みの内側でだけ @ が英字になるので、\@maketitle という名前が正しく一つの命令として認識されます。
\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}最大の落とし穴は **\makeatother の書き忘れ** です。閉じ忘れると @ が英字のまま後続に持ち越され、本文中の @ を含む箇所(メールアドレスなど)や、@ を別扱いする一部パッケージの動作が壊れます。\makeatletter を書いたら、必ず対の \makeatother で閉じる――この二つは常にペアで使う、と覚えておきましょう。
もう一つの誤解は、**.sty/.cls ファイルの中で \makeatletter を書いてしまう** ことです。前述のとおり、パッケージ・クラスの読み込み中はすでに @ が catcode 11 になっているので、そこでは不要であり、むしろ余計な \makeatother が他の処理を乱しかねません。\makeatletter … \makeatother は、あくまで **.tex 文書(ふつうはプリアンブル)の中で内部命令に触れるとき** に使うものです。なお、内部命令にどうしても触れずに済むなら、\renewcommand で公開命令を上書きする、あるいは目的の機能を提供する正規のパッケージを使う方が安全です。さらに本格的なマクロ・パッケージ作成は、別ページで扱います。