tcolorboxで枠付き定理環境を自作した

この記事は、[統合自然科学科 Advent Calendar 2023](https://qiita.com/advent-calendar/2023/integrated-sciences) の13日目の記事です。

以前、tcolorbox packageを用いて枠付きの定理環境を自作したので、そのことを思い出しながら書いていきます。
TeXが全然分からないなりに試行錯誤しながら作ったため、ベストでない可能性がありますが、ご容赦ください。

# 結論
- ネットにある定理環境では私のやりたいものが実現されていなかったので、自作した。
- ~~見た目や使い方はかなり実現できたが、「cleverefが使えない」などの一部問題もある。~~
    - 2023-12-24：解決しました！

# 実現したかったこと
次のことがやりたかったです。
- Thm.などを枠で囲って、地の文と完全に区別できるようにしたい。
    - （できればなるべくカッコいい枠で囲いたい。）
- Def.やThm.の番号を統一したい。（Def.1 → Thm.1ではなく、Def.1 → Thm.2など）
- ページの最後まで来たら、途中で次のページにまたぎたい。
- 定理名を入れるときに、__全角括弧で挿入したい！__
    - 個人的にはこれがデカかった（気がする）。

もしかしたら普通のやつでもできるかもしれないが、ぱっと見て全部は出来なさそうなので、自作することにしました。

# 作ったもの
次のようなものを作りました。
```tex:preamble
\documentclass[dvipdfmx]{jsarticle}
\usepackage{tcolorbox}
\tcbuselibrary{skins, breakable, theorems}
\usepackage{cleveref} %参照用
\newcommand{\kara}{} %無を出力するコマンド
\newtcolorbox[auto counter, number within=section, crefname = {Def.}{Defs.}]{definition}[3][]
{enhanced, breakable = true, fonttitle = \bfseries,
title = Def.~\thetcbcounter~\if #2\kara \else（#2） \fi,
#1,
label = thm:#3}
\newtcolorbox[auto counter, use counter from=definition, crefname = {Thm.}{Thms.}]{theorem}[3][]
{enhanced, breakable = true, fonttitle = \bfseries,
title = Thm.~\thetcbcounter~\if #2\kara \else（#2） \fi,
#1,
label = thm:#3}
\newtcolorbox[auto counter, use counter from=definition, crefname = {Prop.}{Props.}]{proposition}[3][]
{enhanced, breakable = true, fonttitle = \bfseries,
title = Prop.~\thetcbcounter~\if #2\kara \else（#2） \fi,
#1,
label = thm:#3}
\newtcolorbox[auto counter, use counter from=definition, crefname = {Lem.}{Lems.}]{lemma}[3][]
{enhanced, breakable = true, fonttitle = \bfseries,
title = Lem.~\thetcbcounter~\if #2\kara \else（#2） \fi,
#1,
label = thm:#3}
\newtcolorbox[auto counter, use counter from=definition, crefname = {Cor.}{Cors.}]{corollary}[3][]
{enhanced, breakable = true, fonttitle = \bfseries,
title = Cor.~\thetcbcounter~\if #2\kara \else（#2） \fi,
#1,
label = thm:#3}
\newtcolorbox[auto counter, use counter from=definition, crefname = {Rem.}{Rems.}]{remark}[3][]
{enhanced, breakable = true, colback = white, fonttitle = \bfseries,
title = Rem!~\thetcbcounter~\if #2\kara \else（#2） \fi,
#1,
label = thm:#3}

%変更に伴って必要なくなったものたち（2023-12-24）
%\newcommand{\defref}[1]{\hyperref[thm:#1]{Def.~\ref*{thm:#1}}}
%\newcommand{\thmref}[1]{\hyperref[thm:#1]{Thm.~\ref*{thm:#1}}}
%\newcommand{\propref}[1]{\hyperref[thm:#1]{Prop.~\ref*{thm:#1}}}
%\newcommand{\lemref}[1]{\hyperref[thm:#1]{Lem.~\ref*{thm:#1}}}
%\newcommand{\corref}[1]{\hyperref[thm:#1]{Cor.~\ref*{thm:#1}}}
```

こんな感じに入力します。
```tex:example.tex
\begin{theorem}{定理名}{ラベル名} %theorem：「Thm.n.m」としたい場合
hogehoge
\end{theorem}

%\thmref{ラベル名} %変更に伴って必要なくなったもの（2023-12-24）
\cref{thm:ラベル名}
```

こんな感じになります。

![example.tex](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3615490/d4ed4685-ef1f-d5d2-490a-9963b6badf40.jpeg)

以下で中身について解説していきます。

# 中身について
## 参考文献
- 主に実数さんの記事を参考にしました。
    - https://qiita.com/rityo_masu/items/5ef248024b294d72799a
- `\kara`と書いた部分については（おそらく）次の記事を参考に作りました。
    - https://marukunalufd0123.hatenablog.com/entry/2019/03/15/071717
- tcolorboxについて
    - 公式ドキュメント
        - https://ftp.yz.yamagata-u.ac.jp/pub/CTAN/macros/latex/contrib/tcolorbox/tcolorbox.pdf
        - （https://ctan.org/pkg/tcolorbox に置いてあります。）
    - 日本語では以下のものが詳しいです。
        - https://texmedicine.hatenadiary.jp/entry/2015/12/17/000339
- cleverefについて
    - 公式ドキュメント
        - https://jp.mirrors.cicku.me/ctan/macros/latex/contrib/cleveref/cleveref.pdf
        - （https://ctan.org/pkg/cleveref に置いてあります。）
    - 日本語の記事
        - https://qiita.com/wktkshn/items/110cd6007837938e6c88

## 各々の違い
- Def.,Thm.,Prop.,Lem.,Cor.：それぞれ定義、定理、命題、補題、系。動き方は全て同じ。
- Rem.：注意。これだけ上のものと変えている。（完全に私の好み。）
    - `colback = white`で背景色を白くしている。
        - Rem.以外はデフォルトの灰色。
    - 表示を「Rem.」ではなく「Rem!」としている。
        - 完全に私の好み。「注意！」って感じがしていいですよね。

## 各行の説明
TeX素人なので間違っている可能性があります。
- `\tcbuselibrary{skins, breakable, theorems}`：tcolorboxのライブラリ
    - `skins`：tikz関係で必要っぽい。（tikzはtcolorboxを入れた時点で一緒に入るらしい。）
    - `breakable`：ページまたぎを可能にする。
    - `theorems`：tcolorboxを用いた定理環境に必要。
- `\newcommand{\kara}{}`：無を出力するコマンド。名前が統一されていれば「kara」でなくて良い。
    - 下で行う場合分け（定理名部分が空白か否か）で必要になった。
- `\newtcolorbox[初期オプション]{名前}[#の個数][#1の初期値]{内容}`：tcolorboxの定義
    - `[初期オプション]`：このtcolorbox内のオプションを指定する。
    - `{名前}`：読み出すコマンド名。`{hoge}`とすると、`\begin{hoge}`等となる。
    - `[#の個数]`：個別に内容を追加する場所の個数。
        - `#n`：個別に内容を追加する場所。
    - `[#1の初期値]`：#1の初期値を初めから指定しておける。必要ない場合は空白にしておけばいい。
    - `{内容}`：枠内に書く内容。
- `auto counter`、 `number within=section`：定理の番号付け。セクション番号に対応できるようにする。
    - `use counter from=definition`：Thm.などの番号をDef.に合わせる。
- `crefname = {Def.}{Defs.}`：`cleveref`用の設定。
    - 一つ目の{}が単数の参照（Def.1.1）に、二つ目の{}が複数の参照（Defs.1.1-1.2）に対応する。
    - `cleveref`については、この記事などを参照：https://qiita.com/wktkshn/items/110cd6007837938e6c88
- `enhanced`：tikzの複雑な処理を可能にする（らしい）。
- `breakable = true`：ページまたぎをする。大きな枠を使う時に、余白を残して次のページに行ってしまうことがないようにする。
- `colback = white`：背景色を白くする。（上ではRem.にのみ適用。）
- `fonttitle = \bfseries`：次にあるtitle部分を太字にする。
- `title = Def.~\thetcbcounter~\if #2\kara \else（#2） \fi`：定理番号、定理名の設定。
    - 番号を「Def.n.m」のように出力する。
    - 定理名部分が空白（`kara`）なら何もしない。そうでないなら、全角括弧で定理名を括って出力する。
    - `\thetcbcounter`：番号の出力。
    - `\if #2\kara \else（#2） \fi`：if文。`\fi`はifの終わりを指す。
        - 上に書いたように、`\if #2\kara`は#2の部分が空白だった時には何も出力しない。そうでない場合（`\else`）、#2の内容を全角括弧で括って出力する。
        - つまり、**何も書かない場合は「Def.n.m」、定理名を書いた場合は「Def.n.m（定理名）」となる**。
- `label = thm:#3`：定理のラベル。
    - 上ではDef.やThm.に依らず、定理環境のものを全て「`thm：ラベル名`」としている。
    - これにより、Prop.からThm.に書き換える際などに、いちいちラベル名を書き換えなくていいようにしている。
- ~~`\newcommand{\defref}[1]{\hyperref[thm:#1]{Def.~\ref*{thm:#1}}}`：参照用の自作コマンド。~~
    - ~~`\defref{hoge}`と書くと「Def.n.m」と表示され、それを`\thmref{hoge}`と書き換えると「Thm.n.m」と表示される。（hoge：n.mのものに対応するラベル名）~~
    - `cleveref`を用いると、`cref{thm:hoge}`と書いて参照すれば良い。

# ~~現状の問題点~~（解決済み）
~~この定理環境の問題点として、参照に便利なcleveref packageが使えないという点があります。
これは、`cref{hoge}`と書けばhogeが定理なのか命題かなどを自動で判断し、「Theorem n.m」などと表示してくれるものらしいです。
（詳細はhttps://qiita.com/wktkshn/items/110cd6007837938e6c88 など。）~~

~~この記事に書いた定理環境では、本来の定理環境ではなく自作したものだからか、cleverefが適用されませんでした。
そのため、cleverefだと`\begin{theorem}`と`\end{theorem}`の2つだけを書き換えればいいものを、この記事の定理環境ではそれに加えて上で作成した`\thmref{hoge}`の部分もいちいち書き換える必要があります。~~

~~（とはいえ私が詳しくないだけで、もう少し弄ればうまく使える可能性もあります。その辺のことは分かったら追記します。）~~

2023-12-24追記：
私が見落としていただけで、tcolorboxのdocument p.128に`cleveref`による参照方法が載っており、これを用いた方法に書き換えました。このことを教えてくれた友人に感謝します。