Vim や Neovim で LaTeX を書く人の事実上の標準が、Karl Yngve Lervåg 氏による vimtex プラグインです。コンパイル、目次・ラベル間の移動、環境やコマンドを単位とする操作(モーション/テキストオブジェクト)、補完、そして PDF ビューアとの相互ジャンプまでを、エディタを離れずに行えます。このページでは vimtex の導入と設定、補完、そして SyncTeX による逆検索を順に見ていきます。
vimtex とは
Vim も Neovim も、それ自体は TeX を組版しません。実際にコンパイルするのは、PC に入れた TeX Live(や MiKTeX・MacTeX)です。vimtex は、その橋渡しをする「.tex 用のファイルタイプ&シンタックスプラグイン」。tex ファイルタイプを検出すると、ビルドの起動、シンタックスハイライト、補完関数(omnifunc)、目次表示、\ref/\cite のジャンプ、環境・括弧・コマンドのテキストオブジェクトなどを 自動的に有効化 します。コア部分は外部依存なしで動き、補完やスニペットは好みのプラグインと組み合わせます。
前提は二つだけです。第一に、TeX のコマンドが PATH から呼べる こと。vimtex は内部で latexmk などを子プロセスとして起動するため、ターミナルで latexmk --version が動けばまず問題ありません。第二に、Vim 側で ファイルタイプとシンタックスを有効化 していること。vimrc/init.vim に次の二行が要ります(多くの設定では既に入っています)。
filetype plugin indent on
syntax enable導入と設定
vimtex はプラグインマネージャで入れるのが普通です。Vim なら vim-plug、Neovim なら lazy.nvim が広く使われます。ここで重要な注意がひとつ。vimtex を遅延読み込み(lazy-load)してはいけません。 公式が明記している通り、ファイルタイプの検出より後に読み込むと、後述の逆検索が壊れます。lazy.nvim では lazy = false、packer では明示ロード、vim-plug では for による遅延指定を付けない、が鉄則です。
Vim(vim-plug)の最小設定は次の通りです。プラグインを宣言し、ファイルタイプ/シンタックスを有効化し、g:vimtex_view_method で PDF ビューア を選ぶだけで動き始めます。maplocalleader(ローカルリーダー)は vimtex の操作の起点になるので、明示しておくと安心です(既定はバックスラッシュ \)。
call plug#begin()
Plug 'lervag/vimtex'
call plug#end()
filetype plugin indent on
syntax enable
let maplocalleader = ' ' " use Space as <localleader>
let g:vimtex_view_method = 'zathura' " 'skim' on macOS, 'sumatrapdf' on Windows
let g:vimtex_compiler_method = 'latexmk'Neovim(lazy.nvim)なら、同じ設定を Lua で書きます。init の中で変数を設定するのは、プラグイン本体が読み込まれる前に効かせるためです。lazy = false を忘れないこと。
return {
"lervag/vimtex",
lazy = false, -- do NOT lazy-load: it breaks inverse search
init = function()
vim.g.vimtex_view_method = "zathura" -- "skim" / "sumatrapdf"
vim.g.vimtex_compiler_method = "latexmk"
end,
}.tex を開くと、ローカルリーダー l を起点とした操作が使えます。覚えておきたいのは次の四つです。
| 操作 | 既定マッピング | 内容 |
|---|---|---|
compile | \ll | latexmk による 連続コンパイル を開始/停止。保存のたびに自動で組み直す |
view | \lv | PDF を表示し、カーソル位置へ 前方検索(ソース → PDF) |
clean | \lc | 中間ファイル(.aux・.log など)を掃除 |
stop | \lk | 実行中のコンパイルを停止(\lK で全停止) |
実際の流れはこうです。\ll を一度押すと latexmk が常駐し、以降は保存するたびに PDF が更新されます。\lv で該当箇所を PDF に表示し、エラーは \le で quickfix リストに出して該当行へ飛べます。\ll の ll を含め、ローカルリーダーが \ のままなら \ll、Space に変えていれば <Space>ll のように打ちます。
コンパイラの既定は latexmk で、vimtex はあらかじめ -verbose -file-line-error -synctex=1 -interaction=nonstopmode といったオプションを渡します。とくに **-synctex=1 が既定で入っている** ため、後述の前方・逆検索に必要な対応表が、何もしなくても出力されます。Tectonic を使いたければ g:vimtex_compiler_method = "tectonic"、latexrun や arara も選べます。
日本語を組むなら、**エンジンの切り替えは .latexmkrc に任せる** のが最も素直です。vimtex の latexmk バックエンドは、.latexmkrc の $pdf_mode を読み取って処理経路を決めます(1=pdfLaTeX 直接、3=DVI を作って dvipdfmx で PDF 化、4=LuaLaTeX)。注意点として、エンジン指定の -pdf/-lualatex などは vimtex の options に足さず、.latexmkrc か g:vimtex_compiler_latexmk_engines 側で指定します。次は upLaTeX + dvipdfmx(理系の日本語論文で定番)の例です。
$latex = 'uplatex -synctex=1 -interaction=nonstopmode -file-line-error %O %S';
$bibtex = 'upbibtex %O %B';
$biber = 'biber --bblencoding=utf8 -u -U --output_safechars %O %S';
$makeindex = 'upmendex %O -o %D %S';
$dvipdf = 'dvipdfmx %O -o %D %S';
$pdf_mode = 3;
$max_repeat = 5;要点は、$latex に uplatex、$dvipdf に dvipdfmx を割り当て、$pdf_mode = 3 で「DVI を作ってから dvipdfmx で PDF 化する」経路を選ぶことです。$latex 側にも -synctex=1 を渡しておくと、DVI 経由でも SyncTeX 情報が PDF まで引き継がれます。LuaLaTeX で和文を組むなら .latexmkrc は不要で、g:vimtex_compiler_latexmk_engines に lualatex を選ばせるか、$pdf_mode = 4 を書くだけで済みます(luatexja/ltjsclasses 系を使う前提)。
補完
vimtex は文脈に応じた補完候補を、Vim 標準の補完関数(omnifunc)として提供します。tex バッファでは omnifunc=vimtex#complete#omnifunc が 自動で設定 されるので、g:vimtex_complete_enabled(既定 1)が有効なら、すぐに使えます。補える主なものは次の通りです。
\cite{...}** —.bibや\bibitemを読み、引用キーを補完。\ref{...}/\eqref{...}** — 文書中の\labelを集めて参照を補完。- コマンド・環境名 — 読み込んだパッケージに応じた
\commandや\begin{...}の環境名。 - ファイル名 — 図・
\input/\include・\includepdfなどのパス。 - 用語集・パッケージ名 —
glossariesの項目や、利用可能な.sty/.clsに基づくパッケージ名。
素の Vim では、挿入モードで **Ctrl-X Ctrl-O**(omni 補完の呼び出し)を押せば候補が出ます。たとえば \cite{ まで打って Ctrl-X Ctrl-O とすると、文献キーの一覧が並びます。ただ毎回このキーを押すのは煩雑なので、実際には 補完エンジン に omnifunc を橋渡しさせ、入力に応じて自動でポップアップさせる構成が一般的です。
Neovim でモダンに組むなら nvim-cmp が定番です。omni ソースを足すだけで、vimtex の omnifunc 由来の候補がそのまま流れ込みます。
local cmp = require("cmp")
cmp.setup({
sources = cmp.config.sources({
{ name = "omni" }, -- pulls vimtex completion via omnifunc
}),
})Vim と Neovim のどちらでも使える coc.nvim を選ぶ場合は、coc-omni 拡張を入れて tex ファイルタイプを omni ソースに含めます。古い deoplete を使っているなら deoplete-vimtex を併用します。いずれの場合も、補完候補の中身を作るのは vimtex 側、それを「いつどう見せるか」を受け持つのが補完エンジン側、という分担です。
逆検索(PDF → ソース)
SyncTeX は、ソースの行と PDF 上の位置との対応を記録する仕組みです。これにより、編集位置から PDF へ飛ぶ 前方検索 と、PDF 上の場所からソース行へ戻る 逆検索 ができます。前方検索は vimtex が面倒を見てくれるので、\lv を押すだけ。問題は逆検索で、こちらは PDF ビューア側から Vim を呼び戻す 設定が要ります。鍵になるのが、vimtex が用意する :VimtexInverseSearch コマンドです。
仕組みはこうです。ビューアは SyncTeX で「クリックされた位置はソースの何行目・どのファイルか」を割り出し、その行番号とファイルを引数に、エディタを呼び出すシェルコマンドを実行します。そのコマンドの中で VimtexInverseSearch <行> <ファイル> を呼べば、vimtex#view#inverse_search が起動済みの Vim/Neovim を探して該当箇所を開きます。複数のインスタンスやサーバー名の管理は vimtex 側が引き受けるので、利用者が --servername を指定する必要は基本ありません。プレースホルダ名はビューアごとに違い、行番号とファイルがそれぞれ zathura では %{line}/%{input}、Skim では %line/%file、SumatraPDF では %l/%f になります。
Linux — zathura。 vimtex で最も実績のある組み合わせです。g:vimtex_view_method = "zathura" にしておけば、\lv での前方検索に加え、逆検索もほぼ設定不要 で動きます。vimtex は zathura を -x 付きで起動し、VimtexInverseSearch を呼ぶエディタコマンドを自動で渡すためです(xdotool が無い環境では zathura_simple を使います)。zathura 上で **Ctrl + 左クリック** すると、対応するソース行へ移動します。
自分で設定したい場合や、列番号まで同期したい場合は、zathurarc に直接書きます。zathura のプレースホルダは %{line}・%{input}(%l・%f ではない点に注意)。列に対応した実装なら %{column} も使えます。
set synctex true
set synctex-editor-command "nvim --headless -c 'VimtexInverseSearch %{line} %{input}'"macOS — Skim。 g:vimtex_view_method = "skim" にします。Skim 側は、環境設定の 「Sync」タブ → プリセットを「カスタム」 にし、コマンドとオプションを登録します。%line・%file は Skim が行番号とファイルに置換します。
Command: nvim
Arguments: --headless -c "VimtexInverseSearch %line '%file'"これで Skim 上の **Cmd + Shift + クリック** が逆検索になります。Skim はバックグラウンドで Neovim を起動し、VimtexInverseSearch が既存インスタンスへ該当箇所を伝えます。
Windows — SumatraPDF。 g:vimtex_view_method = "sumatrapdf" にします。SumatraPDF の 設定 → オプション → 「逆順検索のコマンドライン」 に、次のようなコマンドを登録します(%l・%f が行番号とファイル)。
cmd /c start /min "" nvim --headless -c "VimtexInverseSearch %l '%f'"SumatraPDF 上では ダブルクリック が逆検索になります。素の gVim を使う場合は、nvim --headless の部分を vim -v --not-a-term -T dumb に置き換えます(gVim や Windows 上の Vim はサーバーを自動で起動します)。
最後にひとつ注意。端末で動かす Vim(Linux/macOS)は、既定ではサーバーを起動しません。 そのため Vim 利用者は vimrc に次を足し、逆検索の呼び戻しを受けられるようにします(Neovim はこの設定は不要です)。
if empty(v:servername) && exists('*remote_startserver')
call remote_startserver('VIM')
endifなお、いずれの OS・ビューアでも前提として **-synctex=1 でコンパイルしてある** ことが必要ですが、前述の通りこれは vimtex の latexmk 既定オプションに含まれているため、通常は意識せずに済みます。