LaTeX Newsを斜め読みしていきます。完全な翻訳を目指す類のものではなく、私が興味を持った項目だけを、ざっくり説明しようと思います。網羅性と正確性には期待しないでください。
今回はLaTeX News Issue 38, November 2023 (LaTeX release 2023-11-01)を読んでいきます。
タグ付きPDFプロジェクトからのニュース
アクセシビリティ向上のため、LaTeXソースから自動的にタグ付きPDFを出力することを目指す「タグ付きPDFプロジェクト」は順調に進捗している。最近は表組み環境(tabularxとlongtableの環境を含む)のサポートが実装された。現時点では、多くの機能は実験的なlatex-labバンドル内に実装されている。texdoc -l latex-lab
を実行すると、多くのドキュメント(残念ながら、今のところタグ付きではない)を閲覧できる。
重要なマイルストーンに近付いている
Lamport本で説明されているLaTeXのすべての基本的な機能に関するタグ付きPDF出力機能は達成されつつある。これらの標準機能に加えて、amsmath, hyperref, natbib, biblatexなどがすでにサポートされている。これらの機能を有効化するには、文書冒頭で以下の宣言を行う。
\DocumentMetadata{testphase={phase-III,math,tabular}}
現時点では、数式と表組みのサポートはまだphase-IIIに組み込まれていない。
プロジェクト用のGitHubリポジトリ
タグ付きプロジェクトに関連するIssue報告は以下のリポジトリに集約する:
これにより、latex2e
, latex3
, tagpdf
, hyperref
, pdfresources
等々多数のリポジトリにIssueが分散するのを防ぐことになった。Issueやdiscussionスレッドへの投稿を歓迎する。
フック、ソケット、プラグ
最近のLaTeXでは新しいフックの概念が導入されている。これらは既存のコマンドや環境に、それらの定義を上書きすることなく、機能を追加する上で重要な役割を果たす。こうしたフックにおいて重要な機能の1つとして、異なるパッケージによって追加されるコード断片を、必要に応じて、何らかのルールによって順番を並び替えられるようにすることが挙げられる(この点に関する詳細はLaTeX News Issue 32-34を参照)。
しかし、ときには排他的・独占的に(他のコード断片をキャンセルして)実行されるべきコード断片を差し込む “フック” が欲しい状況があり得る。例えば、脚注と下部フロートの関係(脚注を下部フロートの上に出すのか、下部フロートより下に出すのか)を定めるようなコードは、他の指定を行うコードとは併存できない。こうしたケースのため、新たにソケット(socket)とプラグ(plug)の概念が導入された。
ソケットとはコードの中でプラグ(名前の付いたコード断片)を挿入することができる場所のことである。あるソケットに別のプログを挿入したい場合、すでにソケット内にあるプラグは事前に除去される必要がある。ソケットはプラグが利用できる入力を持つことができる。これはコード内にコマンドを置いておいて、そのコマンドをあとから定義するのと大差がないが、統一的なインターフェースが提供されることでステータスチェックやトレーシングが容易になるメリットがある。
ソケットやプラグは次のようなシンタックスで作成することができる。
\NewSocket{〈ソケット名〉}{〈入力の数〉}
\NewSocketPlug{〈ソケット名〉}{〈プラグ名〉}{〈コード〉}
例えば、\NewSocket{foo}{0}
のようにfooソケットを定義すれば、直後から\UseSocket{foo}
という形でソケットを利用することができる。\NewSocket
で新しいソケットを宣言した時点で、noop
という何もしないプラグが自動的に作成・挿入される。ソケットに別のプラグを挿入する場合は\AssignSocketPlug
コマンドを利用する。
これらの新概念はタグ付きPDFプロジェクトにおいても重要な意味をもつ。今後さまざまなサードパーティ製パッケージはソケットとプラグを用いることで、LaTeX本体のコードを上書きすることなく、独自のタグ付けロジックを提供することができる。
以上は新しい概念の簡潔な説明だが、詳細はtexdoc ltsockets-doc
を参照されたい。
文書プロパティと相互参照
LaTeXは伝統的に\label
コマンドによって「ページ番号」と「現在のカウンタ値」という2種類の文書ローカルなプロパティを保存し、参照できるようにしてきた。このしくみは、refcount, smart-ref, cleveref, hyperref, tikzmarks, zrefなどさまざまなパッケージよって拡張されてきた歴史がある。
今回のリリースから、LaTeXカーネルは一般のドキュメントプロパティを扱うための機能を標準インターフェースとして提供する。これらの機能のコンセプトはzrefパッケージが由来となっているが、実装上の詳細はさまざまに異なっている。この新機能では、新しいプロパティの宣言とあらゆるプロパティ値の保存をサポートする。また、これらの値は展開可能な方法で取得することができる。
例えば、現在の章番号を保存するプロパティは次のように作成できる。
\NewProperty{chapter}{now}{?}{\thechapter}
第2引数はプロパティ値が(\shipout
を待たず)ただちに(now
)記録されることを意味している。第3引数は未定義ラベルを参照した場合等に使用されるデフォルト値を指定する。最後の引数には値を取得するためのコード(保存時に展開される)を与える。
実際に値を保存する際は、他のプロパティと合わせて以下のようにする。
\RecordProperties{mylabel}{chapter,page,label}
これによりchapter
, page
, label
の3プロパティがmylabel
というラベル(キー)に紐づいて保存される。
一方、保存された値を利用するには\RefProperty
コマンドを利用する。このコマンドは2つの引数を取る。第1引数がラベル名、第2引数がプロパティ名である。
\RefProperty{mylabel}{chapter}
LaTeXカーネルは以下の一般的なプロパティを提供する(抜粋)。
label
: 従来の\label
と同様の情報(\ref
で取れるもの)のテキスト表現page
: ページ番号のテキスト表現title
: タイトル(存在する場合のみ。例えばnamerefで設定可)target
: リンクターゲット(存在する場合のみ。例えばhyperrefで設定可)
その他にもpagetarget
, pagenum
, abspage
, counter
, xpos
, ypos
などが提供されている。
これらの新しい相互参照機構については、LaTeX2eコマンドのほかに、expl3向けの関数もある。詳細はtexdoc ltproperties-doc
を参照のこと。
文書プロパティの実態に関する注意(2024-06-13追記)
本稿の公開後、ZRさんから「最新のLaTeXカーネルにおいても、実際の\label
と\ref
の実装においては新しい文書プロパティ機構を用いたものになっておらず、今回紹介した機能を用いてもラベル情報の取得ができない」旨の解説記事が公開されました。
これは実態としてはご指摘の通りのようで、上記の説明は(明示的に\label
と\ref
の実装を置き換えたとは書いていないものの)ややミスリーディングなところがあります。オリジナルのLaTeX Newsの記述もほとんど同じような具合なので、本稿もそれに倣った書き方をしているものですが、ご注意ください。
ちなみにこの話には続報があり、LaTeXチームとしても将来的には無論この新しい文書プロパティ機構を標準の\label
, \ref
実装にも用いる意図はあるようです。しかし、現時点では互換性の問題(いきなり\label
, \ref
のような重要なコマンドの実装を大幅に変更するとさまざまなサードパーティ製パッケージが壊れてしまう)から文書プロパティを利用した実装に切り替えていないということのようです。
そういえばこの件はこの前Frankに直接意図を聞いたのだけど、これはやはり将来的には\label, \refのような普及した標準コマンドの内部実装をいずれ置き換える気持ちはあるらしい。
その時季については具体的には未定のようだけど、どこかのタイミングで「\DocumentMetadataがある場合の挙動は多くの後方互換性を捨てる」という変更をすることが念頭にあるらしく、おそらくそのときになるだろうと。
— ワトソン🔒 (@wtsnjp.com) Jun 8, 2024 at 9:20 PM
[image or embed]
新しいコマンドと改善されたコマンド
\IfExplAtLeastTF
: expl3のバージョンをテストする
その他の細かなコード変更
\verb*
とverbatim*
環境でタブ文字をサポート(これまでは通常のスペースとして扱われた)- ボックスコマンド(
\makebox
,\framebox
,\parbox
)の引数チェックを改善 - pdfTeXにおけるチルダ(
~
)の扱いを改善 \fpeval
(expl3では\fp_eval:n
)内での変数および関数定義が可能に