LaTeX Workshop のインテリセンスを強化する方法

<!-- # LaTeX Workshop のインテリセンスを強化する方法 -->

LaTeX Workshop では、さまざまなパッケージのサジェストをサポートしています。
プリアンブルで `\usepackage` するとそのパッケージから提供されるコマンドや環境のサジェストが受けられるのは、これのおかげです。

しかしながら、公式インストールされた拡張機能でサポートされるパッケージは約 240 であり、それほど多くのパッケージをサポートしているわけではありません。
サポートされていないパッケージの例として、日本語に関するパッケージ (otf, pxrubica...etc.) や unicode-math、chemfig 等が挙げられます。

そこで本記事では、より多くのパッケージをサポートできるようにインテリセンスデータをローカルに落として使えるようにする方法を紹介します。
加えて、パッケージのサジェストを拡充する方法も紹介します。

## 環境

本記事では、次の環境を前提にしています。

- LaTeX Workshop: 10.3.0 以降
- Windows 11

加えて、以下のツールが使えるようになっていることも前提とします。

- Git: 2.46.0.windows.1
- ts-node: 10.9.2
- Python: 3.10.11

## インテリセンスデータの取得

LaTeX Workshop リポジトリの [<samp>dev/packages/</samp>][github-latexworkshop-dev/packages] には公式インストールに含まれるインテリセンスデータを含む 4000 以上のインテリセンスデータ（JSON ファイル）があります。

[github-latexworkshop-dev/packages]: https://github.com/James-Yu/LaTeX-Workshop/tree/master/dev/packages "LaTeX-Workshop/dev/packages at master · James-Yu/LaTeX-Workshop"

これらのファイルをローカルに落とせば良いです。

### git sparse-checkout

どうやって持ってきても良いですが、本記事では Git を使った方法を紹介します。
また、LaTeX Workshop のリポジトリは今回欲しい JSON ファイル以外不要になります。そのため、これだけを取得するために git sparse-checkout を使います。

リポジトリの欲しいファイルやディレクトリのみを取得するには、以下のようにします。

1. LaTeX Workshop の <samp>.git</samp> のみを clone する
    ```bash
    git clone --filter=blob:none --no-checkout https://github.com/James-Yu/LaTeX-Workshop.git
    ```
1. <samp>LaTeX-Workshop/</samp> ディレクトリに移動
    ```bash
    cd LaTeX-Workshop
    ```
1. ローカルの `sparseCheckout` を `true` にする
    ```bash
    git config --local core.sparseCheckout true
    ```
1. sparse checkout を `set` する（※ `init` は非推奨になっています）
    ```bash
    git sparse-checkout set
    ```
1. VS Code で <samp>.git/info/sparse-checkout</samp> を開く
    ```bash
    code .git/info/sparse-checkout
    ```
1. sparse-checkout に以下を記述して保存する [^parse-cwl]
    ```sparse-checkout
    !/*/
    /data/
    !/data/packages/
    /dev/
    !/dev/githooks/
    /src/
    /.gitignore
    /CHANGELOG.md
    /LICENSE.txt
    /package.json
    /package-lock.json
    /README.md
    ```

    これによって、必要なファイル、ディレクトリのみを git clone できます。
1. sparse-checkout の内容を反映する
    ```bash
    git checkout
    ```

[^parse-cwl]: parse-cwl.ts と ctanpkglist\.py を利用するためのファイルが複数含まれています。不要であれば、`/src/` や `package.json`、`package-lock.json` を削除し、`!/dev/pyintel/` を追加する等してください。

これによって、以下のようなツリー構成になります。
<samp>dev/packages/</samp> に今回求めているインテリセンスデータの JSON ファイルが含まれています。（JSON ファイルは 4000 以上ありますが、30 MB 程度です）

```directory
LaTeX-Workshop/
├─ data/
├─ dev/
│	├─ packages/
│	├─ pyintel/
│	⋮
│	├─ ctanpkglist.py
│	├─ parse-cwl.ts
│	└─ README.md
├─ src/
├─ .gitignore
├─ CHANGELOG.md
├─ LICENSE.txt
├─ package.json
├─ package-lock.json
└─ README.md
```

sparse checkout で有効になっているファイル・ディレクトリは以下から確認できます。

```bash
git sparse-checkout list
```

:::note warn
LaTeX Workshop のバージョンによって JSON ファイルのフォーマットが変更される場合があります。利用している拡張機能のバージョンに合わせたリリースバージョンを利用しましょう。

Git では以下のコマンドによって、特定のバージョンに変更することが出来ます。

```bash
git reset --hard <release version>
```
:::

### オリジナルのインテリセンスデータを作成する

LaTeX Workshop のインテリセンスデータは [TeXstudio][] の CWL ファイルから作成されています。
しかしながら独自のパッケージ等、CWL ファイルが無いパッケージもあります。

[texstudio]: https://github.com/texstudio-org/texstudio/tree/master/completion "texstudio-org/texstudio: TeXstudio is a fully featured LaTeX editor. Our goal is to make writing LaTeX documents as easy and comfortable as possible."

したがって、以下の手順から JSON ファイルを作成しましょう。[^json-format]

[^json-format]: 直接 JSON ファイルを作成せずに CWL ファイルを作成するのは、LaTeX Workshop の JSON ファイルのデータ形式がバージョンによって変更される場合があるからです。

1. CWL ファイルを自作する
1. parse-cwl.ts を利用して CWL ファイルを LaTeX Workshop に対応した JSON ファイルに変換する [^pkgcommand]

[^pkgcommand]: 10.3.0 より前では pkgcommand\.py (Python) を使って作成していました。

#### CWL ファイルの作成

CWL ファイルは TeXstudio のドキュメントに [ファイルのフォーマット仕様][texstudio-doc-cwl] があります。
これを参照しながら CWL ファイルを作成しましょう。具体例は TeXstudio のリポジトリにたくさんあります。

[texstudio-doc-cwl]: https://texstudio-org.github.io/background.html#description-of-the-cwl-format "Background information - TeXstudio documentation"

例として、BXcoloremoji パッケージの CWL ファイルを作成してみました。（CWL ファイルを自動的に生成するツールは無いようです……）

<details>
<summary>BXcoloremoji のための CWL（折りたたみ）</summary>

```cwl
# bxcolroemoji package: v0.22
# https://github.com/zr-tex8r/BXcoloremoji

#include:binhex
#include:etoolbox
#include:twemojis

#ifOption:bxghost=true
#include:bxghost
#endif

#keyvals:\usepackage/bxcolroemoji#c
bbparam=#auto,true,false
bxghost=#auto,true,false
jatype=#auto,true,false
names#true,false
nodvidriver
preload-names=#auto,true,false
pua#true,false
resetdvidriver
twemojis
#endkeyvals

\coloremojisetup{keyvals}
#keyvals:\coloremojisetup,\usepackage/bxcolroemoji#c
family=%<name%>
no-image
scale=%<intger%>
size*=%<length%>
size=%<length%>
twemoji-pdf
twemoji-png
#endkeyvals

\coloremoji[option]{emoji}
\coloremoji{emoji}
\coloremoji*[option]{emoji}
\coloremoji*{emoji}
\coloremojicode[option]{emoji}
\coloremojicode{emoji}
\coloremojicode*[option]{emoji}
\coloremojicode*{emoji}
\coloremojicodefill{emoji}
\coloremojicodeline{emoji}
\coloremojifill{emoji}
\coloremojikeycapof[option]{emoji}
\coloremojikeycapof{emoji}
\coloremojikeycapof*[option]{emoji}
\coloremojikeycapof*{emoji}
\coloremojiucs{emoji}

\begin{coloremojilist}{emoji}
\end{coloremojilist}
\begin{coloremojiautolist}{emoji}
\end{coloremojiautolist}
\begin{coloremojicodelist}{emoji}
\end{coloremojicodelist}
\begin{coloremojicodeautolist}{emoji}
\end{coloremojicodeautolist}
```

</details>

#### CWL から JSON への変換

CWL ファイルを JSON ファイルに変換する parse-cwl.ts は TypeScript によるスクリプトです。

これを利用するには、必要な準備をする必要があります。

##### 準備

parse-cwl.ts を使うための準備として、はじめに <samp>dev/</samp> 内で以下を実行してください。<samp>LaTeX-Workshop/</samp> 内に <samp>node_modules/</samp> が作成されます。

```bash
npm install --save-dev @types/node
```

加えて、変換の対象となる CWL ファイルは <samp>dev/cwl/</samp> にある必要があります。また、作成された JSON ファイルは <samp>dev/packages/</samp> に配置されます。

事前にディレクトリを作成しておいてください。

```directory
dev/
├─ cwl/
└─ packages/
```

##### 使い方

parse-cwl.ts は JavaScript にトランスパイルせずに、[ts-node][] を使って <samp>dev/</samp> 内で以下のように直接実行します。（使い方の詳細は <samp>dev/README.md</samp> を参照してください）

[ts-node]: https://typestrong.org/ts-node/ "ts-node | ts-node"

```bash
ts-node parse-cwl.ts <package_name>.cwl
```

これによって、<samp>dev/packages/</samp> 内に JSON ファイルが作成されます。

## インテリセンスデータを配置したディレクトリの指定

ローカルに配置したインテリセンスデータが入っているディレクトリのパスを LaTeX Workshop に教えることで、パッケージを読み込むたびにインテリセンスデータが使えるようになります。

以下の設定を構成します。

```json
  "latex-workshop.intellisense.package.dirs": [
    // ここにインテリセンスデータ (JSON) が置いてあるディレクトリを絶対パスで指定する
    "X:\\path\\to\\LaTeX-Workshop\\dev\\packages",
  ],
```

もしも、オリジナルのインテリセンスデータを <samp>LaTeX-Workshop/dev/packages/</samp> と異なる場所に配置する場合は、このディレクトリも追加してください。

## パッケージサジェストの拡充

LaTeX Workshop では、`\documentclass` の文書クラス名や `\usepackage` のパッケージ名がサジェストとして表示されます。
このサジェストは非常に便利ですが、表示されるパッケージ名はちょっとだけ不十分です。

そのため、これらのためのインテリセンスデータをローカルで生成しても良いでしょう。

これらのインテリセンスデータは、以下の 2 つに収録されており、ctanpkglist\.py によって生成されます。

- classnames.json：文書クラス名用
- packagenames.json：パッケージ名用

これらのインテリセンスデータは VS Code 拡張機能のディレクトリ内に配置されています。

```directory
~/.vscode/extensions/james-yu.latex-workshop-**
├─ data/
│	⋮
│	├─ classnames.json
│	└─ packagenames.json
⋮
```

したがって、パッケージサジェストを拡張するには以下の手順を実行します。

1. ctanpkglist\.py を実行
    ```bash
    python -u ctanpkglist.py
    ```
1. 生成された classnames.json と packagenames.json を拡張機能の <samp>data/</samp> ディレクトリに配置する

ctanpkglist\.py は実行する作業ディレクトリにある extra-packagenames.json を読んで、CTAN API に含まれていないパッケージを補完します。CTAN に無いパッケージを利用している場合は、ここに追加しておきましょう。（文書クラス名を追加する方法は無いようです）

:::note warn
LaTeX Workshop のバージョンが更新されるたびに拡張機能のディレクトリは新しくなるため、そのたびに生成した classnames.json と packagenames.json を拡張機能のディレクトリに配置する必要があります。

適当にスクリプトを組んでおくと楽です。
:::

## 余談

LaTeX Workshop でインテリセンスデータを強化してみました :muscle:

公式インストールでは、特に日本語周りのパッケージのインテリセンスが足りないので、強化しておいて損はないはずです。

過去にインテリセンスデータとなる [JSON を手書きする記事][165d1180aa515655aebd] を書きましたが、あれは良くないですね。面倒すぎた……。

いつの頃からか、リポジトリに出来る限りのインテリセンスデータが公開されるようになったので、本記事の方法を採ることをお勧めします。

[165d1180aa515655aebd]: https://qiita.com/Yarakashi_Kikohshi/items/165d1180aa515655aebd "LaTeX Workshop のインテリセンスをカスタマイズする - Qiita"

### 日本語に関するインテリセンスデータ

platex、ptex、uptex の 3 つはパッケージとして利用されるデータファイルではないので、常に読み込まれるように `latex-workshop.intellisense.package.extra` で指定しておくと良いです。

```json
  "latex-workshop.intellisense.package.extra": [
    "platex",
    "ptex",
    "uptex"
  ]
```

これらのデータは日本語 LaTeX で使われる基本的なコマンド等が含まれています。