動機
卒論やその毎月の報告書をきっかけにようやく BibTeX を使い始めましたが,BibTeX と LaTeX の処理を何回も行き来するのが面倒な上に非効率なので,今までお世話になっていた ptex2pdf に代わり latexmk を利用することにしました。その際,どうせ一連の作業を自動化するならエディタの機能やシェルスクリプトを逐一実行して .tex
ファイル中の句読点を論文の規定に揃えるのではなく,句読点の置換も自動化できれば楽だなと思って試してみたので,その方法の紹介です。
動作確認環境と要件
以下の環境での動作を確認しています。
- OS X El Capitan 10.11.5
- TeX Live 2015 frozen
また,句読点の置換において find
, xarg
, sed
を使用しているため,上記環境にくわえてこれらのコマンドが利用できる環境を用意するか他の手段や言語に差し替える必要があります。
.latexmkrc
の準備
まず,ホームディレクトリに .latexmkrc
を作成し,latexmk の基本的な設定を行います。ここに示したのはあくまで私の一例ですので,コマンドのオプションや shebang は各自の都合に合わせて読み替えてください。
#!/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
を作成します。
#!/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 の方が移植性に優れる2ので Perl で書きたかったのですが,不勉強ゆえに Perl でカレントディレクトリ以下を再帰的に検索して複数の文字列置換をワンライナーで実行する方法が分からず,普段から使い慣れてるこの方法で書きました。ソースファイルを分割しない場合や分割しても子ファイルをサブディレクトリには置かないような場合は perl -pi -e 's/,/、/g' ./*.tex && perl -pi -e 's/./。/g' ./*.tex
などで構いません。
また,sed は BSD sed と GNU sed で挙動が異なる点があり,今回のコードでも -i
オプションの仕様が異なるので,Linux など GNU sed を使う方は注意が必要です。詳しくは以下の記事を参照してください。
2 つの設定内容はいずれかのディレクトリにまとめて記しても動きますが,書く文書やその投稿先によって使用すべき句読点が規定されていることを考えると,latexmk 自体の設定はホームディレクトリでグローバルに設定して句読点の置換については各プロジェクトディレクトリでローカルに設定するのがベストな運用法だと思います。
じっさいに文書をタイプセットするときは -pvc
オプションで latexmk を実行します。
$ latexmk -pvc foo.tex
[...]
=== Watching for updated files. Use ctrl/C to stop ...
句読点が置換される流れは以下のようになっています。
-
latexmk -pvc
が実行されて監視モードに入る
- ファイル内容の変更を検出すると,latexmk が実行されて PDF が更新される
- PDF が更新されたので
$pdf_update_command
の内容が実行される,つまり句読点が置換される - 句読点の置換を検出し,再び latexmk が実行される
- 今回は置換する句読点がないのでファイル内容は変更されない
- 以下,2. から 5. の繰り返し
方法その 2
はじめに投稿したのは方法その 1 の方でしたが,ふと「たんにタイプセット前に置換すればいいのでは」と思って $latex
の部分で句読点置換を行ってみたところエラーも出ませんでしたので追記しておきます。
#!/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
オプションは不要です。
#!/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 回タイプセットされることになります。普段であればとくに気にならないかもしれませんが,一回のタイプセットに数十分あるいは一時間以上要する文書3を作成していると,これはかなりストレスです。また,-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 )' ...
と出力され4ており,スクリプトを実際に読んだわけではないので確信はありませんが Custom Dependency で指定した内容を実行しようとしているように見えます。DVI が生成された時点で句読点を置換する必要はないのでこれを抑制したいのですが,現状ではその手法がよく分かりません。
総論としては方法その 1 が少し利便性に欠けて,後者 2 つは一長一短という印象です。しかしながら,一つの文書を複数のエンジンに切り替えながらタイプセットするというケースは比較的考えにくいので,基本的には方法その 2 を利用すればいいかと思います。