投稿日:
更新日:

brew + VSCode で TeX 環境を構築する

Authors

目次

はじめに

ソースコードだろうと論文だろうと VSCode で全てを完結させたい!

今回は、mactex-no-gui というパッケージを導入して VSCode に Tex 環境を構築してみました。

各種パッケージのインストール

Homebrew

### インストール
$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

### .zshrcに追加
- Intel chip (x64/x86/x86-64) の場合
基本的にはそのままで良い

- M1 chip (ARM) の場合
$ echo 'eval $(/opt/homebrew/bin/brew shellenv)' >> ~/.zshrc
$ eval $(/opt/homebrew/bin/brew shellenv)

### rezshする
$ source ~/.zshrc
$ exec $SHELL -l

### 確認
$ brew --version
Homebrew 3.4.11

VSCode

### インストール
$ brew install --cask visual-studio-code

### 確認
$ brew list | grep visual-studio-code
visual-studio-code

MacTeX

### インストール
$ brew install --cask mactex-no-gui

### rezsh(ここでrezshしておかないとlatexmkを認識してくれない場合があるっぽい)
$ exec $SHELL -l

### 確認
$ latexmk --version
Latexmk, John Collins, 7 Jan. 2023. Version 4.79

$ tlmgr --version
tlmgr revision 66457 (2023-03-08 00:07:12 +0100)
tlmgr using installation: /usr/local/texlive/2023
TeX Live (https://tug.org/texlive) version 2023

$ pdflatex --version
pdfTeX 3.141592653-2.6-1.40.25 (TeX Live 2023)
kpathsea version 6.3.5
Copyright 2023 Han The Thanh (pdfTeX) et al.
There is NO warranty.  Redistribution of this software is
covered by the terms of both the pdfTeX copyright and
the Lesser GNU General Public License.
For more information about these matters, see the file
named COPYING and the pdfTeX source.
Primary author of pdfTeX: Han The Thanh (pdfTeX) et al.
Compiled with libpng 1.6.39; using libpng 1.6.39
Compiled with zlib 1.2.13; using zlib 1.2.13
Compiled with xpdf version 4.04
  • latexmk コマンド

    • LaTeX 文書をコンパイルおよびプレビューするためのツール
      • コンパイルとプレビューのステップを統合して文書の作成プロセスを簡略化するためのコマンド
    • LaTeX 文書を自動的にコンパイルし、必要な回数だけコンパイルを実行して文書を生成する
    • ソースファイルが変更されると、自動的に再コンパイルを開始する
    • 文書内のクロスリファレンスや参照などに関連する依存関係も自動的に処理する
    • 内部の PDF Viewer を起動してコンパイルされた PDF ファイルを表示する
  • tlmgr コマンド

    • TeX Live Manager
    • TeXLive(TeX のディストリビューション)のパッケージ管理ツール
      • TeXLive パッケージのインストール、アップデート、削除を行うコマンドラインツール
    • 新しい LaTeX パッケージをインストールする
    $ tlmgr install [パッケージ名]
    
    • インストールされているパッケージを最新バージョンにアップデートする
    $ tlmgr update [パッケージ名]
    
    • 不要なパッケージを削除する
    $ tlmgr remove [パッケージ名]
    
    • インストールされているパッケージの情報を表示する
    ### インストール済みパッケージリスト
    $ tlmgr list --only-installed
    
    ### 利用可能なパッケージリスト
    $ tlmgr search search-term
    

VSCode Extension Framework

VSCode 拡張機能をインストール

settings.jsonの編集

  • VSCode を立ち上げて⌘ + ,setting.jsonを開く
  • もしくは直接~/Library/Application\ Support/Code/User/settings.jsonを編集

settings.jsonの書き方

latex-workshop.latex.toolslatex-workshop.latex.recipesという 2 つを組み合わせて使用する。

  • latex-workshop.latex.tools
    • コンパイルコマンドの定義(手順)とそれを識別する名前を定義する
  • latex-workshop.latex.recipes
    • デフォルトで用いる一連の動作を定義する
    • latex-workshop.latex.tools で指定した名前を用いて動作を定義する
    • 基本的に、latex-workshop.latex.toolsと 1 対 1 で定義する

例(自分がよく使用しているコンパイル手順を挙げます)

{
  "latex-workshop.latex.tools": [
    {
      "name": "latexmk",
      "command": "latexmk",
      "args": [
        "-interaction=nonstopmode",
        "-e",
        "$latex=q/platex %O -synctex=1 -interaction=nonstopmode -file-line-error %S/",
        "-e",
        "$bibtex=q/pbibtex %O %B/",
        "-e",
        "$biber=q/biber %O --bblencoding=utf8 -u -U --output_safechars %B/",
        "-e",
        "$makeindex=q/mendex %O -o %D %S/",
        "-e",
        "$dvipdf=q/dvipdfmx %O -o %D %S/",
        "-norc",
        "-pdfdvi",
        "-halt-on-error",
        "-latex=platex",
        "%DOC%"
      ]
    }
  ],
  "latex-workshop.latex.recipes": [
    {
      "name": "latexmk (tex to PDF)",
      "tools": ["latexmk"]
    }
  ],
  "latex-workshop.message.latexlog.exclude": [".*"],
  "latex-workshop.view.pdf.viewer": "tab",
  "latex-workshop.latex.clean.subfolder.enabled": true,
  "latex-workshop.latex.autoClean.run": "onBuilt",
  "latex-workshop.latex.autoBuild.cleanAndRetry.enabled": true,
  "latex-workshop.latex.clean.method": "glob",
  "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",
    "*.dvi",
    "*.synctex.gz"
  ]
}
  • コンパイル順序latex-workshop.latex.tools (args)の定義
    • LaTeX コンパイル:platexコマンドを使用して LaTeX 文書をコンパイル
    • BibTeX 処理:pbibtexコマンドを使用して BibTeX を実行
    • Biber 処理:biberコマンドを使用して Biber を実行
    • MakeIndex 処理:mendexコマンドを使用して MakeIndex を実行
    • DVI から PDF への変換:dvipdfmxコマンドを使用して DVI から PDF へ変換

%DOC%はビルド対象の LaTeX 文書ファイルを示すマクロであり、コンパイル時に実際の文書ファイルに置換される

  • latexmkコマンド-halt-on-errorオプション
    • エラー発生時に即座にコンパイルを停止
    • 最低限のログを記録することでエラー箇所の特定がしやすくなる
  • "latex-workshop.latex.clean.method": "glob"
    • コンパイル後に不要なファイル(.aux等)を自動削除する
  • "latex-workshop.view.pdf.viewer": "tab"
  • "latex-workshop.latex.autoBuild.cleanAndRetry.enabled": true
    • タイプセットに失敗した場合、補助ファイルを削除して自動再タイプセットする
    • 一度失敗しているなら繰り返す必要がないと感じる場合にはfalseとして無効化しておく

TeX ファイルの種類

  • .tex
    • LaTeX の ソースファイル
  • .dvi
    • DeVice Independent
    • LaTeX 処理した結果を記録するバイナリファイル
  • .ps
    • Post Script
    • DVI ファイルを印刷する際にプリンタが解釈可能なファイルに変換する
    • dvi2ps コマンドを使用して DVI ファイルから PS ファイルを生成する
  • .aux
    • AUXiiliar
    • LaTeX 内部での情報の参照に利用されるファイル
    • 目次や参考文献を付与する際に、リファレンスの参照を行う
  • .toc
    • Table Of Contents
    • 目次を作成する場合に生成されるファイル
  • .lof
    • List of Figures
    • 図表目次を作成する場合に生成されるファイル
  • .log
    • コンパイルログが出力されたファイル
  • .cls
    • Class
    • 文書クラスを定義するファイル
    • 指定された文書クラスに対応するクラスファイルを環境変数TEXINPUTSで指定されたディレクトリから検索して読み込む
  • .clo
    • Class Option
    • クラスオプションを定義するファイル
    • cls ファイルと同様に環境変数TEXINPUTSで指定されたディレクトリから読み込まれる
  • .sty
    • Style
    • cls, clo ファイルと同様に環境変数TEXINPUTSで指定されたディレクトリから読み込まれる

Hello, World !

\documentclass{jsarticle}

\begin{document}

Hello,\LaTeX!\\

\end{document}

01

こんな感じで編集できれば設定完了!

では、論文頑張って書いていきましょう 👍

【おまけ】Formatter を導入する

latexindent をインストール

$ brew install latexindent

latex-formatter 追加

settings.jsonの編集

{
  // 追加
  "[latex]": {
    "editor.tabSize": 4,
    "editor.defaultFormatter": "nickfode.latex-formatter",
    "editor.formatOnSave": true
  },
  "[bibtex]": {
    "editor.tabSize": 4
  }
}

【おまけ】LaTeX エンジンの種類

LaTex を使用して.tex文書ファイルから PDF を変換する際のワークフロー(コンパイル方式)は 7 つある。

  • pLaTeX + dvips(最も古い方式)
    • (TeX の本来の出力形式である)DVI ファイルを出力し、その後、dvipsで DVI から PDF を生成する
  • pLaTeX + dvipdfmx
    • (TeX の本来の出力形式である)DVI ファイルを出力し、その後、dvipdfmxで DVI から PDF を生成する
  • upLaTeX + dvips
    • (TeX の本来の出力形式である)DVI ファイルを出力し、その後、dvipsで DVI から PDF を生成する
  • upLaTeX + dvipdfmx
    • (TeX の本来の出力形式である)DVI ファイルを出力し、その後、dvipdfmxで DVI から PDF を生成する
  • pdfLaTeX
    • TEX から PDF を直接出力する
  • XeLaTeX
    • TEX から PDF を直接出力する
  • LuaLaTeX(最近流行り)
    • TEX から PDF を直接出力する

LaTeX エンジンの確認

以下の TeX ファイルをコンパイルすると確認できる

\documentclass[a4paper]{article}
\ProvidesFile{hello.tex}[2023/02/25 v0.3 hello my workflow]
\makeatletter %!!!!!!!!!!!!!!!!!!!!!!!!! TeX code BEGIN

%--------------------------------------- engine check

%% \my@if@primitive
\def\my@if@primitive#1{%
  \edef\my@tmpa{\string#1}\edef\my@tmpb{\meaning#1}%
  \ifx\my@tmpa\my@tmpb \expandafter\@firstoftwo
  \else \expandafter \@secondoftwo \fi}

%% \my@engine : TeX engine type
\let\my@engine=k
\my@if@primitive\pdftexversion{\let\my@engine=P}{}
\my@if@primitive\OmegaVersion{\let\my@engine=o}{}
\my@if@primitive\luatexversion{\let\my@engine=L}{}
\my@if@primitive\XeTeXversion{\let\my@engine=X}{}
\my@if@primitive\kanjiskip{\let\my@engine=p}{}
\my@if@primitive\kchardef{\let\my@engine=u}{}
\my@if@primitive\ngbanner{\let\my@engine=A}{}
\my@if@primitive\jintercharskip{\let\my@engine=j}{}
\ifx u\my@engine
  \ifnum\ucs"3000="3000 \else \let\my@engine=p \fi
\fi

%% \ifmy@pdf
\newif\ifmy@pdf
\@tempcnta\z@
\my@if@primitive\pdfoutput{\@tempcnta\pdfoutput}{}
\my@if@primitive\outputmode{\@tempcnta\outputmode}{}
\ifnum\@tempcnta>\z@ \my@pdftrue \fi
\if X\my@engine \my@pdftrue \fi
\if A\my@engine \my@pdftrue \fi

%% LuaTeX variants
\if L\my@engine \ifx\luatexbanner\@undefined\else
  \ifx\luaescapestring\@undefined\else
    \ifcase\directlua{
      local s = "\luaescapestring{\luatexbanner}"
      if s:match("LuajitTeX") then tex.write("1")
      elseif s:match("HarfTeX") then tex.write("2")
      elseif s:match("LuaHBTeX") then tex.write("3")
      else tex.write("0")
      end}\relax
    \or \let\my@engine=I % LuajitTeX
    \or \let\my@engine=F % HarfTeX
    \or \let\my@engine=H % LuaHBTeX
    \fi
  \fi
\fi\fi

%% \my@lmodern
\if X\my@engine
  \IfFileExists{tulmr.fd}{%
    \expandafter\ifx\csname T@TU\endcsname\relax
      \input{tuenc.def}%
    \fi
    \def\my@lmodern{\fontencoding{TU}}}%
  {%else
    \input{eu1enc.def}%
    \def\my@lmodern{\fontencoding{EU1}}}%
  \g@addto@macro\my@lmodern{\fontfamily{lmr}\selectfont}
\fi

%%<+> \myEngineName
% Prints the name of the *LaTeX* engine in use.
\newcommand*\myEngineName{%
  \ifx P\my@engine
    \ifmy@pdf pdf\/\fi \LaTeX
  \else\ifx o\my@engine Lamed% forget about Lambda
  \else\ifx L\my@engine Lua\LaTeX
  \else\ifx I\my@engine Luajit\LaTeX
  \else\ifx F\my@engine Lua\LaTeX\ (on Harf\TeX)%
  \else\ifx H\my@engine Lua\LaTeX\ (on LuaHB\TeX)%
  \else\ifx X\my@engine \begingroup
      \my@lmodern X\kern-.125em\lower.5ex\hbox{\char"018E}%
      \kern-.075em\LaTeX
    \endgroup
  \else\ifx p\my@engine p\LaTeX
  \else\ifx u\my@engine up\LaTeX
  \else\ifx A\my@engine Ap\LaTeX
  \else\ifx j\my@engine
    \leavevmode\lower.5ex\hbox{J}\kern-.1em \LaTeX
  \else \LaTeX % good old...
  \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi}

%--------------------------------------- dvips or dvipdfmx

%% \my@hedge
\def\my@hedge{2\paperwidth}

%% \my@ps
\def\my@ps#1{\special{ps:#1}}

%% \my@F
\def\my@F{gsave newpath F grestore 0 () gsave p grestore pop }

%% \my@dvips@or@pdf{<dvips>}{<dvipdfmx>}
\def\my@dvips@or@pdf#1#2{%
  \leavevmode
  \my@ps{currentpoint pop /F exch def}%
  \kern\my@hedge
  \my@ps{currentpoint pop \my@F sub /F exch def \my@F neg 0 translate}%
  \hb@xt@\z@{#1\hss}%
  \kern-\my@hedge \hb@xt@\z@{#2\hss}%
  \my@ps{\my@F 0 translate}}

%%<+> \myDviPsOrPdf{<trailer>}
% Would print either 'dvips' or 'dvipdfm' plus the trailer, according
% to the DVI driver actually in use. Note that the reference point
% does not advance.
\newcommand*\myDviPsOrPdf[1]{%
  \my@dvips@or@pdf{dvips#1}{dvipdfmx#1}}

%--------------------------------------- main

%%<+> \myWorkflowName{<trailer>}
\newcommand*\myWorkflowName[1]{%
  \myEngineName
  \ifmy@pdf #1%
  \else \space+\space \myDviPsOrPdf{#1}%
  \fi
  \par}% avoid the influence of zero-advance

\makeatother  %!!!!!!!!!!!!!!!!!!!!!!!!! TeX code END
\begin{document}
Hello, \myWorkflowName{!}
\end{document}

02