コマンドや環境がどのパッケージから提供されているのか知る方法

<!-- # コマンドや環境がどのパッケージから提供されているのか知る方法 -->

LaTeX で「コマンド・環境の名前は知っているけれど、どのパッケージから提供されているか分からない :confounded:」とか「不足しているパッケージがあるけれど、依存関係のあるパッケージを調べ上げてすべてインストールするのは面倒 :confused:」ということがあるでしょう。

そんな問題を簡単に解決するツールの紹介です。

## TeXFindPkg を使おう

:::note info
本記事では Version 2023E (2023-05-05) を使います。
:::

[TeXFindPkg][] はパッケージやその依存関係をパッケージ名、コマンド名、環境名から検索できるツールです。

[texfindpkg]: https://ctan.org/pkg/texfindpkg "CTAN: Package TeXFindPkg"

使い方は簡単で、ターミナルで `texfindpkg` に `query` アクションを付けて、オプションと検索したい名前を入力します。

```batch
texfindpkg query [オプション] [探したいコマンド・環境・ファイル]
```

オプションは以下の 3 つです。

- `-c`：コマンド
- `-e`：環境
- `-f`：ファイル

コマンドは `\` を除き、ファイルでは拡張子名を付けてください。また、当然ですが case sensitive です。

### 具体例

`\qty` がどのパッケージで提供されているかを調べるには、以下のようにします。

```batch
texfindpkg query -c qty
```

長いので次の折りたたみにターミナルでの実行結果を示します。

<details>
<summary>ターミナルの実行結果（折りたたみ）</summary>

```console
$ texfindpkg query -c qty
[tfp] you are using texlive
[tfp] ================================================
[tfp] found package file physics.sty with command \qty
[tfp] building dependency tree for physics.sty:
[tfp] ------------------------
[tfp] physics.sty (from physics)
[tfp] |- amsmath.sty (from amsmath)
[tfp]    |- amstext.sty (from amsmath)
[tfp]       |- amsgen.sty (from amsmath)
[tfp]    |- amsopn.sty (from amsmath)
[tfp]       |- amsgen.sty (from amsmath)
[tfp] |- xparse.sty (from l3packages)
[tfp] ------------------------
[tfp] texlive packages needed: physics amsmath l3packages
[tfp] these packages are already installed
[tfp] ================================================
[tfp] found package file sankey.sty with command \qty
[tfp] building dependency tree for sankey.sty:
[tfp] ------------------------
[tfp] sankey.sty (from sankey)
[tfp] |- etoolbox.sty (from etoolbox)
[tfp] |- tikz.sty (from pgf)
[tfp]    |- pgf.sty (from pgf)
[tfp]       |- pgfrcs.sty (from pgf)
[tfp]          |- everyshi.sty (from everyshi)
[tfp] |- tikzlibrarycalc.code.tex (from pgf)
[tfp] |- tikzlibrarydecorations.markings.code.tex (from pgf)
[tfp]    |- tikzlibrarydecorations.code.tex (from pgf)
[tfp] |- tikzlibrarydubins.code.tex (from sankey)
[tfp]    |- tikzlibrarycalc.code.tex (from pgf)
[tfp]    |- xfp.sty (from l3packages)
[tfp] |- xparse.sty (from l3packages)
[tfp] ------------------------
[tfp] texlive packages needed: sankey etoolbox pgf everyshi l3packages
[tfp] these packages are already installed
[tfp] ================================================
[tfp] found package file siunitx.sty with command \qty
[tfp] building dependency tree for siunitx.sty:
[tfp] ------------------------
[tfp] siunitx.sty (from siunitx)
[tfp] |- translations.sty (from translations)
[tfp]    |- etoolbox.sty (from etoolbox)
[tfp]    |- pdftexcmds.sty (from pdftexcmds)
[tfp]       |- infwarerr.sty (from infwarerr)
[tfp]       |- iftex.sty (from iftex)
[tfp] |- color.sty (from graphics)
[tfp] |- xspace.sty (from tools)
[tfp] ------------------------
[tfp] texlive packages needed: siunitx translations etoolbox pdftexcmds infwarerr iftex graphics tools
[tfp] these packages are already installed
[tfp] ================================================
[tfp] texlive packages not yet installed in total:
```

</details>

非常に煩雑な検索結果となるため、どのパッケージで提供されているのか分かりづらいですが、見るべきは `[tfp] found package file` のある行です。

この行を見れば、`\qty` が以下の 3 つのパッケージから提供されていることが分かります。

- physics\.sty
- sankey\.sty
- siunitx\.sty

同時に、`[tfp] texlive packages needed:` の行を見ると、必要なパッケージが一覧化されており、次行でインストールされていないパッケージが一覧化されます。

`\qty` の例ではどのパッケージでも `[tfp] these packages are already installed` と表示されており、すべてインストールされていることが分かります。

## 依存関係を考慮してインストール

`query` アクションを `install` アクションにすると、依存関係を考慮して必要なパッケージ等をインストールすることが出来ます。

例えば、私の TeX Live 環境では plaingeneric コレクションをインストールしていないため、chemfig パッケージを使うには simplekv パッケージが足りません。

その場合、以下のように `install` アクションを使って `-f chemfig.sty` を調べます。すると、依存関係から足りないパッケージを探して自動的にインストールします。

```batch
texfindpkg install -f chemfig.sty
```

<details>
<summary>ターミナルの実行結果（折りたたみ）</summary>

依存関係を表示し、simplekv パッケージが足りないことを検出、tlmgr を介して simplekv パッケージをインストールしています。

```console
$ texfindpkg install -f chemfig.sty
[tfp] you are using texlive
[tfp] ================================================
[tfp] building dependency tree for chemfig.sty:
[tfp] ------------------------
[tfp] chemfig.sty (from chemfig)
[tfp] |- simplekv.sty (from simplekv)
[tfp] |- tikz.sty (from pgf)
[tfp]    |- pgf.sty (from pgf)
[tfp]       |- pgfrcs.sty (from pgf)
[tfp]          |- everyshi.sty (from everyshi)
[tfp] ------------------------
[tfp] texlive packages needed: chemfig simplekv pgf everyshi
[tfp] texlive package not yet installed: simplekv
[tfp] installing texlive package: simplekv
tlmgr.pl: package repository https://ftp.yz.yamagata-u.ac.jp/pub/CTAN/systems/texlive/tlnet (verified)
[1/1, ??:??/??:??] install: simplekv [143k]
running mktexlsr ...
done running mktexlsr.
tlmgr.pl: package log updated: D:/texlive/2024/texmf-var/web2c/tlmgr.log
tlmgr.pl: command log updated: D:/texlive/2024/texmf-var/web2c/tlmgr-commands.log
```

</details>

反対に、必要なパッケージが揃っている場合は `[tfp] this package is already installed` と表示されます。

:::note warn
`install` アクションで `-c` や `-e` オプションを使うことは注意が必要です。

TeXFindPkg は検索されたコマンドや環境を提供しているパッケージとその依存関係を調べますが、`install` アクションはそれらすべてで足りないパッケージをインストールしようとします。

不用意に多くのパッケージをインストールすることになりかねないので、`install` アクションは `-f` のみにしておく方が良いでしょう。
:::

# 余談

`query` アクションでパッケージを探す場合、適当にラッパースクリプトを作って、パッケージ名だけを抽出するようにした方が見やすいかもしれません。（とは言え頻繁に使うツールではないですが）

<details>
<summary><code>texfindpkg help</code>（折りたたみ）</summary>

```terminal
$ texfindpkg help
usage: texfindpkg <action> [<options>] [<name>]

valid actions are:
   install      Install some package and its dependencies
   query        Query dependencies for some package
   help         Print this message and exit
   version      Print version information and exit

valid options are:
   -f           Query or install by file name
   -c           Query or install by command name
   -e           Query or install by environment name

please report bug at https://github.com/lvjr/texfindpkg
```

</details>