最近$\LaTeX$で文書を書く際,自作のパッケージが必要になった.作り方もわからず,いろいろ調べて大変だったので,この記事にまとめておこうと思う(書き方に統一感がない箇所もあるが,大目に見てほしい).なお,クラスやパッケージという言葉の定義はいくつかの文献を見て自分なりに判断したもので,正しさは保証できない.詳しく知りたい人は参考文献[4]などを読んでほしい.
##パッケージとは
$\LaTeX$で読み込むファイルはクラスファイル(.cls),スタイルファイル(.sty)に大別できる.前者はjsarticle.clsのように\documentclass{jsarticle}
で読み込んで文章の体裁を設定し,後者はgraphicx.styのように\usepackage[dvipdfmx]{graphicx}
で読み込んでコマンドを追加する.それぞれを(ドキュメント)クラス,パッケージともいう.以下ではパッケージについて述べる.
##パッケージの構成
[4]によるとパッケージは
- Identification
- パッケージがどのバージョンの$\LaTeX$対応かを示し,パッケージ情報を記述する.
- Preliminary declarations
- いくつかのコマンドを定義し,他のファイルを読み込むこともできる.ここで定義したり読み込んだりするコマンドはふつう,オプションを宣言する際に必要となるものだけである.
- Options
- オプションを宣言,処理する.
- More declarations
- ここがパッケージのメイン.新しい変数やコマンド,フォントを宣言したり,他のファイルを読み込んだりする.
という構成になっている.いくつかのコマンドを定義するだけの簡単なパッケージであればMore declarationsにコマンドの定義だけを書いて,拡張子".sty"を付けて保存すれば良い.僕の場合はオプションによってコマンドの動作を条件分岐させるようなパッケージを書きたかったのでOptionsが必要になった.
自分専用のパッケージを作る分にはIdentificationは書かなくてもいいと思うが,一応それも含めて,次は各部分の具体的な書き方についてみていこう.
##パッケージの具体的な書き方
###Identification
パッケージを書くにあたり,まずパッケージそのものの情報を記述する.これは次のように書く.
\NeedsTeXFormat{<latex-format>}[<date>]
\ProvidesPackage{<package>}[<date> <other information>]
\NeedsTeXFormat
コマンドは必要な$\LaTeX$のバージョンを,\ProvidesPackage
コマンドはパッケージ情報を宣言する.[6]によればこれを書いておくと警告を出したりしてくれるらしいが,自分専用のパッケージを書く際には必要ないかもしれない.
<latex-format>
はパッケージを使用するのに必要な$\LaTeX$のバージョンであり,欧文用であればLaTeX2e
,和文用であればpLaTeX2e
とする.と[6]に書かれているが,とりあえずLaTeX2e
と書いておけばいいと思う.
<package>
はパッケージ名である.スタイルファイル名がtest.styなら拡張子をとって"test"とつけるのが良いと思うが,ファイル名test.sty,パッケージ名"te"としてTeXworksで試したところエラーは出なかった(ただし.一応警告は出ていましたが,コンパイルはしてくれました.\usepackage
でパッケージを読み込む際はスタイルファイル名(今の場合"test")を用いなければならない)
<date>
は日付であり,2020/04/20のようにYYYY/MM/DD
という形で書く.
<other information>
については調べても特に情報がなかったので,自分のメモ(例えば,文書を使用する分野(MathとかPhysicsとか))を書けばいいと思う.
<date>
と<other information>
に関しては任意なので,書かなくてもいい.
###Preliminary declarations
他のパッケージを読み込むには次のように書く.
\RequirePackage[<options-list>]{<package>}[<date>]
機能としては,通常のtexファイルにおける\usepackage
と同じだから説明は省く.パッケージ自作時に必要かどうかはわからないが,他のクラスを読み込む場合には\RequirePackage
のかわりに\LoadClass
と書けば良い.読み込む必要がなければ書かなくていい.
###Options
個人的にはこれが一番知りたかった.次のように書く.
\DeclareOption{<option>}{<code>}
\ExecuteOptions{<options-list>}
\ProcessOptions\relax
texファイルからパッケージを呼び出す際に\usepackage[<options-list>]{<package>}
のようにいくつかのオプション<options-list>
を指定して,パッケージの動作を呼び出し側が変更することができる.\DeclareOption
はこの<options-list>
の各々(<option>
)を指定した際の動作<code>
を記述する.パッケージに複数個のオプションを設定したければ\DeclareOption
を複数個書けばよい.
\ExecuteOptions
コマンドでは,\DeclareOption
で宣言したオプションのうち,デフォルトで(\usepackage
で読み込む際にオプションに指定しなくても)実行されるものを指定する(たぶん).
\ProcessOptions\relax
はOptionsの最後に書く.これはusepackage
で指定された<options-list>
に対応する<code>
を実行する.\DeclareOption
で宣言するだけでは,オプション指定された場合でも実行されないので,これは必ず書く.
###More declarations
ここではコマンドの定義とかを行うが,これについてはよく知られていると思う.一応書いておくと,コマンドを定義するには
\newcommand{\<command-name>}[<number-of-parameters>]{<definition>}
とする.例えば,偏微分のコマンドは
\newcommand{\pdiff}[2]{\frac{\partial#1}{\partial#2}}
と定義できる.$\partial{f}{x}$
と書けば$\frac{\partial f}{\partial x}$と表示される.
##自作パッケージの例
僕が作ったパッケージを例として掲載する.これは$\arcsin x$
と書く際,オプションに"arc"を指定(\usepackage[arc]{elementary}
)すれば$\arcsin x$のような表記,"inv"を指定(\usepackage[inv]{elementary}
)すれば$\sin^{-1}x$のような表記となるようなパッケージである.
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{elementary}
\newif\if@arc %2値変数@arcを定義
\DeclareOption{arc}{\@arctrue}
\DeclareOption{inv}{\@arcfalse}
\ExecuteOptions{arc}
\ProcessOptions\relax
%逆三角関数のコマンドを定義
\let\oldarcsin\arcsin
\let\oldarccos\arccos
\let\oldarctan\arctan
\renewcommand{\arcsin}{\if@arc \oldarcsin \else \sin^{-1} \fi}
\renewcommand{\arccos}{\if@arc \oldarcsin \else \cos^{-1} \fi}
\renewcommand{\arctan}{\if@arc \oldarcsin \else \tan^{-1} \fi}
\newcommand{\arccsc}{\if@arc \mathrm{arccsc} \else \csc^{-1} \fi}
\newcommand{\arcsec}{\if@arc \mathrm{arcsec} \else \sec^{-1} \fi}
\newcommand{\arccot}{\if@arc \mathrm{arccot} \else \cot^{-1} \fi}
%逆双曲線関数のコマンドを定義
\newcommand{\arsinh}{\if@arc \mathrm{arsinh} \else \sinh^{-1} \fi}
\newcommand{\arcosh}{\if@arc \mathrm{arcosh} \else \cosh^{-1} \fi}
\newcommand{\artanh}{\if@arc \mathrm{artanh} \else \tanh^{-1} \fi}
\newcommand{\arcsch}{\if@arc \mathrm{arcsch} \else \mathrm{csch^{-1}} \fi}
\newcommand{\arsech}{\if@arc \mathrm{arsech} \else \mathrm{sech^{-1}} \fi}
\newcommand{\arcoth}{\if@arc \mathrm{arcoth} \else \coth^{-1} \fi}
このパッケージで利用したいくつかの便利なコマンドについて説明しておく.まず
\newif\if@bool
というコマンドにより2値変数@bool
を定義できる.この変数の値(true,false)を設定するには
\@booltrue
\@boolfalse
のようにする.この変数を用いて条件分岐を行うには
\if@bool <code1> \else <code2> \fi
とすればよい([5]).
なお,ここでは"@"の付いた変数を使ったが,texファイルでは"@"付きの変数は\makeatletter
と\makeatother
の間でしか扱えない.そのため,texファイルで勝手に値を変更してほしくない変数には,パッケージ(styファイル)で"@"を付けて定義しておくとよい.styファイルでは普通に扱える.
次に
\let\copycommand\command
という形のコマンドであるが,これは定義済のコマンド\command
を新しいコマンド\copycommand
にコピーする.
##おわりに
以上でパッケージの作り方については一通り説明できたと思う.説明不足なところもあるかとは思うが,そういった箇所は参考文献を参照してほしい.
##参考文献
[1] LaTeX/Creating Packages
[2] とりぷる ぷぅ 技術メモ [TeX]Class, Package
[3] The LaTeX Project: Core Documentation
[4] The LaTeX Project: Core Documentation/LaTeX2e for class and package writers
[5] すぐできる! latex で if 文による条件分岐を使う方法。
[6] [改訂第7版]LaTeX2ε美文書作成入門