TeXをもっと便利に使う!(自動コンパイル・部分コンパイル・分割ファイルから親ファイルのコンパイル)【Vim + vim-quickrun + latexmk】

前置き
======

以前に[VimでLaTeX編集！vim-quickrunとlatexmkで自動コンパイルと部分コンパイル - Qiita](http://qiita.com/ssh0/items/4aea2d3849667717b36d)というエントリを書いてましたが、使っているうちに更に改良できる点が見つかったので、改めてまとめておこうと思います。

自動コンパイル、部分コンパイルのやり方は、前回のエントリと同じ組み合せ(vim-quickrun+latexmk)で実現しているので、大枠はそちらを参照してください(参考になる外部リンクも張ってあります)。今回は主に`~/.latexmkrc`の設定の変更と、`latexmk`コマンドの自作ラッパースクリプト`latexmk_wrapper`の紹介という形にしたいと思います。


latexmkrcの設定
===============

`~/.latexmkrc`には以下の様に書いています。

* [dotfiles/.latexmkrc at master · ssh0/dotfiles](https://github.com/ssh0/dotfiles/blob/master/.latexmkrc)

```perl
#!/usr/bin/perl
$latex = 'platex -interaction=nonstopmode -kanji=utf-8 %O %S';
$dvipdf = 'dvipdfmx %O -o %D %S';
$bibtex = 'pbibtex';
$pdf_mode = 3; # use dvipdf
$pdf_update_method = 2;
$pdf_previewer = "start mupdf %O %S";
# Prevent latexmk from removing PDF after typeset.
# $pvc_view_file_via_temporary = 0;
```

以前と変わった点は、`dvipdf`のオプションに`-o %D`というのがついた点です。このようにすると、dviファイルがあるディレクトリにpdfファイルを作成してくれるようになります。
また、platexのオプションに`-interaction=nonstopmode`をつけて、エラーが出ても、interactionモードが立ち上がってストップしないようにします。

* [automation - Don't make me manually abort a LaTeX compile when there's an error - Stack Overflow](http://stackoverflow.com/questions/738755/dont-make-me-manually-abort-a-latex-compile-when-theres-an-error)



ラッパースクリプトlatexmk_wrapper
=================================

まんまネーミング。ソースはこちら。

* [dotfiles/latexmk_wrapper at master · ssh0/dotfiles](https://github.com/ssh0/dotfiles/blob/master/bin/latexmk_wrapper)

```bash
#!/bin/sh
# written by Shotaro Fujimoto (https://github.com/ssh0)
# first edited: 2015-06-26

# If there is a file named below in the same directory,
# this script automatically detect that the file is root tex file,
# and compile this file even if you choose different one.
rootfile='main.tex'

# If the choosed file is in $sourcedir, default outputdir is setted to one
# level upper directory.
sourcedir='source'

message() {
  echo "There is$1 '$rootfile' in the directory '$2',"
  echo "so this script compiles this file."
  echo ""
}

search_rootfile() {
if [ -f "$1"/"$rootfile" ]; then
  texfile="$1"/"$rootfile"
  message "" "$1"
  return 0
else
  texfile="$1"/"$name"
  return 1
fi
}

dir="$(cd "$(dirname $1)"; pwd)"
name="$(basename $1)"

if [ ! -f "$dir/$name" ]; then
  echo "$dir/$name doesn't exist."
  exit 1
fi

currentdir="$(basename $dir)"
dir_up="$(dirname $dir)"

if [ ${currentdir} = $sourcedir ]; then
  echo "This file is in '$sourcedir', so search '$rootfile' recursively."
  outdir="${dir_up}"
  search_rootfile ${dir_up} || search_rootfile $dir || message " not" "$dir"
else
  outdir="$dir"
  search_rootfile $dir || message " not" "$dir"
fi

echo "Run latexmk..."
echo "============"
echo ""
shift 1
latexmk -pdfdvi -output-directory=$outdir "$@" $texfile
```

ソースコードのメッセージをみてもらえば条件分岐の意味が分かると思いますが、引数となったファイルが`$sourcedir`にいるときには、自分自身のディレクトリとその上の階層までみることにして、これらのディレクトリに`$rootfile`で指定したファイルがあればそのファイルをターゲットにしてlatexmkを実行します。出力先は、`$sourcedir`があるときはその上の階層のディレクトリで、そうでない時は同じディレクトリ内に設定します。

注)
Vimプラグイン'lervag/vimtex'を入れていれば、latexmkを使い、`\input{}`されたファイルからでも、自動的に親ファイルを見つけてコンパイルを行うことができます。しかしながら、Vimの中でしかそれができないというのも不便なので(スクリプトとしても実行したい時があるだろうから)、期待した動作をするようにシェルスクリプトを書きました。

忘れず実行権限を与えておきましょう。

```
sudo chmod u+x ~/bin/latexmk_wrapper
```

これで、シェルスクリプトとして適当なディレクトリのtexファイルを引数にしてやれば、簡単にコンパイルできるようになります。



Vimから使う準備
===============

`~/.vimrc`に

```vim
" Plugin (managed by NeoBundle)
"==============================
" for LaTeX
NeoBundle 'lervag/vimtex'
let g:vimtex_fold_envs = 0
let g:vimtex_view_general_viewer = 'mupdf'

" vim-quickrun
NeoBundle 'thinca/vim-quickrun'

" autocmd
"==============================
augroup filetype
  autocmd!
  " tex file (I always use latex)
  autocmd BufRead,BufNewFile *.tex set filetype=tex
augroup END

" disable the conceal function
let g:tex_conceal=''
```

と書いておきます。
`let g:vimtex_fold_envs = 0`はenvironment単位で折りたたみするのを無効にします。さすがにやり過ぎ感あったので…
autocmdでtexのファイルタイプを指定していますが、[ここ](https://github.com/lervag/vimtex/blob/master/doc/vimtex.txt#L182)にも書いてあるとおり、plaintexとしてファイルタイプが認識されることがあるので、ファイルタイプはtexに統一します。
`let g:tex_conceal=''`ですが、最近のVimは、数式なんかを打つと、勝手にマルチバイト文字に置き換えて表示してくれます。が、うっとおしいので切ります。

- [【Vim】Conceal機能ってぶっちゃけ見にくいと思う - Qiita](http://qiita.com/xeno1991/items/8d1c8f38595337bab7c8)



vim-quickrunの設定ファイル
===================

続いてvim-quickrunが参照できるようにtexのQuickRunの設定ファイルを`~/.vim/ftplugin/tex_quickrun.vim`に以下のように書きます。

```vim
" LaTeX Quickrun
let g:quickrun_config['tex'] = {
\ 'command' : 'latexmk_wrapper',
\ 'outputter' : 'error',
\ 'outputter/error/success' : 'null',
\ 'outputter/error/error' : 'quickfix',
\ 'srcfile' : expand("%s"),
\ 'exec': '%c %s %a %o',
\}

" 部分的に選択してコンパイル
" http://auewe.hatenablog.com/entry/2013/12/25/033416 を参考に
let g:quickrun_config.tmptex = {
\   'exec': [
\           'mv %s %a/tmptex.latex',
\           'latexmk -pdfdvi -pv -output-directory=%a %a/tmptex.latex',
\           ],
\   'args' : expand("%:p:h:gs?\\\\?/?"),
\   'outputter' : 'error',
\   'outputter/error/error' : 'quickfix',
\
\   'hook/eval/enable' : 1,
\   'hook/eval/cd' : "%s:r",
\
\   'hook/eval/template' : '\documentclass{jsarticle}'
\                         .'\usepackage[dvipdfmx]{graphicx, hyperref}'
\                         .'\usepackage{float}'
\                         .'\usepackage{amsmath,amssymb,amsthm,ascmac,mathrsfs}'
\                         .'\allowdisplaybreaks[1]'
\                         .'\theoremstyle{definition}'
\                         .'\newtheorem{theorem}{定理}'
\                         .'\newtheorem*{theorem*}{定理}'
\                         .'\newtheorem{definition}[theorem]{定義}'
\                         .'\newtheorem*{definition*}{定義}'
\                         .'\renewcommand\vector[1]{\mbox{\boldmath{\(#1\)}} }'
\                         .'\begin{document}'
\                         .'%s'
\                         .'\end{document}',
\
\   'hook/sweep/files' : [
\                        '%a/tmptex.aux',
\                        '%a/tmptex.dvi',
\                        '%a/tmptex.fdb_latexmk',
\                        '%a/tmptex.fls',
\                        '%a/tmptex.latex',
\                        '%a/tmptex.log',
\                        '%a/tmptex.out',
\                        ],
\}

vnoremap <silent><buffer> <F5> :QuickRun -mode v -type tmptex<CR>

" QuickRun and view compile result quickly (but don't preview pdf file)
nnoremap <silent><F5> :QuickRun<CR>
```

QuickRunで使用するコマンドをlatexmk_wrapperに変更し、引数の処理を簡単にした以外はあまり前回と変わっていません。このように設定しておけば、.texファイルを開いてノーマルモードでF5キーを押せば、先ほどのスクリプトで指定したように、main.texがあればそれをコンパイルしてくれます。また、コマンドモードから引数を持たせて実行することにより、例えば

```
:QuickRun -args -pv
```

で`~/.latexmkrc`で指定した開き方でpdfファイルを見ることができますし、

```
:QuickRun -args -c
```

とすれば、中間ファイルをすべて削除してdviファイルやpdfファイルだけが残るようにしてくれます。
また、範囲を選択してビジュアルモードにいるときにF5キーを押すことで、その部分だけを`hook/eval/template`で挟んだ形でコンパイルしてpdfにし、表示してくれます。ちょっとした数式の確認や、泥臭いですがエラーの出処を探すのにも重宝します。



まとめ
======

だいぶ便利にTexのコンパイルができるようになったと思います。なんだかんだで内容を編集する時間よりもエラーつぶしにかける時間も馬鹿にできないので、こまめにコンパイルして、不安なところは部分コンパイルして、という風にしていけば、楽に編集できると思います。