TeX Live に入っているコマンドの大半は、文書を組版しません。文書を 読む ためのものです。この命令は結局どう定義されているのかを見せる texdef、原稿の癖を指摘する chktex と lacheck、千行のログを数行に絞る texfot、語数を数える texcount、.log から必要な行だけ掘り出す texloganalyser ——LaTeX の作業で本当に時間を食うのは組版そのものではなく、うまくいかなかった理由を探す時間なので、このあたりを一度覚えておくと効きます。パッケージの説明書を開く texdoc は別ページの担当なので、ここではそれ以外を扱います。最後に、できあがった PDF に手を入れる Ghostscript も置いておきます。
texdef — この命令は結局どう定義されているのか
再定義がぶつかったとき、いま有効な定義がどれなのかを知る一番早い方法は、エンジンに直接訊くことです。latexdef \section と打つと \long macro:->\@startsection {section}{1}{\z@ }{-3.5ex \@plus -1ex \@minus -.2ex}{2.3ex \@plus .2ex}{\normalfont \Large \bfseries } が返ります。値そのもの、しかもいまの環境の値です。パッケージ込みで見たいなら -p を足します——latexdef -p amsmath \tfrac は \genfrac {}{}{}1 を返し、\tfrac が \genfrac の薄い包みにすぎないことがその場でわかります。存在しない名前を渡すと素っ気なく undefined です。作者は Martin Scharrer、TeX Live 2024 に入っているのは version 1.9(2020/09/27)です。
ここで一つ、dvipdfmx と同じ仕掛けが出てきます。latexdef は texdef への symlink で、プログラムは自分がどの名前で呼ばれたかを見てフォーマットを決めます——texdef なら plain TeX、latexdef なら LaTeX。だから素の texdef \LaTeX は undefined を返し、これはバグではありません。同じことは -t latex や -t lualatex でも指定できます。もっと便利なのが探索系のオプションです。-F は定義された場所そのものを教えてくれます——latexdef -p booktabs -F \toprule は \toprule first defined in "/usr/local/texlive/2024/texmf-dist/tex/latex/booktabs/booktabs.sty". と答えます。-l を使えば、そのパッケージが提供する利用者向け命令の一覧が出ます。説明書を開く前に、まず何があるのかを見たいときに向いています。
latexdef \section # the definition in force right now
latexdef -p amsmath \tfrac # with a package loaded
latexdef -p booktabs -F \toprule # which file defined it
latexdef -p geometry -l # the user-level commands a package adds
latexdef -c beamer \frametitle # inside a different document classchktex と lacheck — 二つのリンタが見ているものは別
どちらも「コンパイルは通るのに紙面が変」を捕まえる道具ですが、得意分野が違います。chktex は組版の作法を見ます。同じ原稿を通すと Warning 26 in lint.tex line 4: You ought to remove spaces in front of punctuation. や Warning 44 in lint.tex line 5: User Regex: 1:Capitalize before references. のような指摘が並び、しかも問題の桁を ^ で指し示します。警告に番号が付いているということは黙らせられるということで、まっすぐな二重引用符を TeX の引用符に直せと言う 18 番が邪魔なら chktex -n18 です。lacheck は構造の対応を見ます。環境や中括弧、数式の開始と終了が食い違っていると、開始と終了の両方を行番号つきで、<- と -> の対で示します。壊れた原稿で試すと "broken.tex", line 5: <- unmatched "\end{enumerate}" と "broken.tex", line 3: -> unmatched "\begin{itemize}" が続けて出ました。エンジンより先に、しかも読みやすい形で教えてくれます。
CI に入れるなら、決定的な違いを一つ知っておいてください。lacheck は何を見つけても終了コード 0 を返します。 上の壊れた原稿——環境の対応が二重に崩れ、数式が閉じていない——でも 0 でした。つまりビルドの成否では使えません。標準出力を捕まえて自分で判定する必要があります。chktex -q のほうは、警告を印字した回は 2 を、きれいな回は 0 を返しました。ゲートに使えるのはこちらです。もう一点、この TeX Live 2024 の macOS ビルドの chktex は POSIX 拡張正規表現で組まれていて、既定の規則の一つが Perl 系の先読みを使っているため、毎回 chktex: WARNING -- Compilation of regular expression で始まる一行が出ます。実害はありませんが、CI のログでは無視するように書いておくと静かになります。
chktex -q paper.tex # exit 2 when it prints warnings, 0 when clean
chktex -q -n18 -n26 paper.tex # mute the quotation-mark and punctuation rules
lacheck paper.tex # unmatched groups, shown as a <- and -> pair
lacheck paper.tex | tee lacheck.out # its exit code is always 0, so read this道具の性格を知るうえで、lacheck の man ページの BUGS 節は一読の価値があります。高度なマクロには混乱させられ、単純なマクロには騙され、TeX そのものは好きではなく、警告を個別に切ることもできない——そして自らを「at best a crude approximation」だと書いています。1990 年代前半に Kresten Krab Thorup が書き、Per Abrahamsen が手を入れた小さなツールが、いまも TeX Live に入り続けているのはこの正直さゆえかもしれません。chktex のほうも起動時のバナーに Copyright 1995-96 Jens T. Berger Thielemann. を掲げたままです。三十年近く前のツールが今日の原稿にまだ有効な指摘をする、というのが LaTeX の世界の速度でもあります。
texfot — 24 行のログを 4 行にする
TeX の出力が読まれなくなる理由は単純で、量が多すぎるからです。texfot はエンジンを代わりに起動し、その出力から 注目に値する行だけ を通します。手元で lipsum を使った 1 ページの文書を pdflatex で組むと端末に 24 行が流れましたが、同じものを texfot pdflatex で走らせると 4 行になりました。残ったのはエンジンのバージョン行、Overfull \hbox (122.18651pt too wide) detected at line 4、そして Output written on over.pdf (1 page, 19010 bytes). です。捨てられたのではなく、フィルタ前の全出力は一時ファイルに tee されているので、必要なら後から読めます(保存先を変えるなら --tee=、要らないなら --tee=/dev/null)。終了コードはエンジンのものをそのまま返すので、latexmk や CI に挟んでも判定は壊れません——エラーのある文書で試すと、素の pdflatex と同じく 1 が返りました。作者は Karl Berry です。
texfot pdflatex paper.tex
# texfot: invoking: pdflatex paper.tex
# This is pdfTeX, Version 3.141592653-2.6-1.40.26 (TeX Live 2024)
# Overfull \hbox (122.18651pt too wide) detected at line 4
# Output written on paper.pdf (1 page, 19010 bytes).
texfot --tee=/dev/null lualatex paper.tex # do not keep the full copy
# .latexmkrc: wrap the engine
$pdflatex = 'texfot pdflatex %O %S';texcount と texloganalyser — 語数を数える、ログを掘る
投稿規定に「本文 8,000 語以内」と書いてあるとき、wc -w は使えません。\usepackage もマクロ名も数えてしまうからです。texcount(TeXcount 3.1.1、2018 年 10 月)は LaTeX の構文を理解して数え、本文・見出し・キャプションを別々に、さらに数式の個数まで分けて報告します。-brief を付けると 2+0+0 (0/0/0/0) File: over.tex のように一行にまとまります。もう一方の texloganalyser(Thomas van Oudenhove、version 0.11、BSD ライセンス)は、すでに書き出された .log を後から掘る道具です。-o で過剰ボックスだけ、-r で相互参照の警告だけ、-i で読み込まれた画像、-s で使われた .sty と .cls を取り出します。texfot が「走らせながら絞る」のに対し、こちらは「終わったログから掘る」——用途が重ならないので両方入れておいて損はありません。
texcount -brief paper.tex # words in text + headers + captions
texcount -inc -sum paper.tex # follow \input and \include, one total
texloganalyser -o paper.log # only the overfull boxes
texloganalyser -r paper.log # only the reference warnings
texloganalyser -s paper.log # which .sty and .cls were actually loadedGhostscript — PDF を結合する、そして「圧縮」が効かない場合
gs は PostScript と PDF のインタプリタで、ps2pdf の中身でもあります。-sDEVICE=pdfwrite を指定すると PDF を書き出すので、PostScript から PDF への変換、複数 PDF の結合、そしてページの抽出が一行で片づきます。結合は特に単純で、入力を並べるだけです——手元で 7,940 バイトと 6,865 バイトの PDF を並べると 12,543 バイトの一冊になりました。なお gs は TeX Live には含まれていません。 MacTeX などが別途入れる Ghostscript で、この環境のバージョンは 10.03.0 です。
gs -q -sDEVICE=pdfwrite -dNOPAUSE -dBATCH \
-sOutputFile=merged.pdf front.pdf body.pdf
gs -q -sDEVICE=pdfwrite -dNOPAUSE -dBATCH \
-dFirstPage=3 -dLastPage=8 -sOutputFile=extract.pdf paper.pdf
gs -q -sDEVICE=pdfwrite -dPDFSETTINGS=/ebook -dNOPAUSE -dBATCH \
-sOutputFile=small.pdf big.pdfここで一つ、よく信じられている話を訂正しておきます。-dPDFSETTINGS は「PDF を圧縮するスイッチ」ではありません。 これらのプリセットが主に決めているのは 画像の再サンプリングの方針で、/screen(画面向け)から /ebook・/printer・/prepress へと解像度の下限が上がっていきます。したがってビットマップ画像を含まない文書では縮まりません。手元で試すと、文字だけの 6,865 バイトの PDF は /screen で 7,310、/ebook で 7,309、/prepress で 7,302、/printer にいたっては 9,869 バイトと、四つとも元より大きくなりました。PDF を作り直すぶんの上乗せだけが残るからです。写真やスキャン画像を大量に含む文書でこそ効くのがこのオプションです。そしていずれの場合も、通す前と後で フォントの埋め込み・リンク・しおり・ページサイズ を目で確かめてください。pdfwrite は PDF を再構築するので、目に見えない情報が落ちることがあります。
疑問からコマンドを引く
| コマンド | 答えてくれる疑問 |
|---|---|
latexdef NAME | この命令はいまどう定義されているのか。-F を足せば、どのファイルが定義したのか |
chktex -q | 原稿に組版上の癖はないか。CI のゲートに使える終了コードを返す |
lacheck | 環境や括弧の対応が崩れていないか。ただし終了コードは常に 0 |
texfot ENGINE FILE | この回のログのうち、本当に見るべき数行はどれか |
texcount -brief | 本文の語数はいくつか。マクロや \usepackage を数えずに |
texloganalyser -o | すでに書かれた .log から、過剰ボックスや参照の警告だけを掘り出す |
gs -sDEVICE=pdfwrite | PDF を結合したい、ページを抜きたい、画像入りの PDF を軽くしたい |