latexmk による LaTeX ワークフロー内で句読点を自動で置換する

# 動機

卒論やその毎月の報告書をきっかけにようやく BibTeX を使い始めましたが，BibTeX と LaTeX の処理を何回も行き来するのが面倒な上に非効率なので，今までお世話になっていた ptex2pdf に代わり latexmk を利用することにしました。その際，どうせ一連の作業を自動化するならエディタの機能やシェルスクリプトを逐一実行して `.tex` ファイル中の句読点を論文の規定に揃えるのではなく，句読点の置換も自動化できれば楽だなと思って試してみたので，その方法の紹介です。

# 動作確認環境と要件

以下の環境での動作を確認しています。

* OS X El Capitan 10.11.5
* TeX Live 2015 frozen

また，句読点の置換において `find`, `xarg`, `sed` を使用しているため，上記環境にくわえてこれらのコマンドが利用できる環境を用意するか他の手段や言語に差し替える必要があります。

# `.latexmkrc` の準備
まず，ホームディレクトリに `.latexmkrc` を作成し，latexmk の基本的な設定を行います。ここに示したのはあくまで私の一例ですので，コマンドのオプションや shebang は各自の都合に合わせて読み替えてください。

```pl:~/.latexmkrc
#!/usr/bin/perl

$latex = 'uplatex -synctex=1 -halt-on-error -file-line-error';
$bibtex = 'pbibtex';
$dvipdf = 'dvipdfmx %O -o %D %S';

$pdf_mode = 3;
$pvc_view_file_via_temporary = 0;
```
## 方法その 1（2015 年 10 月投稿分）

ホームディレクトリに続いて `.tex` ファイルのあるディレクトリ[^1]にも `.latexmkrc` を作成します。

[^1]: 以下ではプロジェクトディレクトリと呼び，パスを `/path/to/project/` と表記します。


```pl:/path/to/project/.latexmkrc
#!/usr/bin/perl

$pdf_update_method = 4;
$pdf_update_command = "find . -type f -name '*.tex' -print0 | xargs -0 sed -i '' -e 's/，/、/g' -e 's/．/。/g'";
```

`$pdf_update_method` とは規定値が `1` または `3` に設定されていますが，これを `4` にすることで，PDF の更新時に `$pdf_update_command` に指定されたコマンドが実行されます。本稿の趣旨から逸れるので実行内容の詳細な説明はしませんが，置換に関する部分は `'s/置換前/置換後/g'` という書式ですので，使用する句読点の組に応じてこの部分を変更してください。

本稿のケースでは `find` や `sed` よりも Perl の方が移植性に優れる[^3]ので Perl で書きたかったのですが，不勉強ゆえに Perl でカレントディレクトリ以下を再帰的に検索して複数の文字列置換をワンライナーで実行する方法が分からず，普段から使い慣れてるこの方法で書きました。ソースファイルを分割しない場合や分割しても子ファイルをサブディレクトリには置かないような場合は `perl -pi -e 's/，/、/g' ./*.tex && perl -pi -e 's/．/。/g' ./*.tex` などで構いません。

[^3]: latexmk が Perl で実装されているので，latexmk が動く環境であればバージョン間の差こそあれど，Perl ですべて書いた方が移植性が高くなります。

また，sed は BSD sed と GNU sed で挙動が異なる点があり，今回のコードでも `-i` オプションの仕様が異なるので，Linux など GNU sed を使う方は注意が必要です。詳しくは以下の記事を参照してください。

> [Macの（BSD版）sed での上書き保存 - Qiita](http://qiita.com/catfist/items/1156ae0c7875f61417ee)

2 つの設定内容はいずれかのディレクトリにまとめて記しても動きますが，書く文書やその投稿先によって使用すべき句読点が規定されていることを考えると，latexmk 自体の設定はホームディレクトリでグローバルに設定して句読点の置換については各プロジェクトディレクトリでローカルに設定するのがベストな運用法だと思います。

じっさいに文書をタイプセットするときは `-pvc` オプションで latexmk を実行します。

```bash
$ latexmk -pvc foo.tex

[...]

=== Watching for updated files. Use ctrl/C to stop ...
```

句読点が置換される流れは以下のようになっています。

1. `latexmk -pvc` が実行されて監視モードに入る
* ファイル内容の変更を検出すると，latexmk が実行されて PDF が更新される
* PDF が更新されたので `$pdf_update_command` の内容が実行される，つまり句読点が置換される
* 句読点の置換を検出し，再び latexmk が実行される
* 今回は置換する句読点がないのでファイル内容は変更されない
* 以下，2. から 5. の繰り返し

## 方法その 2
はじめに投稿したのは方法その 1 の方でしたが，ふと「たんにタイプセット前に置換すればいいのでは」と思って `$latex` の部分で句読点置換を行ってみたところエラーも出ませんでしたので追記しておきます。

```pl:/path/to/project/.latexmkrc
#!/usr/bin/perl

$latex = "find . -type f -name '*.tex' -print0 | xargs -0 sed -i '' -e 's/，/、/g' -e 's/．/。/g' && uplatex -synctex=1 -halt-on-error -file-line-error";
```

こちらは `-pvc` オプションを付ける必要はありません。

## 方法その 3

latexmk の Custom Dependency を利用して句読点を置換します。こちらも `-pvc` オプションは不要です。

```pl:/path/to/project/.latexmkrc
#!/usr/bin/perl

add_cus_dep('tex', 'tex', 0, 'convert_jpnct');
sub convert_jpnct {
    system("find . -type f -name '*.tex' -print0 | xargs -0 sed -i '' -e 's/，/、/g' -e 's/．/。/g'");
}
```


# 各手法の比較

3 つの方法を書いてみたので，簡単に比較でもしたいと思います。

その 1 に関しては一度の編集に対して実質 2 回タイプセットされることになります。普段であればとくに気にならないかもしれませんが，一回のタイプセットに数十分あるいは一時間以上要する文書[^4]を作成していると，これはかなりストレスです。また，`-pvc` オプションが必須なことがデメリットに思う人もいるかもしれません。

その 2 ではタイプセットは 1 回しか行われない上に `-pvc` オプションも不要でやっている処理も分かりやすいですが，`$latex` で実行するコマンドが長くなるのが欠点です。「設定ファイルに一回書くだけだから長くても問題ないのでは」と思われるかもしれませんが，一時的に違うエンジンを使いたくてコマンドライン上で `latexmk` のオプション指定するときに「`find` で置換対象を検索してパイプと `xargs` で `sed` に渡してから置換して最後にタイプセットする」という処理を指定するのは面倒です。Eric Raymond の “Rule of Modularity” じゃないですけど，やはり句読点置換という機能はタイプセットという機能とは切り離した変数に書きたいところです。

となると，その 3 が一番良さそうに思えますが，LaTeX の処理が終わると latexmk のログに

```
------------
Run number 2 of rule 'cusdep tex tex test'
------------
For rule 'cusdep tex tex test', running '&do_cusdep( convert_jpnct )' ...
```
と出力され[^5]ており，スクリプトを実際に読んだわけではないので確信はありませんが Custom Dependency で指定した内容を実行しようとしているように見えます。DVI が生成された時点で句読点を置換する必要はないのでこれを抑制したいのですが，現状ではその手法がよく分かりません。

[^5]: じっさいは `test` に相当する部分には LaTeX ソースのファイル名が入る。

総論としては方法その 1 が少し利便性に欠けて，後者 2 つは一長一短という印象です。しかしながら，一つの文書を複数のエンジンに切り替えながらタイプセットするというケースは比較的考えにくいので，基本的には方法その 2 を利用すればいいかと思います。

[^4]: 大量のサンプルからなるグラフを全て PGFPlots で書いた私の卒論など。

# 参考文献

* [latexmk マニュアル - CTAN](http://mirrors.ctan.org/support/latexmk/latexmk.pdf)