多くの設定が共通の tcolorbox を複数定義する (対話形式などに便利)

多くの設定が共通の tcolorbox を複数定義する (共通設定をまとめて記述する) だけです。参考文献 [1] の中でも同じことをやっていたのでこの記事は劣化版ですが、[1] は tcboxmath の話になっているので大元 tcolorbox でも同じと記す意味と、成果物の趣きも違うので別途記事にしてみます。

なお、この記事中にも最小の再現 TeX ファイルを載せていますが、成果物の例のキャプチャ画像の PDF がコンパイルできる TeX ファイル (とコンパイル結果) は以下のリポジトリにあります[^1][^2]。
[sample-report-0
](https://github.com/CookieBox26/notes-2024/tree/3d7de7bccd2ad7d9e6f5ee7bd8a5dcb677c5de7b/sample-report-0)

[^1]: リポジトリの TeX ファイルをコンパイルするには、お手元に MPLUS1 フォントをインストールするか、フォント指定箇所を適宜書き換える必要があります。
[^2]: そのような方がいるかはわかりませんが、もし私のイラストをそのまま利用してその文書を公開される場合は、イラストの著作者がクッキー (または CookieBox26 ) であることを表記ください。

### 参考文献
1. [LaTeXの数式を映えさせる - Qiita#スタイルに名前をつける](https://qiita.com/t_kemmochi/items/483b8fcdb5db8d1f5d5e#%E3%82%B9%E3%82%BF%E3%82%A4%E3%83%AB%E3%81%AB%E5%90%8D%E5%89%8D%E3%82%92%E3%81%A4%E3%81%91%E3%82%8B)
1. [LaTeX入門/LaTeXマクロの作成 - TeX Wiki](https://texwiki.texjp.org/?LaTeX%E5%85%A5%E9%96%80%2FLaTeX%E3%83%9E%E3%82%AF%E3%83%AD%E3%81%AE%E4%BD%9C%E6%88%90)

### 成果物の例
tcolorbox を利用すると下図のような対話ごっこができます。が、このとき各キャラクターのセリフの tcolobox は背景色や画像などを除いては同じ設定になると思います。なので、同じことを複数回記述したくないと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/177688/0b2e955f-eed1-8c83-2a7a-e841bdf2c957.png)

### TeX ファイル

以下のように共通設定をまとめて記述できます。`xelatex main.tex` でコンパイルできます (ただし `../images/` にキャラ画像ファイルが格納されている必要があります)。お使いのエンジンが xelatex でない場合はドキュメントクラス宣言を適宜変更ください。

```tex:main.tex
\documentclass[b5paper,xelatex,ja=standard,11pt]{bxjsarticle}

% 色名の読み込みと独自色定義
\usepackage[x11names]{xcolor}
\definecolor{PaleIris}{RGB}{229,227,246}
\definecolor{PaleGold}{RGB}{255,247,204}
\definecolor{PaleIris2}{RGB}{173,165,223}
\definecolor{PaleGold2}{RGB}{248,222,75}

% カラーボックス (most はページまたぎのため必要)
\usepackage[most]{tcolorbox}

% 独自のセリフ用カラーボックスの定義
\tcbset{
  % セリフ用カラーボックスの共通設定 (引数にキャラ画像ファイルパスを受け取る)
  serifubox/.style={
    enhanced,  % タイトルボックスの分離に必要 (タイトルボックスにキャラ画像をはめるため)
    breakable,  % ページをまたぐのに必要
    arc=7pt, top=7pt, right=7pt, left=7pt, bottom=7pt,  % パディング
    boxrule=0pt, frame hidden,  % フレーム隠蔽
    grow to left by=-31pt,  % キャラクター画像を表示するため左にマージン
    enlarge bottom by=-1pt, title={\,},
    attach boxed title to top left={xshift=-34pt, yshift=-40pt},
    boxed title style={
      enhanced, arc=19pt, top=17pt, right=15pt, left=17pt, bottom=17pt,
      boxrule=0pt, frame hidden, underlay={\begin{tcbclipinterior}
        \includegraphics[width=39pt,keepaspectratio]{#1}\end{tcbclipinterior}},
    }
  }
}
% 部長
\newtcolorbox{SERIFU1}[1][]{  % オプション引数を1つとる (規定値はなし)
  serifubox={../images/a0_.png},  % 部長の画像
  colback=PaleIris, colbacktitle=PaleIris2, #1
}
% 副部長
\newtcolorbox{SERIFU2}[1][]{
  serifubox={../images/b0_.png},  % 副部長の画像
  colback=PaleGold, colbacktitle=PaleGold2, #1
}

\begin{document}

\section*{はじめに}

\begin{SERIFU1}[enlarge top by=3pt]  % 節タイトル直後だけマージンをとりたいとき
こんにちは Hello こんにちは{\bf こんにちは}こんにちはこんにちは
こんにちはこんにちはこんにちはこんにちはこんにちはこんにちは。
\end{SERIFU1}

\begin{SERIFU2}
こんにちは Hello こんにちは{\bf こんにちは}こんにちはこんにちは
こんにちはこんにちはこんにちはこんにちはこんにちはこんにちは。
\end{SERIFU2}

\begin{SERIFU1}
こんにちは Hello こんにちは{\bf こんにちは}こんにちはこんにちは
こんにちはこんにちはこんにちはこんにちはこんにちはこんにちは。
\end{SERIFU1}

\end{document}
```

やっていることは以下です。
- `\tcbset` コマンドで serifubox という名前の共通設定を定義します。画像ファイルパスを引数にします。
- `\newtcolorbox` コマンドで SERIFU1, SERIFU2 という名前の tcolorbox を定義します。このとき、キャラごとの画像ファイルパス付きで serifubox を呼び出し、キャラごとの背景色も設定します。SERIFU1, SERIFU2 自体も一つのオプション引数を取るようにしてありますが、これは一時的に設定を変えて呼び出したいときにつかいます。

なお、背景色も serifubox の引数にしたいですが、やってみると `\tcbset` で定義する設定は1つの引数しか取れません (参考文献 [1] にも引数は1つとかいてあります)。

### 他の例

命題とコード (listings でシンタクスハイライトする) を tcolorbox で囲みたいということがあると思います。このとき、命題と同じ設定の tcolorbox に lstlisting を入れるとコードの上下に隙間が結構空くと思います。このようなときも、ほとんどの設定は共有しつつ上下の隙間だけは別々の値を設定することができます (以下)。

```tex:main2.tex
\documentclass[b5paper,xelatex,ja=standard,11pt]{bxjsarticle}
\usepackage[x11names]{xcolor}
\usepackage{listings}
\usepackage[most,listings]{tcolorbox}  % listings は tcolorbox 内で lstlisting するため

\lstset{  % listings のグローバル設定
  basewidth=0.5em,  % 字間詰め
  lineskip=-3pt,  % 行間詰め
  basicstyle={\ttfamily\color{black}},  % 全体フォント設定
  keywordstyle=[1]{\color{DodgerBlue3}},  % kewords[1]の設定 (Python だと予約語)
  keywordstyle=[2]{\color{VioletRed3}},  % kewords[2]の設定 (Python だと組み込み関数)
  stringstyle={\color{Firebrick3}},  % 文字列リテラルの設定
  commentstyle={\color{SeaGreen4}},  % コメントの設定
  showstringspaces=false,  % 半角スペース記号を表示しない (コピペの邪魔)
}

% 独自のカラーボックスの定義
\tcbset{
  % 個人的カラーボックスの共通設定 (引数にタイトルを受け取る)
  custombox/.style={
    breakable,  % ページをまたぐのに必要
    arc=2pt, colframe=DeepSkyBlue4, boxrule=1pt, colback=Snow1, right=7pt, left=7pt,
    title={\color{yellow}\textbf{#1}}
  }
}
% 独自の命題用カラーボックスの定義
\newtcolorbox{PROP}[2][]{  % オプション引数1つと必須引数1つとる (オプション引数の規定値はなし)
  custombox={#2}, top=7pt, bottom=7pt, #1
}
% 独自のコード用カラーボックスの定義
\newtcolorbox{CODE}[2][]{
  custombox={#2}, top=0pt, bottom=0pt, #1
}

\begin{document}

\begin{PROP}{定理 1.1}
$x^\ast$ を問題(P)の局所最適解とする。
\end{PROP}

\begin{CODE}[enlarge top by=3pt]{Python コード}  % オプション引数でボックス上部にマージンをとる
\begin{lstlisting}[language=python]
import numpy as np
\end{lstlisting}
\end{CODE}

\end{document}
```

上の TeX ファイルでは、PROP も CODE も 2 番目の引数が必須引数で、タイトルを受け取ります。そして、受け取ったタイトルを共通設定 custombox に渡しています。

一時的な設定変更用に PROP も CODE もオプション引数を受け取れるようにもしてあります。このとき、プログラミング言語でよくある方式と違って LaTeX ではオプション引数が最初の1つとなることに注意が必要です (もはや tcolorbox 特有の話ではないですが、LaTeX マクロでどう引数をとって呼び出し側からどう渡すかは規則を知らないとコードからはわからないと思います) (参考文献 [2] に詳しかったです)。