texdoc / texfot / Ghostscript / dvisvgm

Most of the commands in TeX Live do not typeset a document. They read one. texdef shows you what a command is actually defined as; chktex and lacheck point out the habits in your source; texfot cuts a thousand-line log down to a handful; texcount counts words; texloganalyser digs the lines you need out of a .log. What really consumes time in LaTeX work is not the typesetting but finding out why something did not work, so this corner of the distribution pays for the hour it takes to learn. Opening a package manual with texdoc belongs to another page; here we cover everything else, and finish with Ghostscript for operating on the finished PDF.

texdef: what is this command actually defined as

When redefinitions collide, the fastest way to learn which definition is currently in force is to ask the engine. Type latexdef \section and back comes \long macro:->\@startsection {section}{1}{\z@ }{-3.5ex \@plus -1ex \@minus -.2ex}{2.3ex \@plus .2ex}{\normalfont \Large \bfseries } — the actual value, in your actual installation. To look at it with a package loaded, add -p: latexdef -p amsmath \tfrac returns \genfrac {}{}{}1, and you can see at once that \tfrac is a thin wrapper around \genfrac. Hand it a name that does not exist and the answer is a curt undefined. The author is Martin Scharrer; the version in TeX Live 2024 is 1.9, dated 2020/09/27.

The same trick as dvipdfmx turns up here. latexdef is a symlink to texdef, and the program decides which format to load from the name it was invoked under: texdef means plain TeX, latexdef means LaTeX. That is why a bare texdef \LaTeX answers undefined, and it is not a bug. The same thing can be said explicitly with -t latex or -t lualatex. More useful still are the locating options. -F reports where a command was defined: latexdef -p booktabs -F \toprule answers \toprule first defined in "/usr/local/texlive/2024/texmf-dist/tex/latex/booktabs/booktabs.sty". And -l lists the user-level commands a package provides — handy when you want to see what is on offer before opening the manual.

terminal
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 class

chktex and lacheck: two linters looking at different things

Both catch the class of problem where the document compiles but the page looks wrong, and they specialise differently. chktex looks at typographic habit. Run the same file through it and you get numbered complaints such as Warning 26 in lint.tex line 4: You ought to remove spaces in front of punctuation. and Warning 44 in lint.tex line 5: User Regex: 1:Capitalize before references., each with a ^ marking the offending column. Numbered means silenceable: if rule 18, which asks you to replace a straight double quote with proper TeX quotes, is in your way, chktex -n18. lacheck looks at structural correspondence. When environments, braces or math delimiters do not match, it shows both ends with line numbers, paired as <- and ->. On a deliberately broken file it printed "broken.tex", line 5: <- unmatched "\end{enumerate}" immediately followed by "broken.tex", line 3: -> unmatched "\begin{itemize}" — earlier than the engine would, and in a far more readable shape.

If you are putting these into CI, one difference is decisive. lacheck returns exit code 0 no matter what it finds. The broken file above — two mismatched environments and an unclosed formula — still gave 0. You cannot gate a build on it; you have to capture its standard output and judge for yourself. chktex -q, by contrast, returned 2 on every run that printed warnings and 0 on a clean file. That is the one you can gate on. One more note: the chktex in this macOS build of TeX Live 2024 is compiled with POSIX extended regular expressions, and one of its default rules uses a Perl-style lookahead, so every run begins with a line starting chktex: WARNING -- Compilation of regular expression. It does no harm, but teaching your CI log to ignore it keeps things quiet.

terminal
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

To understand the character of these tools, the BUGS section of lacheck’s man page is worth reading. It admits that the program is confused by advanced macros and fooled by simple ones, that it does not like TeX, that it offers no way to switch individual warnings off — and describes itself as “at best a crude approximation”. Perhaps that honesty is why a small tool written by Kresten Krab Thorup in the early 1990s, with modifications by Per Abrahamsen, is still shipped in TeX Live today. chktex likewise still opens with the banner Copyright 1995-96 Jens T. Berger Thielemann. Tools nearly thirty years old that still make useful remarks about a manuscript written today: that is also the speed at which the LaTeX world moves.

texfot: turning 24 lines of log into 4

The reason nobody reads TeX’s output is simple: there is too much of it. texfot launches the engine on your behalf and passes through only the lines worth noticing. Here, a one-page document using lipsum scrolled 24 lines past under plain pdflatex; the same run under texfot pdflatex produced 4. What survived was the engine’s version line, Overfull \hbox (122.18651pt too wide) detected at line 4, and Output written on over.pdf (1 page, 19010 bytes). Nothing is discarded, either: the complete unfiltered output is teed to a temporary file, so you can read it afterwards if you need to — --tee= changes where it goes and --tee=/dev/null turns it off. The exit status is passed straight through from the engine, so slipping it into latexmk or CI does not break anything: on a document with an error it returned 1, exactly as bare pdflatex did. The author is Karl Berry.

terminal
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 and texloganalyser: counting words, mining the log

When a submission says “no more than 8,000 words of body text”, wc -w is useless: it counts \usepackage and every macro name. texcount — TeXcount 3.1.1, dated October 2018 — understands LaTeX syntax and counts accordingly, reporting body text, headers and captions separately, right down to how many formulas there are. Add -brief and it collapses to a single line such as 2+0+0 (0/0/0/0) File: over.tex. The other tool, texloganalyser (Thomas van Oudenhove, version 0.11, BSD licence), mines a .log that has already been written: -o pulls out only the overfull boxes, -r only the cross-reference warnings, -i the images that were loaded, -s the .sty and .cls files that were used. Where texfot filters while the engine runs, this one digs through the finished log; the two do not overlap, so keeping both around costs nothing.

terminal
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 loaded

Ghostscript: merging PDFs, and when “compression” does nothing

gs is the PostScript and PDF interpreter, and it is also what ps2pdf runs underneath. Give it -sDEVICE=pdfwrite and it writes PDF, which settles conversion from PostScript, merging several PDFs, and extracting pages in a single line each. Merging is the simplest of the three: list the inputs in order. Here, a 7,940-byte PDF and a 6,865-byte one became a single 12,543-byte volume. Note that gs is not part of TeX Live; it is the Ghostscript that MacTeX and similar installers add separately, and the version on this machine is 10.03.0.

terminal
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

One widely believed claim needs correcting here. -dPDFSETTINGS is not a switch that compresses a PDF. What those presets mainly govern is the policy for resampling images, with the resolution floor rising from /screen through /ebook and /printer to /prepress. A document with no bitmap images therefore has nothing to shrink. Tested here, a text-only PDF of 6,865 bytes came out at 7,310 with /screen, 7,309 with /ebook, 7,302 with /prepress and 9,869 with /printerall four larger than the original, because all that remains is the overhead of rebuilding the file. The option earns its keep on documents stuffed with photographs and scans. And in every case, check by eye before and after: embedded fonts, links, bookmarks and page size. pdfwrite reconstructs the PDF, and invisible information can be lost in the process.

Which command answers which question

CommandThe question it answers
latexdef NAMEHow is this command defined right now — and with -F, which file defined it
chktex -qDoes the source have typographic bad habits — and it returns a status you can gate CI on
lacheckAre environments and braces properly matched — but the exit code is always 0
texfot ENGINE FILEOut of this run’s log, which handful of lines actually matter
texcount -briefHow many words of body text are there, without counting macros or \usepackage
texloganalyser -oPull only the overfull boxes or reference warnings out of an existing .log
gs -sDEVICE=pdfwriteMerge PDFs, extract pages, or lighten an image-heavy PDF