TeXのターミナル出力がうるさい件

TeX文書をターミナルで処理させると、ターミナルに大量の出力が表示させる。

そのうち(パッケージ開発者ではない)一般ユーザーにも有益なものはほんのわずか(Undefined referenceとかOverfull hboxとか)で、大半は価値のない文字列である。一般人というのは「大量のメッセージが表示される」→「解読するのが面倒なので読まない」という思考回路で動く[要出典]ので、価値のない文字列が大量に表示されるのは有害である。(一般人はターミナルではなくTeXworksとかの統合環境を使うのでターミナルにどれだけ文字列が表示されようと関係ない、という説はある)

そこで、TeX文書の処理時に表示される文字列がなるべく少なくなるようにするにはどうしたらいいか考えよう。

なお、-interaction=batchmodeを指定すれば当然ターミナルに表示される文字列は減るが、しかしそれでは有益な情報も表示されなくなるし、何よりエラー時のメッセージもターミナルに表示されなくなってしまうので、-interaction=batchmode以外のモードで表示文字列を減らすことを考える。

サンプル

処理対象のファイル(ベンチマーク)を2つほどでっち上げよう。

ひとつめ test.tex:

\documentclass{article}
\usepackage{amsmath}
\usepackage{tikz}
\begin{document}
Hello world!
\end{document}

まずはamsmathとtikzを読み込むだけの、簡単なファイルである。

実行例:

$ max_print_line=65536 latex test.tex
This is pdfTeX, Version 3.14159265-2.6-1.40.19 (TeX Live 2018) (preloaded format=latex)
restricted \write18 enabled.
entering extended mode
(./test.tex
LaTeX2e <2018-04-01> patch level 2
Babel <3.18> and hyphenation patterns for 84 language(s) loaded.
(/usr/local/texlive/2018/texmf-dist/tex/latex/base/article.cls
Document Class: article 2014/09/29 v1.4h Standard LaTeX document class
(/usr/local/texlive/2018/texmf-dist/tex/latex/base/size10.clo)) (/usr/local/texlive/2018/texmf-dist/tex/latex/amsmath/amsmath.sty
For additional information on amsmath, use the `?' option.
(/usr/local/texlive/2018/texmf-dist/tex/latex/amsmath/amstext.sty (/usr/local/texlive/2018/texmf-dist/tex/latex/amsmath/amsgen.sty)) (/usr/local/texlive/2018/texmf-dist/tex/latex/amsmath/amsbsy.sty) (/usr/local/texlive/2018/texmf-dist/tex/latex/amsmath/amsopn.sty)) (/usr/local/texlive/2018/texmf-dist/tex/latex/pgf/frontendlayer/tikz.sty (/usr/local/texlive/2018/texmf-dist/tex/latex/pgf/basiclayer/pgf.sty (/usr/local/texlive/2018/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty (/usr/local/texlive/2018/texmf-dist/tex/generic/pgf/utilities/pgfutil-common.tex (/usr/local/texlive/2018/texmf-dist/tex/generic/pgf/utilities/pgfutil-common-lists.tex)) (/usr/local/texlive/2018/texmf-dist/tex/generic/pgf/utilities/pgfutil-latex.def (/usr/local/texlive/2018/texmf-dist/tex/latex/ms/everyshi.sty)) (/usr/local/texlive/2018/texmf-dist/tex/generic/pgf/utilities/pgfrcs.code.tex)) (/usr/local/texlive/2018/texmf-dist/tex/latex/pgf/basiclayer/pgfcore.sty (/usr/local/texlive/2018/texmf-dist/tex/latex/graphics/graphicx.sty (/usr/local/texlive/2018/texmf-dist/tex/latex/graphics/keyval.sty) (/usr/local/texlive/2018/texmf-dist/tex/latex/graphics/graphics.sty (/usr/local/texlive/2018/texmf-dist/tex/latex/graphics/trig.sty) (/usr/local/texlive/2018/texmf-dist/tex/latex/graphics-cfg/graphics.cfg) (/usr/local/texlive/2018/texmf-dist/tex/latex/graphics-def/dvips.def))) (/usr/local/texlive/2018/texmf-dist/tex/latex/pgf/systemlayer/pgfsys.sty (/usr/local/texlive/2018/texmf-dist/tex/generic/pgf/systemlayer/pgfsys.code.tex (/usr/local/texlive/2018/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex (/usr/local/texlive/2018/texmf-dist/tex/generic/pgf/utilities/pgfkeysfiltered.code.tex)) (/usr/local/texlive/2018/texmf-dist/tex/generic/pgf/systemlayer/pgf.cfg) (/usr/local/texlive/2018/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-dvips.def (/usr/local/texlive/2018/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-common-postscript.def))) (/usr/local/texlive/2018/texmf-dist/tex/generic/pgf/systemlayer/pgfsyssoftpath.code.tex) (/usr/local/texlive/2018/texmf-dist/tex/generic/pgf/systemlayer/pgfsysprotocol.code.tex)) (/usr/local/texlive/2018/texmf-dist/tex/latex/xcolor/xcolor.sty (/usr/local/texlive/2018/texmf-dist/tex/latex/graphics-cfg/color.cfg)) (/usr/local/texlive/2018/texmf-dist/tex/generic/pgf/basiclayer/pgfcore.code.tex (/usr/local/texlive/2018/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex (/usr/local/texlive/2018/texmf-dist/tex/generic/pgf/math/pgfmathcalc.code.tex (/usr/local/texlive/2018/texmf-dist/tex/generic/pgf/math/pgfmathutil.code.tex) (/usr/local/texlive/2018/texmf-dist/tex/generic/pgf/math/pgfmathparser.code.tex) (/usr/local/texlive/2018/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.code.tex (/usr/local/texlive/2018/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.basic.code.tex) (/usr/local/texlive/2018/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.trigonometric.code.tex) (/usr/local/texlive/2018/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.random.code.tex) (/usr/local/texlive/2018/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.comparison.code.tex) (/usr/local/texlive/2018/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.base.code.tex) (/usr/local/texlive/2018/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.round.code.tex) (/usr/local/texlive/2018/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.misc.code.tex) (/usr/local/texlive/2018/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.integerarithmetics.code.tex))) (/usr/local/texlive/2018/texmf-dist/tex/generic/pgf/math/pgfmathfloat.code.tex)) (/usr/local/texlive/2018/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepoints.code.tex) (/usr/local/texlive/2018/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathconstruct.code.tex) (/usr/local/texlive/2018/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathusage.code.tex) (/usr/local/texlive/2018/texmf-dist/tex/generic/pgf/basiclayer/pgfcorescopes.code.tex) (/usr/local/texlive/2018/texmf-dist/tex/generic/pgf/basiclayer/pgfcoregraphicstate.code.tex) (/usr/local/texlive/2018/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretransformations.code.tex) (/usr/local/texlive/2018/texmf-dist/tex/generic/pgf/basiclayer/pgfcorequick.code.tex) (/usr/local/texlive/2018/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreobjects.code.tex) (/usr/local/texlive/2018/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathprocessing.code.tex) (/usr/local/texlive/2018/texmf-dist/tex/generic/pgf/basiclayer/pgfcorearrows.code.tex) (/usr/local/texlive/2018/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreshade.code.tex) (/usr/local/texlive/2018/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreimage.code.tex (/usr/local/texlive/2018/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreexternal.code.tex)) (/usr/local/texlive/2018/texmf-dist/tex/generic/pgf/basiclayer/pgfcorelayers.code.tex) (/usr/local/texlive/2018/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretransparency.code.tex) (/usr/local/texlive/2018/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepatterns.code.tex))) (/usr/local/texlive/2018/texmf-dist/tex/generic/pgf/modules/pgfmoduleshapes.code.tex) (/usr/local/texlive/2018/texmf-dist/tex/generic/pgf/modules/pgfmoduleplot.code.tex) (/usr/local/texlive/2018/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-0-65.sty) (/usr/local/texlive/2018/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-1-18.sty)) (/usr/local/texlive/2018/texmf-dist/tex/latex/pgf/utilities/pgffor.sty (/usr/local/texlive/2018/texmf-dist/tex/latex/pgf/utilities/pgfkeys.sty (/usr/local/texlive/2018/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex)) (/usr/local/texlive/2018/texmf-dist/tex/latex/pgf/math/pgfmath.sty (/usr/local/texlive/2018/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex)) (/usr/local/texlive/2018/texmf-dist/tex/generic/pgf/utilities/pgffor.code.tex (/usr/local/texlive/2018/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex))) (/usr/local/texlive/2018/texmf-dist/tex/generic/pgf/frontendlayer/tikz/tikz.code.tex (/usr/local/texlive/2018/texmf-dist/tex/generic/pgf/libraries/pgflibraryplothandlers.code.tex) (/usr/local/texlive/2018/texmf-dist/tex/generic/pgf/modules/pgfmodulematrix.code.tex) (/usr/local/texlive/2018/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibrarytopaths.code.tex)))
No file test.aux.
ABD: EveryShipout initializing macros [1] (./test.aux) )
Output written on test.dvi (1 page, 5048 bytes).
Transcript written on test.log.

max_print_line変数を指定しているから行数は少なく見えるが、横にめちゃくちゃ長い。スクロールして最後まで読むか、max_print_lineを指定しない状態で、ぜひご自分で実行していただきたい。

ふたつめ testltja.tex:

\documentclass{ltjsarticle}
\usepackage{amsmath}
\begin{document}
こんにちは、世界!
\end{document}

最近はLuaTeXが流行りなので、もう一つのファイルではLuaTeX-jaを使ってみよう。

実行例:

$ max_print_line=65536 lualatex testltja.tex
This is LuaTeX, Version 1.07.0 (TeX Live 2018) 
restricted system commands enabled.
(./testltja.tex
LaTeX2e <2018-04-01> patch level 2
(using write cache: /Users/aratamizuki/Library/texlive/2018/texmf-var/luatex-cache/generic)(using read cache: /usr/local/texlive/2018/texmf-var/luatex-cache/generic /Users/aratamizuki/Library/texlive/2018/texmf-var/luatex-cache/generic)
luaotfload | main : initialization completed in 0.175 seconds
Babel <3.18> and hyphenation patterns for 1 language(s) loaded.
(/usr/local/texlive/2018/texmf-dist/tex/luatex/luatexja/ltjsarticle.cls
Document Class: ltjsarticle 2018/03/22 ltjsclasses 
(/usr/local/texlive/2018/texmf-dist/tex/luatex/luatexja/luatexja.sty (/usr/local/texlive/2018/texmf-dist/tex/luatex/luatexja/luatexja-core.sty (/usr/local/texlive/2018/texmf-dist/tex/luatex/luatexbase/luatexbase.sty (/usr/local/texlive/2018/texmf-dist/tex/luatex/ctablestack/ctablestack.sty)) (/usr/local/texlive/2018/texmf-dist/tex/generic/oberdiek/ltxcmds.sty) (/usr/local/texlive/2018/texmf-dist/tex/generic/oberdiek/pdftexcmds.sty (/usr/local/texlive/2018/texmf-dist/tex/generic/oberdiek/infwarerr.sty) (/usr/local/texlive/2018/texmf-dist/tex/generic/oberdiek/ifluatex.sty) (/usr/local/texlive/2018/texmf-dist/tex/generic/oberdiek/ifpdf.sty)) (/usr/local/texlive/2018/texmf-dist/tex/latex/xkeyval/xkeyval.sty (/usr/local/texlive/2018/texmf-dist/tex/generic/xkeyval/xkeyval.tex (/usr/local/texlive/2018/texmf-dist/tex/generic/xkeyval/xkvutils.tex (/usr/local/texlive/2018/texmf-dist/tex/generic/xkeyval/keyval.tex)))) (/usr/local/texlive/2018/texmf-dist/tex/generic/oberdiek/atbegshi.sty) (/usr/local/texlive/2018/texmf-dist/tex/latex/etoolbox/etoolbox.sty) (/usr/local/texlive/2018/texmf-dist/tex/latex/everyhook/everyhook.sty (/usr/local/texlive/2018/texmf-dist/tex/latex/svn-prov/svn-prov.sty))(load cache: /Users/aratamizuki/Library/texlive/2018/texmf-var/luatexja/ltj-cid-auto-adobe-japan1.luc) (/usr/local/texlive/2018/texmf-dist/tex/luatex/luatexja/ltj-base.sty) (/usr/local/texlive/2018/texmf-dist/tex/luatex/luatexja/ltj-latex.sty (/usr/local/texlive/2018/texmf-dist/tex/luatex/luatexja/patches/lltjfont.sty (/usr/local/texlive/2018/texmf-dist/tex/latex/base/tuenc.def) (/usr/local/texlive/2018/texmf-dist/tex/latex/ms/everysel.sty) ABD: EverySelectfont initializing macros) (/usr/local/texlive/2018/texmf-dist/tex/luatex/luatexja/patches/lltjdefs.sty(load luc: /Users/aratamizuki/Library/texlive/2018/texmf-var/luatex-cache/generic/fonts/otl/lmroman10-regular.luc)(load luc: /Users/aratamizuki/Library/texlive/2018/texmf-var/luatex-cache/generic/fonts/otl/ipaexm.luc)(load cache: /Users/aratamizuki/Library/texlive/2018/texmf-var/luatexja/extra_ipaexmincho.luc)
(/usr/local/texlive/2018/texmf-dist/tex/luatex/luatexja/jfm-ujisv.lua)
(/usr/local/texlive/2018/texmf-dist/tex/luatex/luatexja/jfm-ujis.lua)) (/usr/local/texlive/2018/texmf-dist/tex/luatex/luatexja/patches/lltjcore.sty) (/usr/local/texlive/2018/texmf-dist/tex/luatex/luatexja/patches/lltjp-geometry.sty (/usr/local/texlive/2018/texmf-dist/tex/latex/filehook/filehook.sty)))) (/usr/local/texlive/2018/texmf-dist/tex/luatex/luatexja/luatexja-compat.sty(load cache: /Users/aratamizuki/Library/texlive/2018/texmf-var/luatexja/ltj-jisx0208.luc)))(load luc: /Users/aratamizuki/Library/texlive/2018/texmf-var/luatex-cache/generic/fonts/otl/lmroman8-regular.luc) (/usr/local/texlive/2018/texmf-dist/tex/platex/jsclasses/jslogo.sty) (/usr/local/texlive/2018/texmf-dist/tex/latex/sttools/stfloats.sty)) (/usr/local/texlive/2018/texmf-dist/tex/latex/amsmath/amsmath.sty
For additional information on amsmath, use the `?' option.
(/usr/local/texlive/2018/texmf-dist/tex/latex/amsmath/amstext.sty (/usr/local/texlive/2018/texmf-dist/tex/latex/amsmath/amsgen.sty)) (/usr/local/texlive/2018/texmf-dist/tex/latex/amsmath/amsbsy.sty) (/usr/local/texlive/2018/texmf-dist/tex/latex/amsmath/amsopn.sty))
No file testltja.aux.
(/usr/local/texlive/2018/texmf-dist/tex/luatex/luatexja/patches/lltjp-stfloats.sty) ABD: EverySelectfont initializing macros [1{/usr/local/texlive/2018/texmf-var/fonts/map/pdftex/updmap/pdftex.map}] (./testltja.aux))
3071 words of node memory still in use:
9 hlist, 2 vlist, 5 rule, 2 glue, 32 kern, 1112 attribute, 57 glue_spec, 64 attribute_list, 1 write, 13 user_defined nodes
avail lists: 1:5,2:1169,3:10,4:13,5:17,6:2,7:68,8:16,9:16
</usr/local/texlive/2018/texmf-dist/fonts/opentype/public/lm/lmroman10-regular.otf></usr/local/texlive/2018/texmf-dist/fonts/truetype/public/ipaex/ipaexm.ttf>
Output written on testltja.pdf (1 page, 109746 bytes).
Transcript written on testltja.log.

これも横にめちゃくちゃ長い。

これらのファイルの処理時に発生するターミナルへの出力を削減する、ということが目標となる。

\inputするファイル名

TeXで\inputすると、読み込んだファイル名が括弧付きで表示される。上記2つの実行例について、ターミナルへの出力の大半を占めるのはこれである。

\usepackageで読み込んだLaTeXパッケージ (.sty) ならともかく、そこからさらに読み込まれたファイルなんかはユーザーの知ったことではないので、一般ユーザーには表示される必要はない。

これを抑制する方法はあるだろうか。

Knuthの書いたtex.webを読むと(texdoc tex で読める。procedure start_input;print_char("("); … の部分)、この「読み込んだファイル名を括弧付きで表示する」挙動はハードコードされており、パラメーターで変えられる様子はない。どうしてもこれらの出力を除去したかったら、パイプでTeXの出力を受け取ってファイル名の部分を認識して取り除くしかないだろう(開きかっこはともかく、閉じかっこは他の出力と紛らわしいので、綺麗に除去することは難しいだろう)。

LuaTeXの場合

LuaTeXはこの「読み込んだファイル名をかっこ付きで表示する」挙動をカスタマイズできるようになっている。

具体的には、luatexコマンドの--luaオプションにLuaのファイル名を与えるとそのファイルでLuaTeXの挙動をカスタマイズすることができる。

そこでカスタマイズできる設定としては

  • texconfig.trace_file_names
  • start_file, stop_file callback

の2通りがあるが、前者は texconfig.kpse_init を false にする必要がありよくわからん感じなので、もっぱら後者を考える。

LuaTeXのcallbackという仕組みは、LuaTeXの各種動作をLuaの関数によって乗っ取ることを可能にする。御託はいいから実際のコード例で見てみよう。

次の内容をmyinit.luaとして保存する。

local function start_file_cb(category, filename)
  if category == 1 then -- a normal data file, like a TeX source
    texio.write("("..filename)
  elseif category == 2 then -- a font map coupling font names to resources
    texio.write("{"..filename)
  elseif category == 3 then -- an image file (png, pdf, etc)
    texio.write("<"..filename)
  elseif category == 4 then -- an embedded font subset
    texio.write("<"..filename)
  elseif category == 5 then -- a fully embedded font
    texio.write("<<"..filename)
  else
    print("start_file: unknown category", category, filename)
  end
end
callback.register("start_file", start_file_cb)
local function stop_file_cb(category)
  if category == 1 then
    texio.write(")")
  elseif category == 2 then
    texio.write("}")
  elseif category == 3 then
    texio.write(">")
  elseif category == 4 then
    texio.write(">")
  elseif category == 5 then
    texio.write(">>")
  else
    print("stop_file: unknown category", category)
  end
end
callback.register("stop_file", stop_file_cb)

この状態で

$ lualatex --lua=myinit.lua testltja.tex

を実行…してもあまり変わった風には見えないだろう。(Luaで書いたコールバック関数の内容を、LuaTeXの元々の挙動を真似るようにしたため)

start_file callback と stop_file callback では、ファイルの種類ごとに何を実行するか決めることができる。今回は「TeXファイル」「font mapファイル」のターミナルへの出力を抑制しよう。つまり、これらのファイルについては標準出力へはファイル名を出力せず、ログファイルのみにファイル名を出力する。

local function start_file_cb(category, filename)
  if category == 1 then -- a normal data file, like a TeX source
    texio.write("log", "("..filename)
  elseif category == 2 then -- a font map coupling font names to resources
    texio.write("log", "{"..filename)
  elseif category == 3 then -- an image file (png, pdf, etc)
    texio.write("<"..filename)
  elseif category == 4 then -- an embedded font subset
    texio.write("<"..filename)
  elseif category == 5 then -- a fully embedded font
    texio.write("<<"..filename)
  else
    print("start_file: unknown category", category, filename)
  end
end
callback.register("start_file", start_file_cb)
local function stop_file_cb(category)
  if category == 1 then
    texio.write("log", ")")
  elseif category == 2 then
    texio.write("log", "}")
  elseif category == 3 then
    texio.write(">")
  elseif category == 4 then
    texio.write(">")
  elseif category == 5 then
    texio.write(">>")
  else
    print("stop_file: unknown category", category)
  end
end
callback.register("stop_file", stop_file_cb)

これを使った test.tex の処理結果は

$ lualatex --lua=myinit.lua test.tex
This is LuaTeX, Version 1.07.0 (TeX Live 2018) 
 restricted system commands enabled.

LaTeX2e <2018-04-01> patch level 2
(using write cache: /Users/aratamizuki/Library/texlive/2018/texmf-var/luatex-ca
che/generic)(using read cache: /usr/local/texlive/2018/texmf-var/luatex-cache/g
eneric /Users/aratamizuki/Library/texlive/2018/texmf-var/luatex-cache/generic)
luaotfload | main : initialization completed in 0.167 seconds
Babel <3.18> and hyphenation patterns for 1 language(s) loaded.

Document Class: article 2014/09/29 v1.4h Standard LaTeX document class
(load luc: /Users/aratamizuki/Library/texlive/2018/texmf-var/luatex-cache/gener
ic/fonts/otl/lmroman10-regular.luc)
For additional information on amsmath, use the `?' option.
ABD: EveryShipout initializing macros
[Loading MPS to PDF converter (version 2006.09.02).]
 [1]
 427 words of node memory still in use:
   5 hlist, 2 vlist, 2 rule, 2 glue, 1 kern, 5 attribute, 48 glue_spec, 5 attri
bute_list, 1 write nodes
   avail lists: 2:23,3:2,4:5,5:23,6:1,7:24,8:1,9:9
</usr/local/texlive/2018/texmf-dist/fonts/opentype/public/lm/lmroman10-regular.
otf>
Output written on test.pdf (1 page, 3340 bytes).
Transcript written on test.log.

testltja.tex の処理結果は

$ lualatex --lua=myinit.lua testltja.tex
This is LuaTeX, Version 1.07.0 (TeX Live 2018) 
 restricted system commands enabled.

LaTeX2e <2018-04-01> patch level 2
(using write cache: /Users/aratamizuki/Library/texlive/2018/texmf-var/luatex-ca
che/generic)(using read cache: /usr/local/texlive/2018/texmf-var/luatex-cache/g
eneric /Users/aratamizuki/Library/texlive/2018/texmf-var/luatex-cache/generic)
luaotfload | main : initialization completed in 0.141 seconds
Babel <3.18> and hyphenation patterns for 1 language(s) loaded.

Document Class: ltjsarticle 2018/03/22 ltjsclasses 
(load cache: /Users/aratamizuki/Library/texlive/2018/texmf-var/luatexja/ltj-cid
-auto-adobe-japan1.luc) ABD: EverySelectfont initializing macros(load luc: /Use
rs/aratamizuki/Library/texlive/2018/texmf-var/luatex-cache/generic/fonts/otl/lm
roman10-regular.luc)(load luc: /Users/aratamizuki/Library/texlive/2018/texmf-va
r/luatex-cache/generic/fonts/otl/ipaexm.luc)(load cache: /Users/aratamizuki/Lib
rary/texlive/2018/texmf-var/luatexja/extra_ipaexmincho.luc)
(/usr/local/texlive/2018/texmf-dist/tex/luatex/luatexja/jfm-ujisv.lua)
(/usr/local/texlive/2018/texmf-dist/tex/luatex/luatexja/jfm-ujis.lua)(load cach
e: /Users/aratamizuki/Library/texlive/2018/texmf-var/luatexja/ltj-jisx0208.luc)
(load luc: /Users/aratamizuki/Library/texlive/2018/texmf-var/luatex-cache/gener
ic/fonts/otl/lmroman8-regular.luc)
For additional information on amsmath, use the `?' option.
 ABD: EverySelectfont initializing macros [1]
 3071 words of node memory still in use:
   9 hlist, 2 vlist, 5 rule, 2 glue, 32 kern, 1112 attribute, 57 glue_spec, 64 
attribute_list, 1 write, 13 user_defined nodes
   avail lists: 1:5,2:1169,3:10,4:13,5:17,6:2,7:68,8:16,9:16
</usr/local/texlive/2018/texmf-dist/fonts/opentype/public/lm/lmroman10-regular.
otf></usr/local/texlive/2018/texmf-dist/fonts/truetype/public/ipaex/ipaexm.ttf>

Output written on testltja.pdf (1 page, 109746 bytes).
Transcript written on testltja.log.

となる。最初の状態に比べるとだいぶスッキリしたのではないだろうか。(これが「スッキリした」ように見える人はだいぶTeXに毒されているのでしばらく断TeXした方が良い)

応用すれば、「システムで提供されるパッケージのみ出力を抑制する」「トップレベルのパッケージ名のみ表示する」というような調節もできるだろう。

LaTeXパッケージの出力メッセージ

ファイル名の出力を抑制したとはいえ、まだまだターミナルにたくさんの文字列が出力されている。これらの多くは、LaTeXパッケージが\messageやtexio.write, io.write等の命令によって表示するものである。

TeXプリミティブの\messageはともかく、Luaのtexio.writeやio.writeはLua側で細工すればメッセージを抑制できそうである。

luaotfload

まず目につくのは、luaotfloadが出力する、以下の形のメッセージである。

(using cache: )
(using write cache: )
(using read cache: )
(load luc: )
(load cache: )
luaotfload | main : initialization completed in .. seconds

普段使いする分にはこれらは必要ないので、消してしまおう。

myinit.luaに次を書き加える:

local texio_write = texio.write
texio.write = function(...)
  if select("#",...) == 1 then
    -- Suppress luaotfload's message (See src/fontloader/runtime/fontload-reference.lua)
    if string.match(...,"^%(using cache: ") then
      return
    elseif string.match(...,"^%(using write cache: ") then
      return
    elseif string.match(...,"^%(using read cache: ") then
      return
    elseif string.match(...,"^%(load luc: ") then
      return
    elseif string.match(...,"^%(load cache: ") then
      return
    end
  end
  return texio_write(...)
end
local io_write = io.write
io.write = function(...)
  if select("#",...) == 1 then
    if string.match(...,"^luaotfload | main : initialization completed in ") then
      return
    end
  end
  return io_write(...)
end

luaotfload | main : initialization completed in の方はグローバル変数 default_log_level-1 にとかに設定したらもっと綺麗に消せないかな〜〜と思ったがうまくいかなかっった。

ともかく、これで test.tex の処理時の出力は次のようになる:

$ lualatex --lua=myinit.lua test.tex
This is LuaTeX, Version 1.07.0 (TeX Live 2018) 
 restricted system commands enabled.

LaTeX2e <2018-04-01> patch level 2


Babel <3.18> and hyphenation patterns for 1 language(s) loaded.

Document Class: article 2014/09/29 v1.4h Standard LaTeX document class
For additional information on amsmath, use the `?' option.
ABD: EveryShipout initializing macros
[Loading MPS to PDF converter (version 2006.09.02).]
 [1]
 427 words of node memory still in use:
   5 hlist, 2 vlist, 2 rule, 2 glue, 1 kern, 5 attribute, 48 glue_spec, 5 attri
bute_list, 1 write nodes
   avail lists: 2:23,3:2,4:5,5:23,6:1,7:24,8:1,9:9
</usr/local/texlive/2018/texmf-dist/fonts/opentype/public/lm/lmroman10-regular.
otf>
Output written on test.pdf (1 page, 3340 bytes).
Transcript written on test.log.

testltja.texはこうだ:

$ lualatex --lua=myinit.lua testltja.tex
This is LuaTeX, Version 1.07.0 (TeX Live 2018) 
 restricted system commands enabled.

LaTeX2e <2018-04-01> patch level 2


Babel <3.18> and hyphenation patterns for 1 language(s) loaded.

Document Class: ltjsarticle 2018/03/22 ltjsclasses 
 ABD: EverySelectfont initializing macros
(/usr/local/texlive/2018/texmf-dist/tex/luatex/luatexja/jfm-ujisv.lua)
(/usr/local/texlive/2018/texmf-dist/tex/luatex/luatexja/jfm-ujis.lua)
For additional information on amsmath, use the `?' option.
 ABD: EverySelectfont initializing macros [1]
 3071 words of node memory still in use:
   9 hlist, 2 vlist, 5 rule, 2 glue, 32 kern, 1112 attribute, 57 glue_spec, 64 
attribute_list, 1 write, 13 user_defined nodes
   avail lists: 1:5,2:1169,3:10,4:13,5:17,6:2,7:68,8:16,9:16
</usr/local/texlive/2018/texmf-dist/fonts/opentype/public/lm/lmroman10-regular.
otf></usr/local/texlive/2018/texmf-dist/fonts/truetype/public/ipaex/ipaexm.ttf>

Output written on testltja.pdf (1 page, 109746 bytes).
Transcript written on testltja.log.

ターミナルへの出力がますますスッキリした。

LuaTeX-ja

testltja.texの出力を見ると、まだファイル名らしきものが表示されている。luatexja/jfm-***.luaというやつがそれだ。これはLuaTeX本体ではなく、LuaTeX-jaが独自に出力している文字列である。これも消そう。

myinit.luaに次を書き加える:

local texio_write_nl = texio.write_nl
texio.write_nl = function(...)
  if select("#",...) == 1 then
    if string.match(...,"^%(.*jfm%-.*%.lua%)$") then -- LuaTeX-ja: luatexja.load_lua
      return
    end
  end
  return texio_write_nl(...)
end

すると、testltja.texの処理時の出力は次のようになる:

$ lualatex --lua=myinit.lua testltja.tex
This is LuaTeX, Version 1.07.0 (TeX Live 2018) 
 restricted system commands enabled.

LaTeX2e <2018-04-01> patch level 2


Babel <3.18> and hyphenation patterns for 1 language(s) loaded.

Document Class: ltjsarticle 2018/03/22 ltjsclasses 
 ABD: EverySelectfont initializing macros
For additional information on amsmath, use the `?' option.
 ABD: EverySelectfont initializing macros [1]
 3071 words of node memory still in use:
   9 hlist, 2 vlist, 5 rule, 2 glue, 32 kern, 1112 attribute, 57 glue_spec, 64 
attribute_list, 1 write, 13 user_defined nodes
   avail lists: 1:5,2:1169,3:10,4:13,5:17,6:2,7:68,8:16,9:16
</usr/local/texlive/2018/texmf-dist/fonts/opentype/public/lm/lmroman10-regular.
otf></usr/local/texlive/2018/texmf-dist/fonts/truetype/public/ipaex/ipaexm.ttf>

Output written on testltja.pdf (1 page, 109746 bytes).
Transcript written on testltja.log.

(.../luatexja/jfm-*.lua) がちゃんと消えていることが確認できる。

amsmath

amsmathパッケージは、読み込み時に次のメッセージを表示する:

For additional information on amsmath, use the `?' option.

これはLaTeXの\typeout命令で出力されている。これを抑制したかったら、amsmathを読み込む前のどこかで

% amsmath対策コード
\def\@message@amsmath{For additional information on amsmath, use the \lq ?\rq\space option.}
\let\real@typeout=\typeout
\def\typeout#1{%
  \def\message@temp@{#1}%
  \ifx\message@temp@\@message@amsmath
  \else
    \real@typeout{#1}%
  \fi
}

を実行すれば良い。今回はtest.texの\documentclassの前に \makeatletter .. \makeatother で挟んでベタ書きした。

everysel

残った出力メッセージを見ると、

ABD: EverySelectfont initializing macros

というものもある。これはeveryselパッケージが表示するメッセージだ。

これはTeX primitiveの\messageで出力されている。TeX primitiveが受け取る引数のフォーマットはマクロのそれとは異なるので、安易に\messageをマクロで上書きしてやろうとすると罠にハマる可能性があるが、筆者レベルのTeXnicianであれば、〈general text〉を受け取るマクロを定義できる:

% everysel対策コード
\let\real@message=\message
\newtoks\message@temp
\def\@message@everysel{ABD: EverySelectfont initializing macros}
\def\do@message{%
  \edef\message@temp@{\the\message@temp}%
  \ifx\message@temp@\@message@everysel
  \else
    \real@message\expandafter{\the\message@temp}%
  \fi
}
\def\message{%
  \afterassignment\do@message
  \message@temp=
}

これを、さっきのamsmath対策コードの隣に置いておけば良い。

これら(amsmath対策コード、everysel対策コード)を適用した後のtestltja.texを処理させた時の出力は

$ lualatex --lua=myinit.lua testltja.tex
This is LuaTeX, Version 1.07.0 (TeX Live 2018) 
 restricted system commands enabled.

LaTeX2e <2018-04-01> patch level 2


Babel <3.18> and hyphenation patterns for 1 language(s) loaded.

Document Class: ltjsarticle 2018/03/22 ltjsclasses 
[1]
 3071 words of node memory still in use:
   9 hlist, 2 vlist, 5 rule, 2 glue, 32 kern, 1112 attribute, 57 glue_spec, 64 
attribute_list, 1 write, 13 user_defined nodes
   avail lists: 1:5,2:1169,3:10,4:13,5:17,6:2,7:68,8:16,9:16
</usr/local/texlive/2018/texmf-dist/fonts/opentype/public/lm/lmroman10-regular.
otf></usr/local/texlive/2018/texmf-dist/fonts/truetype/public/ipaex/ipaexm.ttf>

Output written on testltja.pdf (1 page, 109746 bytes).
Transcript written on testltja.log.

となる。

LuaLaTeXの統計データ(\tracingstats)

さて、LuaLaTeXが出力するメッセージを順調に削減していったわけだが、出力の後半部に「3071 words of node memory still in use:」というようなメッセージが表示されていることにお気づきだろうか。

これはLuaTeXで\tracingstatsというパラメーターを設定した時に表示される統計情報の一部である。そして、LaTeXでは標準で\tracingstatsが1に設定される。

\tracingstats自体はLuaTeX以外のTeX処理系にも存在するが、他のTeX処理系はログファイルのみに統計情報を書き出すのに対し、LuaTeXではこの統計情報の一部が標準出力にも書き出されてしまう。

これは…LuaTeX本体の挙動を変えるべきな気がする。

既存ツール

TeXの出力がうるさい!と思った人は筆者の他にもいたらしく、ググったらlatexrunというツールが見つかった。

これはPython製のツールで、メッセージをいい感じに整形(?)して表示してくれるようだ。標準出力を解釈しているのか、ログファイルを解釈しているのかは(ソースを読んでいないので)よくわからない。誰か日本語の紹介記事を書いてくれると嬉しい。

ClutTeXへの実装

【7月29日 追記】

ClutTeXとは、筆者が作っているLaTeX実行自動化ツールである。「カレントディレクトリを .aux や .log などで散らかさない」ことが特徴である。詳しくは以前書いたブログ記事

TeX 実行の自動化ツールを作った (ClutTeX)

を参照して欲しい。

さて、この記事に書いたLuaTeX向けテクニックのいくつかを、先ほどこの自動化ツールに実装した(無効化するオプションは今の所実装していない)。なので、この記事に書いたテクニックの効果を自分で見てみたい方はClutTeXを利用すると良い。