目的
LaTeX コンパイル環境を構築したい。LaTeX はモジュールや文字フォント等で複雑な依存関係がありそう、ということで、構築失敗による環境汚染を避けるために Ubuntu Docker コンテナで実現したい。LaTeX の文書作成 & PDF 閲覧は Windows 上の Visual Studio Code で行いたい。(あれもこれも、欲張りだなぁ ...)
前提
Windows 10 上には Visual Studio Code と SumatraPDF *1 が、WSL2 上には Ubuntu 20.04 LTS と Docker が既に導入されているものとする。
成果
以下の手順を踏むと Visual Studio Code にて次のことが可能になる。
- Ctrl + Alt + B (Build) でビルド
- Ctrl + Alt + V (View PDF) で PDF 閲覧
- Ctrl + Alt + C (Clear intermediate files) で中間ファイル削除
一度、ビルドが通ると、編集 → ファイル保存、するだけで自動リビルドされる。
TeX 記述サポートにおいても、@a
と書くだけで \alpha
に補完される、など Visual Studio Code はかなり便利。LaTeX Workshop のスニペットは こちら。
Ubuntu での LaTeX 実行環境構築
こちらの記事 によると Docker で日本語 LaTeX をやるには paperist/alpine-texlive-ja イメージで uplatex
コマンドを使うのがよいらしい。ということで、このイメージを Docker Hub から docker pull
しておく。次に ~/.bashrc
に以下のように記述しておく。
# latex through docker function func_tex2pdf() { docker run --rm -it -v /mnt/d/[working folder path on raw Ubuntu]/$1:/workdir paperist/alpine-texlive-ja latexmk -pdfdvi -latex=uplatex -e '$dvipdf=q/dvipdfmx %O -o %D %S/;' -synctex=1 -silent $1.tex; } alias tex2pdf=func_tex2pdf
これで WSL2 Ubuntu のコマンドラインから tex2pdf Sample
と打つことで、Docker コンテナをワンタイム起動し、コンテナ内の作業フォルダ /workdir
にある tex ファイルから同フォルダに pdf が生成できるようになる。ここでのポイントは以下のとおり。
- コンテナの
/workdir
は-v
オプションでホスト Ubuntu の作業フォルダにマウントしている - さらに当該 Ubuntu フォルダの実体は Windows 側の NTFS ドライブ (
/mnt/d/
すなわちd:/
) にある - 環境変数
$1
にはコマンドの第1引数 (上述の例では Sample) が入り、共通フォルダの下のサブフォルダ Sample を作業フォルダとしてその中の Sample.tex を対象ファイルとしている - 環境変数
$1
はalias
文内で2度使えないため、関数定義にする - オプション
-synctec
は後述 (Ubuntu 環境では利用する予定なし) - uplatex や dvipdf による一連の作業を latexmk を用いたワンライナーで実行する (texwiki 参照)
- 当該イメージ内に dvipdf がないため、代わりに dvipdfmx を用いることを Perl 表記の引数で指示している *2
- マウント対象パスのスペース文字はエスケープシーケンス \ ("\" + Space) になる
Visual Studio Code の LaTeX 作業環境構築
こちらの記事 に従い、Visual Studio Code に LaTeX Workshop 拡張機能をインストールする。
Visual Studio Code の JSON 設定
次に Power Shell から WSL を通じて上述の Docker イメージのワンタイム起動を行うように Visual Studio Code に設定する。ただし先ほど定義した .bashrc
の tex2pdf エイリアスをそのまま利用することはできない。Visual Studio Code の設定 (JSON ファイル *3 ) には以下のように記述する。
// -- LaTeX Workshop -- // 使用パッケージのコマンドや環境の補完を有効にする "latex-workshop.intellisense.package.enabled": true, // 生成ファイルを削除するときに対象とするファイル // デフォルト値に "*.synctex.gz" を追加 "latex-workshop.latex.clean.fileTypes": [ "*.aux", "*.bbl", "*.blg", "*.idx", "*.ind", "*.lof", "*.lot", "*.out", "*.toc", "*.acn", "*.acr", "*.alg", "*.glg", "*.glo", "*.gls", "*.ist", "*.fls", "*.log", "*.fdb_latexmk", "*.snm", "*.nav", "*.dvi", // "*.synctex.gz", // 中間ファイル消去後も SyncTeX 利用の場合はコメントアウト ], // ビルドのレシピ "latex-workshop.latex.recipes": [ { "name": "tex2pdf", "tools": [ "tex2pdf", ] }, ], // ビルドのレシピに使われるパーツ "latex-workshop.latex.tools": [ { "name": "tex2pdf", "command": "wsl", "args": [ "docker", "run", "--rm", "-v", "/mnt/d/[working folder path on raw Ubuntu]/%DOCFILE%:/workdir", "paperist/alpine-texlive-ja", "sh", "-c", "latexmk -latex=uplatex -synctex=1 -silent %DOCFILE%.tex && dvipdfmx %DOCFILE%.dvi" ], }, ], // PDF Viewer の表示方法 "latex-workshop.view.pdf.viewer": "tab", // Internal PDF Viewer // "latex-workshop.view.pdf.viewer": "external", // External PDF Viewer // SyncTeX "latex-workshop.view.pdf.internal.synctex.keybinding": "double-click", // or "ctrl-click" "latex-workshop.synctex.afterBuild.enabled": true, "latex-workshop.synctex.path": "synctex", "latex-workshop.synctex.synctexjs.enabled": true, // Internal PDF Viewer Settings "latex-workshop.view.pdf.zoom": "page-width", // External PDF Viewer "latex-workshop.view.pdf.external.viewer.command": "c:/Users/[user name]/AppData/Local/SumatraPDF/SumatraPDF.exe", "latex-workshop.view.pdf.external.viewer.args": [ "-reuse-instance", "%PDF%", ], "latex-workshop.view.pdf.external.synctex.command": "c:/Users/[user name]/AppData/Local/SumatraPDF/SumatraPDF.exe", "latex-workshop.view.pdf.external.synctex.args": [ "-reuse-instance", "%PDF%", "-forward-search", "%TEX%", // Sumatra PDF がなぜかこのパスを正しく認識しないため、順方向検索が無効 "%LINE%", "-inverse-search", "\"c:\\Users\\[user name]\\AppData\\Local\\Programs\\Microsoft VS Code\\bin\\code.cmd\" -r -g \"%f:%l\"", ],
ここまでの作業により、Visual Studio Code のビルドコマンドを実行すると、WSL と Docker を通じたワンライナーで TeX 文書をコンパイルするようになる。ここまでのポイントは以下のとおり。
- Power Shell から起動する
WSL
やbash
は対話シェルではないため、.bashrc
が反映されない - したがって、Power Shell から
WSL
コマンドでワンライナー起動する - 対話シェルではないため、
docker
コマンドの引数-it
は付けない - JSON 設定の latex-workshop.latex.tools セクションに記述するワンライナーが
.bashrc
と若干違うのは、dvipdf 設定の引数部分である Perl 記述が (どうエスケープシーケンスを書いても) 失敗してうまく起動しないため - 環境変数 %DOC% は用いず %DOCFILE% のみを用いるのが吉 (%DOC% の挙動が不安定で何度かハマっている。 参考記事 参照)
- オプション
-synctex
によりコンパイル時に .synctex.gz ファイルを生成し、これにより tex と pdf 両ファイルでの項目位置を紐づけ、クリックによる相互ジャンプを可能にする (後述) - マウント対象パスのスペース文字はエスケープシーケンス不要になる
PDF Viewer の設定
この記事 と この記事 を参考に synctex 関連を設定する。
Sumatra PDF を起動し、メニュー > 三 > 設定 > 詳細設定 を開き、設定ファイルの下記部分を修正する *4。
EnableTeXEnhancements = true InverseSearchCmdLine = "c:\Users\[user name]\AppData\Local\Programs\Microsoft VS Code\bin\code.cmd" -r -g "%f:%l"
これにより、Sumatra PDF をダブルクリックしたときに、逆順検索 (ダブルクリック箇所に対応する Visual Studio Code 上の LaTeX ファイル該当箇所へジャンプ) する。
課題
Visual Studio Code 内タブの PDF ビューアも外部 PDF ビューア Sumatra PDF も起動・表示・ビルド時再読み込みはうまく動作するが、いまのところ synctex は外部 PDF ビューアからの逆順検索しか成功しない ...
内部ビューアの場合は、おそらく Visual Studio Code 内の Ctrl 押しながら系の操作がキャンセルかインタラプトされている。
外部ビューアの場合は、Sumatra PDF が -forward-search
の次の引数のファイルパスを正しく読み込めていない。不明なソースファイル (C:\ ..... \Sample.tex) と表示される。そのパスにファイルがあるにも関わらず。
継続調査。