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日