luatexbaseについて

luatexbase パッケージは TeX 開発者用のパッケージで、 LuaTeX の拡張機能の LaTeX/plain TeX での使用を支援する。 luatexbase パッケージが本体で、 その他に以下のサブパッケージから構成される。

  • luatexbase-compat : 互換性支援
  • luatexbase-loader : Lua ファイル検索の改良
  • luatexbase-regs : 拡張レジスタの使用
  • luatexbase-cctb : カテゴリコードテーブル
  • luatexbase-attr : 属性
  • luatexbase-mcb : コールバック多重化
  • luatexbase-modutil : モジュール管理

本体パッケージを読み込む (\input luatexbase.sty、または \RequirePackage{luatexbase} ) と全てのサブパッケージが読み込まれるが、 サブパッケージを単体で読み込むこともできる。

(注意) 本ページ中では、LuaTeX 拡張のプリミティブは luatex の接頭辞を付した形で記述する。

各サブパッケージの主な機能

luatexbase-compat : 互換性支援

TeX Live 2009 (0.40.6 版)以降(および同時期の W32TeX) の LuaTeX では以下の条件が満たされる:

  • プリミティブ \directlua はこの名前で使用可で、 また \directlua{...} { の前の引数なし)の書式が使える。 (現在の版では省略可能な引数が存在するが、この条件は満たす。)
  • plain/LaTeX 系のフォーマットでは、pdfTeX から継続するもの以外のプリミティブ (ただし \directlua は除く)は前に pdftex を付した名前で定義されている。 (実際には、LaTeX 系では接頭辞付の名前のみが定義され、 plain 系では接頭辞付と接頭辞無の両方の名前が定義されている。)

このパッケージでは、これらの条件を満たさない LuaTeX (つまり、極めて古いか、「異質な」環境) での互換性確保のための支援を行う。

従って、上記の「普通の」 環境を動作要件とするようなパッケージでは、 このパッケージの機能は直接的には不要である。 (LuaTeX-ja はそれでいいんですね…?)

luatexbase-loader : Lua ファイル検索の改良

普通の Lua インタプリタ環境では、 モジュール読み込み(require "foo.bar") でモジュール名をパス名に変換する (package.path の設定値を用いる)際に、 「.」をパス区切り文字に変換する動作を行っていた (例えば package.path に「/usr/lib/lua/?.lua」 とある場合は「/usr/lib/lua/foo/bar.lua」)。

LuaTeX では、このファイル検索が Kpathsea を用いたものに置き換えられているが、 少し古い LuaTeX だとこのドットの変換が行われなかった。 (つまり、$LUAINPUTS 以下の foo.bar.lua を検索する。) 現在の LuaTeX ではドットの変換が行われる ($LUAINPUTS 以下の foo/bar.lua を検索する)ように変更されている。

このパッケージは、古い LuaTeX で同じ機能を提供し、 またさらに古い版のための互換性支援を行っている。 LuaTeX での Lua ファイル検索の方法が解っていれば、 それ以上気にする必要はない。

luatexbase-regs : 拡張レジスタの使用

plain/LaTeX のレジスタ割当(\newcount 等)において、 LuaTeX のもつ 65536 個のレジスタを利用できるようにする。

LaTeX において 32768 個のレジスタを利用するためのパッケージが etex であるが、luatexbase-regs はまず etex を読んでから、 それへのパッチという形で 65536 個への拡張を行っている。 LaTeX のパッケージは重複読込が防止されるので、 予め etex を読んでいる場合もいない場合も正常に 65536 個への拡張が実施され、 またその後に etex が読まれることがあっても、 32768 個に戻ることはない。

plain の場合は、etex パッケージ相当の機能はフォーマットに組み込まれている (その部分のソースは etex.src)。 従って、luatexbase-regs.sty の読込時に、 etex の機能は必ず存在するし、 また後から etex が読み込まれることもない。

e-TeX では拡張部分(256 番以上) のレジスタは元のものに比して効率が劣るという性質があったが、 LuaTeX ではそうではない。 従って、luatexbase-regs が読まれた時点で、 そこからの新規の割当は全て 256 番以上から行うようにすることで、 255 番以下の残っているレジスタを insert のために確保するという処理が行われている。

なお、luatexbase-regs は etex を内部で読み込むので、 その独自機能(ローカル割当など)は全て利用できる。 ただ、それらを使う必要は全く生じないと思われる。

luatexbase-cctb : カテゴリコードテーブル

LuaTeX ではカテゴリコードのテーブルが複数存在して、 「現在有効なテーブル」を切り替えることにより、 全部の文字のカテゴリコードの値を一斉に切り替えることができる。 このパッケージはカテゴリコードテーブルの利用を支援する。

  • \newluatexcatcodetable\制御綴 : [一般] 新しいカテゴリコードテーブルを \制御綴 に割り当て、それを \luatexinitcatcodetable で初期化(IniTeX のカテゴリコードの状態をもつ)する。 実際には、\制御綴 は割り当てられたテーブルの番号を表す整数定数 (chardef トークン)になっている(\newbox と同じ仕組)。 この定数は、Lua 変数 luatexbase.catcodetables["制御綴"] にも保存される。
  • \setluatexcatcodetable\制御綴{<テキスト>} : [一般] \制御綴 のテーブルに対して、カテゴリコード値の設定を行う。 つまり、ローカルに <テキスト> (これは普通 \luatexcatcodetable 実行と \catcode の設定からなる) を実行して、結果のカテゴリコードの状態を \制御綴 に(グローバルに)保存する。
  • \setcatcoderange{<開始>}{<終了>}{<値>} : [一般] (現在アクティブなカテゴリコードテーブルについて、) <開始> から <終了> までの符号値のカテゴリコードを <値> に設定する。

割り当てたカテゴリコードテーブルに実際に切り替える (アクティブにする)には \luatexcatcodetable プリミティブを用いる (つまり、\luatexcatcodetable\制御綴)。 luatexbase-cctb を使っている限り、 \luatexsavecatcodetable プリミティブを使う必要はなくなる。

いくつかのプリセットが用意されている。 これらは \newluatexcatcodetable で割り当てられたものなので、luatexbase.catcodetables 中に対応するキーをもつが、 〈 〉内に示した短い文字列の別名も与えられている。 つまり、例えば \directlua 中で 「\makeatletter で TeX に書き出したい」という場合は

local cctb_pkg = luatexbase.catcodetables["latex-package"]
tex.sprint(cctb_pkg, "\\ltj@hoge")

のようにすればよい。 (「どこで使われるか解らないマクロ」は、大概の場合、 「現在のカテゴリコードの値」には依存して欲しくないはずである。)

  • \CatcodeTableIniTeX : 〈ini〉 IniTeX 既定。
  • \CatcodeTableString : 〈string〉 空白文字(U+0020)のみ 10 で残りは 12。
  • \CatcodeTableOther : 〈other〉 全て 12。
  • \CatcodeTableLaTeX : 〈latex〉 LaTeX の \makeatother の状態。
  • \CatcodeTableLaTeXAtLetter : 〈latex-package〉 LaTeX の \makeatletter の状態。
  • \CatcodeTableExpl : 〈expl〉 LaTeX3 のプログラム用の設定。 \CatcodeTableLaTeX との相違点は、 〈~〉が 10 で空白文字とタブが 9 で〈:〉と〈_〉が 11 であること。

luatexbase-attr : 属性

属性(attribute)は、TeX の表層のレベルで管理されている情報を内部処理のレベルに受け渡すための仕組みである。 従って、仕組の理解には内部処理に関する知識が必要となるが、 雰囲気を掴むために、ここでは粗い概説をしておく。

普通、TeX で「\hbox{AB} 」が実行されると、 そのボックスの「内部表現」として、 「〈A〉 の『文字ノード』と〈B〉の『文字ノード』 が順に並んだリスト」 が生成される。 ここで、次のように属性の値を設定したとする。

\hbox{A\luatexattribute10=1 B}
この場合、〈B〉の『文字ノード』 には「属性 10 = 1」という「情報」が付加される (〈A〉には付加されない)。 LuaTeX では、TeX の内部処理に Lua の関数 (これが「コールバック」である) を用いて割り込むことができるが、 そのような Lua の関数内で、 先ほどのボックス中のノードの属性値を読みだして、 それに応じて何か処理を行う (例えば「属性 10 が 1 なら下線を付加する」) ことが可能になる。 なお、ここでは明示的なボックスを用いたが、 普通に(段落として)書くテキストも、 実際には暗黙のボックスを作る処理が行われているので話は同じである。

このパッケージは属性の利用を支援する。

  • \newluatexattribute\制御綴 : [一般] 新たに \制御綴 に属性レジスタを割り当てる。 同時に Lua 変数 luatexbase.attributes["制御綴"] に割り当てられたレジスタ番号が代入される。
  • (<番号> =) luatexbase.new_attribute(<名前>) : [Lua 関数] Lua 上で属性レジスタを割り当てる。 ただし、TeX の制御綴は定義されず、luatexbase.attributes のキーだけが設定される。 戻り値は割り当てられた番号。
  • [\global]\setluatexattribute\制御綴{<整数式>} : [一般] 属性の値の代入。
  • \unsetluatexattribute\制御綴 : [一般] 属性を未設定にする。 (つまり、-"7FFFFFFF を代入する。; ここで \global が使えないのは設計ミスかな?
  • luatexbase.unset_attribute(<名前>) : [Lua 関数] 属性を未設定にする。

luatexbase-mcb : コールバック多重化

LuaTeX のコールバックの仕様では、 一つの種別のコールバックには同時に一つの関数しか登録できない。 このパッケージは複数の関数の登録を可能にし、 さらにコールバックの種類によっては擬似的に複数の関数が同時に機能するようにする (例えば、フィルタ系のコールバックでは、 登録されたフィルタ関数を順番に適用するという処理を行う)。

以下の説明は、元来のコールバック(callback ライブラリ) に関する知識を前提にする。

  • luatexbase.add_to_callback(<種別>, <処理>, <名称>, <優先度>) : [Lua 関数] <種別> の処理リストの中に <処理> (関数)を登録する。 <種別><処理>callback.register() に渡す引数と同じ。 <名称> はその <処理> を参照するのに後で使用される。 <優先度> はその <種別> に対する処理リストの中の順位を表し (1 が先頭)、範囲外の値は端の値に丸められる。 だから 1 とすれば先頭(優先度最大)に、1000 等の十分大きな値とすれば末尾(優先度最小)になる。
  • luatexbase.remove_from_callback(<種別>, <名称>) <種別> の処理リストの中から <名称> で参照される関数を削除する。
  • (<優先度> = ) luatexbase.priority_in_callback(<種別>, <名称>) <種別> の処理リストの中の <名称> で参照される関数の優先度を返す。

この他、ユーザ定義のコールバックを新設する等の機能もある。

luatexbase-modutil : モジュール管理

Lua のモジュールの取扱を拡張し、 LaTeX のパッケージ(\RequirePackage) と同等の名前一致検査やバージョン検査を提供する。 Lua 5.1 で導入された「モジュール」の概念を前提にしていることに注意。

  • \RequireLuaModule{<モジュール名>}[<日付>] : [一般] TeX から Lua モジュールを読み込む。 <モジュール名> は Lua の require() の引数に渡すものと同じ。 <日付>YYYY/MM/DD 形式である。
  • luatexbase.require_module(<モジュール名>[, <日付>]) : [Lua 関数] \RequireLuaModule に対応する Lua 上のインタフェース。
  • luatexbase.provides_module(<情報>) : [Lua 関数] モジュールの中で実行し、そのモジュールの情報を宣言する。

\RequireLuaModule (または luatexbase.require_module()) は次のような動作を行う。 基本的に require() の拡張であることに注意。 多重読み込みの回避などは require() が行っている。

  • require("<モジュール名>") を実行する。
  • 読み込まれたファイルの中で、 luatexbase.provides_module({ name = <宣言名> [, date = <宣言日付>] }) が実行されているかを検査し、されていない場合は警告する。
  • <宣言名><モジュール名> に一致しない場合は警告する。
  • <日付><宣言日付> の両方が指定されていて、 かつ前者が後者よりも新しい場合は警告する。

luatexbase.provides_module() の引数には次のようなテーブルを渡す。

luatexbase.provides_module({
  name        = 'useful.util',                -- モジュール名(必須)
  date        = '2011/01/01',                 -- 日付
  version     = '0.1a',                       -- バージョン
  description = 'some useful utilities',      -- 要約
  author      = 'A. U. Thor',              -- 残りは無視される
  license     = 'NYSL',
})

\RequireLuaModule で読まれるモジュールについては、 luatexbase.provides_module() が必要なことを除き、 Lua の require() で読まれるモジュールと全く同じ方法で構成できる。 すなわち、module() 命令を用いてもよいし、 全く別の方法を用いてもよい。 基本的に、luatexbase.provides_module() はそのモジュールの他の部分のコードに影響を与えない。