マクロツイーター

はてダから移行した記事の表示が崩れてますが、そのうちに直せればいいのに(えっ)

luatexbase の話:カテゴリコードテーブル (1)

LaTeX における(パッケージ開発者用の)パッケージに luatexbase (作者:Manuel Pégourié-Gonnard、Élie Roux)というものがある。これは LuaTeX における基礎的な拡張機能、例えば属性(attribute)、カテゴリコードテーブル(category code table)等を LaTeX (または plain TeX)上(の TeX マクロ)で使うことを支援するものである。「レジスタを大量に確保する話」で述べたが、LaTeX を拡張エンジンの機能に適応させるにはそのためのパッケージの読込が必要なのである。((LuaTeX には 65536 個のレジスタがある(e-TeX は 32768 個だった)が、これを \newcount 等で割り当てるのも luatexbase を読み込んで初めて可能になる。))

ここではカテゴリコードテーブルについて説明する。LuaTeX ではカテゴリコードのテーブルが複数存在して、「現在有効なテーブル」を切り替えることにより、全部の文字のカテゴリコードの値を一斉に切り替えることができる。


\newluatexcatcodetable\制御綴 % 新しいテーブルの宣言
\luatexsavecatcodetable\制御綴 % 現在のテーブルの内容を指定のテーブルにコピー
\luatexcatcodetable\制御綴 % 指定のテーブルに切り替える

【補足】(2011-04-30)この記事を書いた時点では、カテゴリコードテーブルを「カテゴリコードの値のセットを保存するためのもの、つまり、『現在のカテゴリコードセット』と各々のカテゴリコードテーブルとの間でのコピーをすることで、値を一斉に切り替える」と誤解していた。実際は、カテゴリコードテーブルが複数あって、その中の『現在アクティブなもの』が『現在のカテゴリコードセット』そのものである。つまり、現在 5 番のテーブルがアクティブだとすると、\catcode 命令による操作は 5 番のテーブル自体を書き換える。(「初期値」は 0 番である。)実際の実装では、\catcodetable は『現在アクティブなカテゴリコードテーブルの番号』を表す整数パラメタになっている(だから値を読み出すことも可能)。何故か、LuaTeX のマニュアルではそのように記述されていないのだが。

上記のように \newluatexcatcodetable で宣言を行った時、実際には \制御綴 は割り当てられたテーブルの番号を表す整数定数になっている(つまり、\newbox と同じ仕組)。この値は Lua 上の変数 luatexbase.catcodetables['制御綴'] にも保存されていて、これを tex.print()/tex.sprint() の第 1 引数に指定することで、「そのカテゴリコードテーブルで」文字列を TeX に送り込むことができる。

luatexbase では 6 種類の設定が予め割り当てられている。例えば、\CatcodeTableString は「\the-文字列」*1\CatcodeTableLaTeXAtLetter は「LaTeX\makeatletter の状態」の設定である。Lua 変数については、例えば luatexbase.catcodetables['CatcodeTableLaTeXAtLetter']luatexbase.catcodetables['latex-package'] というように短い名前も用意されている。((そもそも長い luatexbase.catcodetables がコード中に頻出するのであれば、単にその値を短い名前のローカル変数に代入すればよいだけである。)) 以下にこのプリセット値を用いた例を示す。((ここでは luatexbase の「Lua モジュール管理機能」(\RequireLuaModule 等)も用いているが、カテゴリコードテーブルとは直接は関係ない。それから、この「Lua モジュール」は、Lua の言語要素の「モジュール」とは直接は関係ない。))

[test.tex]


\documentclass{article}
\usepackage{luatexbase}
\RequireLuaModule{test} % test.lua を読み込む
\makeatletter
\def\@@yes{YES} % @ 付の制御綴を定義した
\makeatother % @ を非文字に戻した
%%\usepackage{luatex} % (後述)
\typeout{\directlua{ cctabletest() }} % Lua 関数実行
\begin{document}
\end{document}

[test.lua]


luatexbase.provides_module { name = 'test' }
function cctabletest()
-- \makeatletter のカテゴリコードで \@@yes を出力する
local cctb = luatexbase.catcodetables['latex-package']
tex.sprint(cctb, '\\@@yes')
end

上のソース中の \directlua は〈@〉のカテゴリコードが 11 の状態で「\@@yes」と書いたのと同じで、結局マクロ「\@@yes」が展開されて「YES」が端末に出力される。もし単に tex.sprint('\\@@yes') とすると、\directlua の位置では〈@〉のカテゴリコードは 12 なので、結果的に「\@」「@」「y」「e」「s」の 5 トークンと見なされてしまうことに注意。

【補足】 ちなみに、etex パッケージと luatexbase はともにレジスタ割当の上限を変更する(前者は 32768 個、後者は 65536 個)が、LuaLaTeX で両方が読み込まれても衝突することはなく、上限は(正しく)65536 個になる(実際は、luatexbbase は内部で etex を呼んでいる)。etex パッケージと luatex パッケージの関係についても全く同じである。

(続く)

*1:ASCII 空白(符号位置 32)のみ 10 で残りは全て 12。