☃️

パッケージ作成者のためのLaTeXマクロマニュアル

2022/03/19に公開

編集協力:博ノ助(Zenn/Github

はじめに

\TeXマクロ用の日本語版マニュアルがなかったので以下を参照してこの記事を書きました。
https://ftp.kddilabs.jp/CTAN/info/macros2e/macros2e.pdf
前提知識がない場合は、以下の記事を一通り読んでからこの記事をお読みください。
https://texwiki.texjp.org/?TeX入門%2Fマクロの作成

変数

一時的な変数

次の整数値の一部は、\countdef(-1の場合)、\chardef(0以上255以下の場合)、\mathchardef(256以上の場合)を使用して定義されています。これらは\edefでは展開されません。割り当ての右側で使用すると、カウントレジスタと同じように機能します。

訳注

展開とは、\<マクロ名>のような抽象化された状態から定義された内容に置き換えることをさします。例えば、以下のような命令は

example.tex
\def\macro{This is macro.}

This is body.\macro

このように置き換えられます。

example.tex
This is body.This is macro.

他の数値は通常のマクロとして定義され、単に展開されます。これらは、非整数であるフォントサイズを設定するために使用されることを目的に定義されています。

マクロ 定義方法
\@ne 1 \chardef
\tw@ 2 \chardef
\thr@@ 3 \chardef
\sixt@@n 16 \chardef
\@xxxii 32 \chardef
\@cclv 255 \chardef
\@cclvi 256 \mathchardef
\@m 1000 \mathchardef
\@M 10000 \mathchardef
\@Mi 10001 \mathchardef
\@Mii 10002 \mathchardef
\@Miii 10003 \mathchardef
\@Miv 10004 \mathchardef
\@MM 20000 \mathchardef
\@vpt 5 \def
\@vipt 6 \def
\@viipt 7 \def
\@viiipt 8 \def
\@ixpt 9 \def
\@xpt 10 \def
\@xipt 10 \def
\@xiipt 12 \def
\@xivpt 14.4 \def
\@xviipt 17.28 \def
\@xxpt 20.74 \def
\@xxvpt 24.88 \def
\m@ne -1 \countdef
sample
\documentclass[dvipdfmx]{jsarticle}
\begin{document}
\makeatletter

\the\@ne \par
\the\tw@ \par
\the\@cclv \par
\the\@cclvi \par
\the\@MM \par
\@vpt \par
\@xxvpt \par
\the\m@ne \par
\end{document}

1
2
255
256
20000
5
24.88
-1

ディメンション定数

次のディメンションとスキップ定数は、レジスタを使用して定義されます。これらは変更されてはいけません。

マクロ 定義方法 備考
\p@ 1pt \newdimen 結果として生じる乗算により、数値の背後にあるptの置換として使用できます
\z@ 0pt \newdimen 0ptと0の両方を意味します
\maxdimen 16383.99999pt \newdimen 最大有効寸法
\z@skip 0pt,±0pt \newskip
\hideskip −1000pt+\fill \newskip
\@flushglue 0pt+\fill \newskip
sample
\documentclass[dvipdfmx]{jsarticle}
\begin{document}
\makeatletter

\the\p@ \par
\the\maxdimen \par
\the\hideskip \par
\the\@flushglue
\end{document}

1.0pt
16383.99998pt
-1000.0pt plus 1.0fill
0.0pt plus 1.0fil

一定の文字列

以下のマクロは共通の文字列を保持し、完全に拡張可能です。
いくつかの特別な文字は、ここで文字通りASCII表現として定義されています。よって、そのような文字を補助ファイルに書き込む場合に便利です。

マクロ 備考
\space catcode 10の「スペース」。
\@spaces ␣␣␣␣ \space\space\space\spaceと同じ。
\empty 空の文字列 \letを使用して空のマクロを定義するために使用。
\@empty 空の文字列 上と同じ。\LaTeXのカーネルコマンドで用いられる。
\@backslashchar \ Catcode12。\writeで使用できる単純なASCII。
\@percentchar % Catcode12。\writeで使用できる単純なASCII。
\@charlb { Catcode11。
\@charrb } Catcode12。
\@clsextension cls \@currextとの比較に使用。
\@pkgextension sty \@currextとの比較に使用。
\@depth depth ボックスサイズ宣言\hb@xt@に使用。
\@height height ボックスサイズ宣言\hb@xt@に使用。
\@width width ボックスサイズ宣言\hb@xt@に使用。
\@minus minus スキップ宣言に使用。
\@plus plus スキップ宣言に使用。

一定のトークン

以下のマクロは、\let<マクロ>=<トークン>によって定義されています。
\letまたは\futureletで読み取られたトークンとの\ifx比較に役立ちます。

マクロ トークン Catcode 備考
\@sptoken スペース 10 \spaceと混同厳禁。
\bgroup { 1 グループの開始位置
\egroup } 2 グループの終了位置

その他

マクロ 定義方法 備考
\voidb@x (空) \newbox ボックスレジスタを永久に無効化します。
\@undefined (未定義) (未定義) このマクロは定義されていません。他のマクロが未定義かどうかを評価(\ifx)するか、未定義の状態に設定(\let)するために使用されます。

可変値

一時的な変数

次の可変値は、\LaTeXカーネルコマンドによってスクラッチレジスタとマクロとして定義され、使用されます。

一時的な変数 形式 定義方法
\count@ counter
\@tempcnta counter
\@tempcntb counter
\dimen@ dimension
\dimen@i dimension グローバル専用。
\dimen@ii dimension
\dimen@ima dimension
\dimen@imb dimension
\dimen@imc dimension
\@tempa macro
\@tempb macro
\@tempc macro
\@gtempa macro グローバルにしなければならない一時的な定義用。
\skip@ skip
\@tempskipa skip
\@tempskipb skip
\toks@ token register
\@temptokena token register
\if@tempswa if switch
\@tempboxa box register 通常のセッター\@tempswatrue\@tempswafalseが付属しています。
\@let@token let \@Ifnextchar\futureletを使用して次のトークンを一時的に保存するために使用します。似たような目的に使用できます。

ディメンション変数

マクロ 説明
\@wholewidth このディメンジョンレジスタは、picture環境で完全な線幅(厚さ)を保持します。
\@halfwidth このディメンジョンレジスタは、picture環境で半分の線幅(厚さ)を保持します。

文字列とその他の変数

マクロ 説明
\@currext 現在のパッケージまたはクラスファイルの拡張子。外部では空。
\@currname 現在のパッケージまたはクラスファイルのファイル名。外部では空。
\@currenvir 現在の環境の名前。
\@currenvline 現在の環境の開始の行番号。
\@currentlabel \labelが指す値。\stepcounter\refstepcounterで設定。

マクロ

マクロの定義

  • マクロ\<名前>\defで定義。 \long,\globalの接頭辞を付けることができます。
\@namedef{<名前>}<パラメータ>{<定義>}
  • マクロ\名前を展開。
\@nameuse{<名前>}
  • トークンBトークンAに等しいかどうかを評価します。
\@ifnextchar<トークンA>{<trueの時の処理>}{<falseの時の処理>}<トークンB>
訳注

\@ifnextcharは後のトークンを参照しますが、これは他マクロの\futureletの働きのため必ずしも"直後"とは限りません。以下に例を示します。

example.tex
\def\exampleA{\fbox{\@ifnextchar\token[{true}{false}}}
\def\exampleB{\@ifstar{}{\@ifnextchar\token[{true}{false}}}

\exampleA\token
\exampleB\token
output
false
true

\exampleA及び\exampleBはともに\@ifnextcharの直後は}ですが、\fbox{}}が評価対象(トークンB)になっているのに対し、\@ifstarでは意図した形で評価されています。


また、\@ifnextcharの例として以下のようにある程度自由な数の引数をとるマクロを実装することができます。

example.tex
\def\macro{\@ifnextchar[{\macro@pri}{Nothing}}
\def\macro@pri[#1]{\@ifnextchar[{\macro@sec[#1]}{This is #1}}
\def\macro@sec[#1][#2]{\@ifnextchar[{\macro@ter[#1][#2]}{This is #1 and #2}}
\def\macro@ter[#1][#2][#3]{This is #1, #2 and #3}

\macro
\macro[example]
\macro[example][TeX]
\macro[example][TeX][Zenn]
output
Nothing
This is example
This is example and TeX
This is example, TeX and Zenn

こうすることでオプショナルな引数を実装し、処理を分けることができました。

  • マクロ直後のトークンが*付きであるかどうかを評価します。
\@ifstar{<trueの時の処理>}{<falseの時の処理>}
  • <コマンド>[<引数>]<コマンド>{<引数>}に展開します。
\@dblarg{<コマンド>}{<引数>}
  • \<名前>が未定義かどうか(かつ\relaxでないかどうか)を評価します
\@ifundefined{<名前>}{<trueの時の処理>}{<falseの時の処理>}
  • \<名前>が未定義であり、名前が"relax"ではないかつ"end"から始まらない、および\end<名前> が定義されていないかどうかを評価します。
\@ifdefinable\<名前>{<trueの時の処理>}
  • 指定された<マクロ>は、プリアンブルでのみ有効であるとマークします。
    "AtBeginDocument"というエラーメッセージとして再定義されます。
\@onlypreamble<マクロ>
  • \l@ngrel@xが見つかった場合、次のアスタリスクのテストは\relaxに許可されますが、そうでない場合は\longになります。
    これは、潜在的な接頭辞として\defの前に使用できます。
\@star@or@long
  • \@ifnextchar[{<1>}{<1>[{<2>}]}の省略形。
    つまり、何も指定されていない場合、<2>がデフォルトの引数として使用されます。
\@testopt{<1>}{<2>}
  • \@testoptの堅い表現。
\@protected@testopt
  • トークンレジスタにコードを追加。
\addto@hook<トークンレジスタ>{<コード>}
  • マクロの定義にコードを追加します。
\g@addto@macro<マクロ>{<コード>}

引数の増減

マクロ 説明
\@gobble{<引数>} 自身の引数を削除。
\@gobbletwo{<1>}{<2>} 自身の2つの引数を削除。
\@gobblefour{<1>}{<2>}{<3>}{<4>} 自身の4つの引数を削除。
\@gobblecr 続く改行を削除し、そうでない場合はスペースを無視。
\@firstofone{<引数>} 引数に展開されます。つまり、{}を消すために使用されます。
\@iden{<引数>} "Identity"を意味する。互換性のため、\@firstofoneと同じ。
\@firstoftwo{<1>}{<2>} <2>を消して<1>を展開。
\@secondoftwo{<1>}{<2>} <1>を消して<2>を展開。
\@thirdofthree{<1>}{<2>}{<3>} <1>と<2>を消して<3>を展開。
\@expandtwoargs\macro{<1>}{<2>} \edefを使用して2つの引数を展開し、\macroに与えます。

リスト

  • <1><2>に存在するかどうかを評価し、\ifin@を設定します。
\in@{<1>}{<2>}
  • カンマ区切りのリストから要素を削除し、制御綴(コントロールシーケンス)に入れます。
\@removeelement{<要素>}{<リスト>}{<制御綴>}

ループ

マクロ 説明
\loop ... \iterate ... \repeat
\@whilenum<評価>\do{<ボディ>} \ifnumを使ったwhileループ
\@whiledim<評価>\do{<ボディ>} \ifdimを使ったwhileループ
\@for<マクロ>:=<リスト>\do{<ボディ>} forループ。<リスト>はカンマ区切りのリストに展開されることになっています。リストの各要素に<マクロ>を定義し、毎回<ボディ>を実行します。空のリストをエラーなく処理できます。
\@tfor<マクロ>:=<リスト>\do{<ボディ>} Forループ。<リスト>は展開されず、トークンまたは{...}のリストとして取得されません。<リスト>の各要素に<マクロ>を定義し、毎回<ボディ>を実行します。空のリストをエラーなく処理できます。
\@break@tfor \@tforループを終了します。これは\fiのスコープ内で呼び出す必要があります。

次のマクロは、colorまたはxcolorパッケージによって追加された、実際のコードのプレースホルダーとして、\LaTeX 2\epsilonによって\relaxと同じ意味で定義されています。
保存したボックス内の色を正しく処理するために必要です。例は、\sboxの定義を参照してください。

マクロ colorパッケージによる定義
\color@begingroup \begingroup
\color@endgroup \endgroup
\color@setgroup \begingroup\set@color
\color@hbox \hbox\bgroup\color@begingroup
\color@vbox \vbox\bgroup\color@begingroup
\color@endbox \color@endgroup\egroup

補助マクロ

この補助マクロは、もともとフォントの変更を処理するために定義されていましたが、他のコードにも使用できます。

マクロ 説明
\ifnot@nil{<1>}{<2>} <1>\@nilトークンである可動化を評価します。trueであれば<2>を無視し、falseであれば、\@firstofone<2<{}を外します。
\@nil このマクロは意図的に未定義であり、トークンリストを処理するループやその他のマクロのエンドマーカーとして使用されます。
\@nnil 定義には\@nilのみが含まれており、\ifnot@nil\@nilの存在を評価するために使用されます。エンドマーカーとしても使用されます。
\remove@to@nnil \@nnilを含む、その背後にあるすべてのものを削除します。
\remove@star *を含む、その背後にあるすべてを削除します。
\zap@space<テキスト>␣\@empty <テキスト>からすべてのスペースを削除します。展開可能。
\strip@prefix 次の>までのすべてを削除します。

Catcode

マクロ 説明
\@makeother{<文字>} <文字>のCatcodeをvに変更します。特殊な文字はバックスラッシュでエスケープする必要があります。
\@sanitize {}を除くすべてのcatcodeを"other"(Catcode 12)に変更します。
\@onelevel@sanitize<マクロ> <マクロ>をサニタイジングし、定義を文字通りのコードに変換します。スペース以外の文字は、"other"(Catcode 12)になります。\meaning\strip@prefixを使用します。

メッセージ

  • メッセージ内では、このマクロは新しい行とそれに続く継続テキストを作成します。外部では\relaxと同じです。
\MessageBreak
  • <メッセージ>をログファイルに出力します。付属の\MessageBreakは、<続き>で始まる新しい行に影響します。
\GenericInfo{<続き>}{<メッセージ>}
  • ログファイルに<エラーメッセージ>を表示し、その後に<詳細な情報の参照先>を表示します。ユーザーが"h"を押すと、<ヘルプテキスト>が表示されます。
\GenericError{<続き>}{<エラーメッセージ>}{<詳細な情報の参照先>}{<ヘルプテキスト>}
  • ログファイルにのみ書き込みます。
\wlog{<ログメッセージ>}

ディメンション/リスト/スキップ

名前 説明
\@settopoint<レジスタ> <レジスタ>の小数点以下を切り上げ。
\rem@pt<ディメンション値> <ディメンション値><整数>.<小数>pt)から"pt"を削除する。もし<小数>が0に等しいければ、それと小数点のドットも削除されます。
\strip@pt<ディメンション> \theを使用して<ディメンション>を展開し、\rem@ptを使用して"pt"を削除します。
\@killglue 最後のスキップを削除(\unskips)し、サイズがゼロになるまでさらにスキップ(\lastskip)します。

\@defaultunits
ディメンションまたはスキップの割り当てのデフォルト単位を提供するために使用されます。他の単位は"pt"の代わりに使用できます。

\@defaultunits\dimen=#1pt\relax\@nnil

クラスとパッケージオプション

マクロ 説明
\@classoptionslist メインクラスのオプションのリスト。
\@unusedoptionlist 宣言されていないメインクラスへのオプションのリスト。
\@declaredoptions 現在のパッケージまたはクラスで宣言されたオプションのカンマ区切りリスト。リストは、オプションが宣言された順序です。

ファイル

マクロ 説明
\if@filesw falseの場合、パッケージは出力ファイルに生成または書き込みしてはいけません。\nofilesでfalseに設定します。
\if@partsw
\@currdir 現在のディレクトリを保持します。例えば、Unix OSの"./"。
\input@path 入力パスのリスト。各パスは、パス間の区切り文字のない{}で囲む必要があります。
\@filelist これまでに読み取られたすべてのファイルのカンマ区切りリスト。プリアンブルで\listfilesが使用されている場合にのみアクティブです。
\@inputcheck ファイル記述子を入力して、ファイルの存在を確認します。
\@unused 標準出力を割り当てるために使用される出力されるファイル記述子。\typeout でターミナルに書き込むために使用されます。
\@mainaux メインauxファイルのファイル記述子を出力します。
\@partaux ヘッダauxファイルのファイル記述子を出力します。
\@auxout ヘッダファイル内では、\@partauxを実行し、そうでない場合は\@mainauxを実行します。
\@partlist \includeonlyで定義されたカンマ区切りのリストを保持します。
\@pushfilename ファイル名、拡張子、現在の"@"のcatcodeをスタックファイルに保存します。
\@popfilename ファイル名、拡張子、現在の"@"のcatcodeをスタックファイルに保存します。
\@currnamestack スタックファイルの名前を出力します。
  • ファイル名を解析し、そのディレクトリ、名前ベース、拡張子を\filename@area,\filename@base,\filename@extに提供します。filename@extは、存在しない場合は\relaxにします。
\filename@parse{<ファイル名>}
  • マクロ \IfFileExists\InputIfFileExistsによって使われている)には、見つかったファイルの後にスペースが格納されます。
\@filef@und
  • 指定された拡張子( \jobname<拡張子>)のファイルを読み込み、その後の書き込み用に開きます。初期状態では、ファイルは空である。出力ファイル記述子\tf@<拡張子>を作成します。
\@starttoc{<拡張子>}
  • 出力ファイル記述子\tf@⟨ext⟩が存在したら、それを使って`<コード>を書きます。
\@writefile{<拡張子>}{<コード>}
  • 指定されたファイルが、\TeXによって直接、または\input@pathによって指定されたディレクトリのいずれかにあるかどうかを確認します。
\@iffileonpath{<ファイル名>}
  • 別のファイルが入力されたという警告メッセージ(のみ)を出力します。
\@obsoletefile{<新>}{<旧>}
  • <ファイル名>をファイルのリストに追加します。プリアンブルで\listfilesが使用されている場合にのみアクティブです。
\@addtofilelist{<ファイル名>}
  • 完全なファイル名で指定されたパッケージ、クラス、またはファイルのオプションリストを展開します。
\@ptionlist{<ファイル名>}
  • 指定されたパッケージ/クラス/ファイルが読み込まれているかどうかを検証します。
\@ifpackageloaded{<パッケージ名 >}{<trueの時の処理>}{<falseの時の処理>}
\@ifclassloaded{<クラス名>}{<trueの時の処理>}{<falseの時の処理>}
\@ifl@aded{<拡張子>}{<ベースファイル>}{<trueの時の処理>}{<falseの時の処理>}
  • 指定されたパッケージ/クラス/ファイルに指定されたオプションがロードされているかどうかを検証します。
\@ifpackagewith{<名前>}{<オプション>}{<trueの時の処理>}{<falseの時の処理>}
\@ifclasswith{<名前>}{<オプション>}{<trueの時の処理>}{<falseの時の処理>}
\@if@ptions{<拡張子>}{<名前>}{<オプション>}{<trueの時の処理>}{<falseの時の処理>}
  • 指定されたパッケージ/クラス/ファイルに、現在のバージョンよりも新しいバージョンがロードされているかどうかを検証します。
\@ifpackagelater{<名前>}{<日付 YYYY/MM/DD>}{<trueの時の処理>}{<falseの時の処理>}
\@ifclasslater{<名前>}{<日付 YYYY/MM/DD>}{<trueの時の処理>}{<falseの時の処理>}
\@ifl@ter{<拡張子>}{<ベースファイル>}{<date YYYY/MM/DD>}{<trueの時の処理>}{<falseの時の処理>}

フォント

マクロ 説明
\f@encoding 現在のフォントのエンコーディング形式を保持します
\f@family 現在のフォントファミリーを保持します。
\f@series 現在のフォントシリーズを保持します。
\f@shape 現在のフォントシェイプを保持します。
\f@size 現在のフォントサイズを保持します。(単位はptですが、末尾に"pt"はつきません)
\f@baselineskip 現在の行間幅の値を保持します。(単位はptですが、末尾に"pt"はつきません)
\f@linespread \baselinestretchの値を保持します。(単位はptですが、末尾に"pt"はつきません)
\@currsize 最後のフォントサイズ命令を保持します。(例えば\smallなど)
\curr@math@size 現在の数式サイズを保持します。
\curr@fontshape \f@encoding/\f@family/\f@series/\f@shape

段落

マクロ 説明
\@@par 単純な\LaTeX\par命令です。
\@setpar{<値>} \parに環境全体の変更を加えるために使用されます。\par\@parの両方を<値> に設定します。
\@restorepar \par\@parに定義します。

Space Hack

マクロ 説明
\@bsphack
\@esphack これらのマクロは両方とも、それらの間のコードが文書にスペースを挿入しないことを保証します。コード自体はテキストを生成せず、数式モードの開始や終了などといった、モードを変更すべきではありません。
\@Esphack @ignoreスイッチをtrueに設定する\@esphackの変種は、環境の\endの後に\ignorespacesを引き起こします。
\@vbsphack 目に見えないコンテンツが"vmode"に設定されていないことを保証する\@bsphackの変種。現在、\LaTeX自体では使用されていません。

マクロ 説明
\null 空の\hbox。何か入れなければならない場所を埋めるのに良い。
\strutbox \strutの寸法、つまり現在のフォントの最大高さと深さ、幅ゼロの枠。\ht\strutbox\dp\strutboxを使って、それを抽出するために使用することができます。
\@arstrutbox 配列と表の中で定義されています。\strutboxに似ていますが、\arraystretchで引き伸ばされています。
\@begin@tempboxa<枠>{<内容>} <内容>\@tempboxa<枠>\hboxまたは\vbox)として格納し、そのディメンションを\width\height\depth\totalheightに格納します。
\@end@tempboxa \@begin@tempboxa環境を終了します。
\hb@xt@
\hmode@bgroup \leavevmode\bgroup
\@settodim{<ディメンジョン制御綴>}{<長さレジスタ>}{<内容>}

<長さレジスタ>を、コンテンツの寸法(\ht\dp\wd)で指定されたディメンションに設定します。

\@settodim{\wd}{\@tempdima}{Hello World}

\@tempdimaを"Hello World"の幅に設定します。

進法変換

マクロ 説明
\hexnumber@{<数値>} <数値>から1桁の16進数(0〜9,A〜F)を返します。これは数値レジスタまたはスペースで終わる数値でなければなりません。
\@alph{<数値>} <数値>に対応する小文字アルファベットに展開します (1=a,2=b,...)。数値が26より大きい場合、\@ctrerrに展開されます。
\@Alph{<数値>} <数値>に対応する大文字アルファベットに展開します (1=A, 2=B,...)。数値が26より大きい場合、\@ctrerrに展開されます。
\two@digits{<数値>} 文字列として<数値>(カウントレジスタなど)を返し、必要に応じて"0"を追加して少なくとも2桁であることを確認します。

条件文

マクロ 説明
\if@compatibility \LaTeX 2.09互換モードがアクティブであるかどうかを示すように切り替えます。
\if@ignore 環境の後にスペースを無視するかどうか。\ignorespacesafterendtrueに設定します。
\if@minipage "minipage"ではtrue、"parbox"ではfalse。"parbox"のスペース、スキップ、段落インデントの追加に関係します。
\if@twoside 両面文書であるかどうかを示します。
\if@twocolumn 2段組モードがアクティブかどうかを示します。
\if@firstcolumn 最初の段が処理されたかどうかを示します。

Discussion