LaTeXカーネルの2020/10/01の改版で導入される、新しいフックシステムを理解するためのメモ書き。
フック
- フック(hook)は「ラベル(label)からコード片(code chunk)へのマップ」と「ルール(rule)の集合」をもつ。
- まだ作成していないフックにコード片を追加することができる。
※△印の命令ではラベル指定でドット記法が使えない。
フック作成・実行
\NewHook{<フック名>}:フックを作成する。\NewReversedHook{<フック名>}:逆順フック(reversed hook)を作成する。
※逆順フックではコード片の実行順が通常とは逆になる。(後述)\NewMirroredHookPair{<フック名1>}{<フック名2>}:フックの組を作成する。
※単に\NewHook{<フック名1>}\NewReversedHook{<フック名2>}と同等。- △
\UseHook{<フック名>}:フックを実行する。 - △
\UseOneTimeHook{<フック名>}:フックを“one-time実行”する。すなわち、フックを実行した後、「以後そのフックへコードを追加しようとした場合は代わりに即時に実行する」ようにする。
コード片の追加
※オプション引数<ラベル>の既定値は「既定ラベル」。
\AddToHook{<フック名>}[<ラベル>]{<コード>}:フックにコード片を追加する。既に当該のラベルに対するコード片がある場合はそのコード片の末尾に引数のコードを追記する。\RemoveFromHook{<フック名>}[<ラベル>]:フックから当該のラベルに対するコード片を削除する。\AddToHookNext{<フック名>}{<コード>}:フックに“次回用”のコード片を追加する。“次回用”のコード片はそのフックが次に実行されたときにのみ実行される。
既定ラベル
- ドット記法(dot-syntax):フック名またはラベルの引数の値が「
.であるか./で始まる」場合は.は「既定ラベル(default label)」に置き換えられる。
※ただし△印の命令のフック名引数ではドット記法が使えない。 - 「既定ラベル」はパッケージ・クラスの読込中はその名前(
\@currname)、それ以外はtop-level。 \DeclareDefaultHookLabel{<ラベル>}:「既定ラベル」を変更する。
※有効範囲は当該ファイルの読込中。
ルール
- ルールが指定されない場合、コード片の実行順は、通常のフックでは追加された順、逆順フックではその逆順となる。
※そのように動作すると記載されている。仕様として保証されているのかは微妙であるが、そうでないと「逆順フック」という概念が意味を成さない気がする。 ※“次回用”のコード片は常に(逆順フックでも)最後に実行される。 - ルールを指定することでコード片の実行順を変更できる。
\DeclareHookRule{<フック名>}{<ラベル1>}{<関係>}{<ラベル2>}:フックにルールを指定する。
※特定のラベルの組についてルールは1つしか指定できない。既にルールが指定されている場合は新しく指定したもので置き換えられる。
有効な<関係>の値は以下の通り:before/<:ラベル1のコードはラベル2のコードより前に実行される。after/>:ラベル1のコードはラベル2のコードより後に実行される。incompatible-warning:ラベル1のコードとラベル2のコードは併存できない。違反した場合は警告を出す。
※違反の場合、両方のコードが無効になる。incompatible-error:ラベル1のコードとラベル2のコードは併存できない。違反した場合はエラーを出す。voids:ラベル1のコードが存在する場合はラベル2のコードが無効になる。unrelated:ラベル1のコードとラベル2のコードの実行順序を問わない。(これが既定。)
\ClearHookRule{<フック名>}{<ラベル1>}{<ラベル2>}:指定のラベルに対するルールを削除する。
※\DeclareHookRule{<フック名>}{<ラベル1>}{unrelated}{<ラベル2>}と同等。\DeclareDefaultHookRule{<ラベル1>}{<関係>}{<ラベル2>}:全フックに対する既定のルールを指定する。
※フックに対して指定されたルールの方が既定のルールより優先する。
※プレアンブル専用。
情報取得
- △
\IfHookEmptyTF{<フック名>}{<真>}{<偽>}:フックが空である(コード片が全く追加されていない)かどうかのテスト。 - △
\IfHookExistsTF{<フック名>}{<真>}{<偽>}:フックが存在する(作成されている)かどうかのテスト。 \ShowHook{<フック名>}:フックの現在の状態を端末に出力する。\LogHook{<フック名>}:フックの現在の状態をログに出力する。\DebugHooksOn/\DebugHooksOff:デバッグ用出力を有効/無効にする。
カーネルが定義するフック
当該のフックに追加する専用の命令がある場合は一緒に紹介する。(ただし、\AddToHook{<フック>}と等価であるとは限らない。)
※ ◇印は“one-time実行”されるフック。
※ ☆印は逆順フック。
環境
※etoolboxパッケージで一部の命令が提供されていたが、カーネルに取り込まれた。(新etoolboxは\begin/\endへのパッチを行わなくなる。)
env/環境名/before:環境の実行の直前(グルーピングの外)。\BeforeBeginEnvironment[<ラベル>]{<コード>}※元々はetoolboxの機能。
env/環境名/begin:環境のbegin部実装コードの直前。\AtBeginEnvironment[<ラベル>]{<コード>}
env/環境名/end:環境のend部実装コードの直前。\AtEndEnvironment[<ラベル>]{<コード>}
env/環境名/after☆:環境の実行の直後(グルーピングの外)。\AfterEndEnvironment[<ラベル>]{<コード>}※元々はetoolboxの機能。
文書本体開始・終了
※etoolboxパッケージでは独自に文書本体開始・終了時のフックを提供している。最新版のetoolboxが新カーネルで動作する場合は、カーネルで用意されたフックを利用する動作に切り替わる。(つまり\(end)documentへのパッチを行わなくなる。)
※atveryendパッケージでは独自に文書本体終了時のフックを提供している。新カーネルのLaTeX上ではatveryendはカーネルで用意されたラッパーに置き換えられる。(ただし\BeforeClearDocumentはサポートされない。)
begindocument/before◇:\begin{document}の実行の先頭。\AtEndPreamble[<ラベル>]{<コード>}〈新etoolbox〉
begindocument◇:\begin{document}の途中。\AtBeginDocument[<ラベル>]{<コード>}
※プレアンブル専用であることは変わらず。\AfterPreamble{<コード>}〈新etoolbox〉
begindocument/end◇:\begin{document}の実行の最後。\AfterEndPreamble{<コード>}〈新etoolbox〉
enddocument◇:\end{document}の実行の先頭。\AtEndDocument[<ラベル>]{<コード>}
enddocument/afterlastpage◇:\end{document}で最終ページを吐き出した直後。\AfterLastShipout{<コード>}〈新atveryend〉
enddocument/afteraux◇:\end{document}でauxファイルを再読込した直後。\AtVeryEndDocument{<コード>}〈新atveryend〉
enddocument/info◇:enddocument/afterauxフックの直後。\AtEndAfterFileList{<コード>}〈新atveryend〉
enddocument/end◇:TeXの実行が終了する直前。\AfterEndDocument{<コード>}〈新etoolbox〉\AtVeryVeryEnd{<コード>}〈新atveryend〉
フォント選択(NFSS)
※詳細未調査
rmfamily:sffamily:ttfamily:normalfont:expand@font@defaults:bfseries/defaults:bfseries:mdseries/defaults:mdseries:
ページ出力(shipout)
※新カーネルのLaTeX上ではeveryshiはカーネルで用意したラッパーに置き換えられる。
※新カーネルのLaTeX上ではatbegshiはカーネルで用意したラッパーに置き換えられる。
※atenddviパッケージの機能はカーネルに取り込まれた。
shipout/before:実際にページ出力が起こる前に行う処理。
※shipoutのフックの中でこれだけは「実行する内容」をコード片とする。残りのフックは「ボックスに挿入する内容」をコード片とする。
※ページ出力予定のボックスの内容は\ShipoutBoxレジスタに入っていて、フックのコードでこの内容を変更することができる。\EveryShipout{<コード>}〈新everyshi〉\AtNextShipout{<コード>}〈新everyshi〉:“次回用”に追加。\AtBeginShipout{<コード>}〈新atbegshi〉\AtBeginShipoutNext{<コード>}〈新atbegshi〉:“次回用”に追加。 ※新atbegshiでは\AtBeginShipoutBoxは\ShipoutBoxと等価。
shipout/background:直接位置指定で各ページの背景に描画する内容。shipout/foreground:直接位置指定で各ページの前景に描画する内容。
※backgroundとforegroundのコードはページ左上隅を原点とするpicture環境内で実行される。単純に「全ページに挿入する」という目的でも使える。- atbegshiでの類似の機能は
\AtBeginShipoutUpperLeft(Foreground)であるが、インタフェースが少し異なる。\AtBeginShipoutUpperLeft(…)はそれ自身はフックでなく\AtBeginShipoutBoxを操作する命令であり、他のatbegshiのフック中で使われる想定である。従って、新atbegshiの実装もフックに帰着されるのではない。
- atbegshiでの類似の機能は
shipout/firstpage:最初のページに挿入する内容。\AtBeginDvi{<コード>}AtBeginShipoutFirst{<コード>}〈新atbegshi〉
shipout/lastpage:最後のページに挿入する内容。
※2回コンパイルが必要。\AtEndDvi{<コード>}※元々はatenddviの機能。
最終的にページ出力されるボックスの中では、以下の順で内容が配置されている。
shipout/firstpageの内容(先頭ページのみ)shipout/backgroundの内容- 元の出力ボックスの内容を
shipout/beforeで加工したもの shipout/foregroundの内容shipout/lastpageの内容(最終ページのみ)
※1つのフック内では“次回用”のコード片は最後に実行されることに注意。
ファイル読込
filehookパッケージの仕様に従っている。filehookを置き換えるためのラッパーであるfilehook-ltxパッケージが作成されているが、まだ一部の機能が実装されていないため、filehookを置き換えるようにはなっていない。 filehookが読み込まれた場合は、その実装がそのまま使われる。
※ファイル名はパス無しで拡張子付の名前。
file/before:何かのファイルが読まれる直前。\AtBeginOfEveryFile{<コード>}〈filehook-ltx〉
file/before/ファイル名:そのファイルが読まれる直前。\AtBeginOfFile{<ファイル名>}{<コード>}〈filehook-ltx〉
file/after☆:何かのファイルが読まれた直後。\AtEndOfEveryFile{<コード>}〈filehook-ltx〉
file/after/ファイル名☆:そのファイルが読まれた直後。\AtEndOfFile{<ファイル名>}{<コード>}〈filehook-ltx〉
package/before:何かのパッケージが読まれる直前。\AtBeginOfPackages{<コード>}〈filehook-ltx〉
package/before/パッケージ名:そのパッケージが読まれる直前。\AtBeginOfPackageFile{<パッケージ名>}{<コード>}〈filehook-ltx〉
package/after☆:何かのパッケージが読まれた直後。\AtEndOfPackages{<コード>}〈filehook-ltx〉
package/after/パッケージ名☆:そのパッケージが読まれた直後。\AtEndOfPackageFile{<パッケージ名>}{<コード>}〈filehook-ltx〉
class/before:何かのクラスが読まれる直前。\AtBeginOfClasses{<コード>}〈filehook-ltx〉
class/before/クラス名:そのクラスが読まれる直前。\AtBeginOfClassFile{<クラス名>}{<コード>}〈filehook-ltx〉
class/after☆:何かのクラスが読まれた直後。\AtEndOfClasses{<コード>}〈filehook-ltx〉
class/after/クラス名☆:そのクラスが読まれた直後。\AtEndOfClassFile{<クラス名>}{<コード>}〈filehook-ltx〉
include/before:\includeでのファイル読込において、事前の\clearpageの直後。\AtBeginOfIncludes{<コード>}〈filehook-ltx〉
include/before/ファイル名:前項と同様で特定ファイルに限ったもの。\AtBeginOfIncludeFile{<ファイル名>}{<コード>}〈filehook-ltx〉
include/end☆:\includeでのファイル読込において、事後の\clearpageの直前。\AtEndOfIncludes{<コード>}〈filehook-ltx〉
include/end/ファイル名☆:前項と同様で特定ファイルに限ったもの。\AtEndOfIncludeFile{<ファイル名>}{<コード>}〈filehook-ltx〉
include/after☆:\includeでのファイル読込において、事後の\clearpageの直後で、書込対象の.auxを本体に戻す前。\AfterIncludes{<コード>}〈filehook-ltx〉
include/after/ファイル名☆:前項と同様で特定ファイルに限ったもの。\AfterIncludeFile{<ファイル名>}{<コード>}〈filehook-ltx〉
ファイルを読み込んだときに実行されるコードの順番。
※ 〇印はパッケージまたはクラスの場合のみ。
- 〇
package/beforeまたはclass/beforeの内容。 - 〇
package/before/名前またはclass/before/名前の内容。 file/beforeの内容。file/before/名前の内容。- ファイル自体の内容。
file/after/名前の内容。file/afterの内容。- 〇
\AtEndOfPackageまたは\AtEndOfClassの内容。 - 〇
package/after/名前またはclass/after/名前の内容。 - 〇
package/afterまたはclass/afterの内容。
まとめ
だめだ 新しいLaTeX なにもわからない 😭😭😭#TeX #TeXLaTeX #マジで
— 某ZR(ざんねん🙃) (@zr_tex8r) 2020年9月25日