Proofreading (proofread)

If a reviewer has ever sent you a comment keyed to “page 12, third paragraph, fourth line”, you already know what LaTeX proofreading needs first: line numbers, from the lineno package. Many journals require a line-numbered manuscript on submission, and with numbers in the margin a comment costs one token — “L412”. This page follows a full review cycle: numbering the lines, pinning to-dos in the margin, colour-coding each co-author's edits, using latexdiff to show someone exactly what changed since the last draft, and turning three linters — chktex, lacheck and nag — loose on the source. Every step below is shown with output from an actual run.

Line numbers for a review copy: the lineno package

Load \usepackage{lineno}, write \linenumbers, and every line of body text from that point on gets a number in the left margin. Options change the presentation: modulo numbers only every fifth line, which keeps the margin quiet; pagewise restarts the count at 1 on each page; switch puts the numbers in the outer margin for two-sided work. \nolinenumbers turns them off again, and the linenumbers environment numbers a range. Numbering only part of a document — the body but not the appendix, say — is an everyday requirement.

latex
\usepackage[modulo]{lineno}   % number every 5th line only
% \usepackage[pagewise]{lineno} % restart the count on each page
% \usepackage[switch]{lineno}   % outer margin, for twoside
\linenumbers
...
\nolinenumbers                % stop numbering (e.g. before the appendix)

Here is the pitfall that will make a review conversation go sideways. By default, displayed equations are not numbered. Measured on a document containing an amsmath equation and an align, the body text ran 1, 2, 3 — stepping straight over the mathematics. Add \usepackage[mathlines]{lineno} to the same document and the count runs 1 to 6, with each line of each display numbered too. In other words, whether mathlines is set changes what “L4” points at, and if reviewer and author are looking at PDFs built with different settings, the discussion will not line up. For a maths-heavy manuscript, turning mathlines on is the safer choice.

Option or commandEffect
\linenumbersstart numbering the body text from here on
\nolinenumbersstop numbering (put it just before the appendix, say)
moduloprint a number only on every fifth line
pagewiserestart the count at 1 on every page
switchput the numbers in the outer margin for two-sided work
mathlinesnumber the lines of displayed formulas too (off by default)

lineno is an old tool, going back to 1995; the version in TeX Live 2024 is v5.3, dated 20 May 2023. Three generations of maintainers are listed in the copyright notice at the top of the package: Stephan I. Böttcher for 1995–2003, Uwe Lück for the 4.x series, and Karl Wette, who took over the 5.x series in 2021. Thirty years of compatibility work leaves marks, and the package does not always combine tidily with others. Load order can matter, so if the numbers refuse to appear, try loading lineno last.

How to use latexdiff: show a co-author exactly what changed

Run latexdiff old.tex new.tex > diff.tex and compile the resulting diff.tex with pdflatex as usual. That is the whole procedure, and it yields a PDF in which added and deleted wording are visually distinct. In an actual run, latexdiff threads markers — \DIFaddbegin, \DIFadd{...}, \DIFdelbegin, \DIFdel{...} — through the prose and adds \RequirePackage[normalem]{ulem} plus colour definitions to the preamble. What makes this the highest-value tool in the whole proofreading kit is that it spares your reader the job of reading LaTeX: the difference shows up on a typeset page, not in a git diff.

terminal
# the whole workflow
latexdiff old.tex new.tex > diff.tex
pdflatex diff.tex

# one file made of many \input files: flatten first
latexdiff --flatten old/main.tex new/main.tex > diff.tex

# diff straight against a git revision (produces main-diffHEAD~1.tex)
latexdiff-vc --git --flatten -r HEAD~1 main.tex

# a different visual style, e.g. bold instead of underline
latexdiff --type=CFONT old.tex new.tex > diff.tex

The default appearance is a little more specific than the usual description of “additions underlined, deletions struck through”. The version in TeX Live 2024 is v1.3.3latexdiff --version identifies itself as “(c) 2004-2022 F J Tilmann” — and the preamble it injects defines \DIFadd as {\protect\color{blue}\uwave{#1}} and \DIFdel as {\protect\color{red}\sout{#1}}. So: additions are a blue wavy underline, deletions a red strikeout. That default has a name, --type=UNDERLINE, and the alternatives are CTRADITIONAL, TRADITIONAL, CFONT, FONTSTRIKE, INVISIBLE, CHANGEBAR, CCHANGEBAR, CULINECHBAR, CFONTCHBAR, BOLD and PDFCOMMENT. For a reviewer who will print in black and white, FONTSTRIKE or BOLD reads far better.

latex
% What latexdiff actually writes into diff.tex (excerpt of a real run):
\RequirePackage[normalem]{ulem}
\providecommand{\DIFadd}[1]{{\protect\color{blue}\uwave{#1}}}
\providecommand{\DIFdel}[1]{{\protect\color{red}\sout{#1}}}
...
The measured value was \DIFdelbegin \DIFdel{3.2}\DIFdelend
  \DIFaddbegin \DIFadd{3.4}\DIFaddend \,mm.

There are two places this earns its keep. One is the revised submission: many journals ask for a marked-up version alongside the clean one, and latexdiff output is that deliverable. The other is sending drafts to co-authors. For a document split across files, --flatten expands the \inputs before comparing, and latexdiff-vc --git --flatten -r HEAD~1 main.tex compares the working tree straight against an earlier commit, writing main-diffHEAD~1.tex. One caveat: latexdiff treats LaTeX as text, not as syntax, so changes inside tables and figures can break the markup. When that happens, add the offending command to the safe list with --append-safecmd, or exclude the environment with --exclude-textcmd.

Colour-coding each co-author: the changes package

Where latexdiff compares two versions from outside, changes records the edits inside the source. Register the authors — \definechangesauthor[name={Ada Lovelace}, color=blue]{AL} — and then mark up with \added[id=AL]{...}, \deleted[id=AL]{...}, \replaced[id=AT]{new}{old} and \comment[id=AT]{...}. Add \listofchanges and you get a “List of changes”; in an actual run it listed Added (AL): ..., Replaced (AT): ..., Deleted (AL): ... and Commented (AT): ..., each attributed to its author. The version in TeX Live 2024 is v4.2.1 (2021/07/15).

latex
\usepackage[markup=underlined]{changes}   % draft look; the default
\definechangesauthor[name={Ada Lovelace}, color=blue]{AL}
\definechangesauthor[name={Alan Turing},  color=orange]{AT}
\begin{document}
\listofchanges
The engine \added[id=AL]{weaves algebraical patterns} and
\replaced[id=AT]{computes}{calculates} the numbers.
\deleted[id=AL]{This sentence is redundant.}
\comment[id=AT]{Check the citation here.}

The finishing move matters. Switch to \usepackage[final]{changes} and the package does not merely hide the markup — it applies the edits. In an actual run, the \added wording stayed, \replaced kept only the new text, and both the \deleted sentence and the \comment vanished, leaving the clean sentence “The engine weaves algebraical patterns and computes the numbers. Ordinary text.” You therefore never have to strip the commands by hand to produce a final version. The corollary is that the PDF before and after the switch say different things, so always rebuild in final mode and reread before submitting.

Pinning to-dos in the margin: todonotes and \todo

A comment written with % disappears when you compile, which means your co-author never sees it. todonotes exists to keep to-dos in the output. \todo{check this number} draws a sticky note in the margin, \todo[inline]{...} places a band in the flow of the text, and \missingfigure{plot of the residuals} draws a placeholder box saying a figure belongs here. \listoftodos produces a “Todo list” at the front; in an actual run each item appeared there with its page number, so you can see at a glance what is still outstanding.

latex
\usepackage[textwidth=3cm]{todonotes}
% \usepackage[disable]{todonotes}   % final version: hides notes AND the list
\begin{document}
\listoftodos
Some text.\todo{check this number}
More text.\todo[inline,color=green!30]{rewrite this paragraph}
\missingfigure{plot of the residuals}

For the final version, swap in \usepackage[disable]{todonotes}. Measured, that removes the margin notes, the \missingfigure boxes and the “Todo list” at the front as well — while the commands stay in the source, so dropping disable at the next revision brings every to-do back. That is the decisive difference from a % comment: the note is hidden rather than destroyed. The risk is submitting with disable still on and nobody noticing that open items remain. Make “turn disable off once and read \listoftodos” a fixed step just before submission.

chktex and lacheck: catching what pdflatex never mentions

These two catch mistakes that are typographically wrong but perfectly compilable — because pdflatex only cares whether the run succeeds. A concrete case: put the line As shown in Fig. 1 and in Table \ref{tab:one}, see also \cite{knuth1984}. through pdflatex and all you get back is LaTeX Warning: Reference 'tab:one' on page 1 undefined, a remark about cross-references. Put the same line through chktex and this warning fires twice:

terminal
$ chktex -q ref.tex
Warning 2 in ref.tex line 3: Non-breaking space (`~') should have been used.
As shown in Fig. 1 and in Table \ref{tab:one}, see also \cite{knuth1984}.
                               ^
Warning 2 in ref.tex line 3: Non-breaking space (`~') should have been used.
As shown in Fig. 1 and in Table \ref{tab:one}, see also \cite{knuth1984}.
                                                       ^

One correction is due here. It is often said that chktex scolds you for the missing ~ in Fig. 1. With the stock configuration it does not. The ~ check — Warning 2 — watches only what is listed under Linker in chktexrc: \ref, \vref, \pageref, \eqref and \cite. A bare string like Fig. 1 is not covered. To have Fig. caught you must add it to the Abbrev list yourself. Do that and re-run on the same file, and Warning 12 in ref.tex line 3: Interword spacing should perhaps be used. now points at Fig. — the complaint being that the period will otherwise get the wider end-of-sentence space.

WarningWhat it objects toWhat triggers it
2Non-breaking space (~) should have been used.a plain space before Table \ref{...} or see \cite{...}
8Wrong length of dash may have been used.a single - used where a range or dash was meant
11You should use \ldots to achieve an ellipsis.typing ... instead of an ellipsis command
12Interword spacing should perhaps be used.after the period of an abbreviation listed under Abbrev
18Use TeX quotes as an alternative to the straight double quote.using the straight double quote "
26You ought to remove spaces in front of punctuation.a space left in front of punctuation
29$\times$ may look prettier here.using x as a multiplication sign, as in 5x10^3
9'itemize' expected, found 'enumerate'.an environment closed with the wrong name
terminal
# The messages exactly as chktex prints them (one run, one bad file):
Warning 18 in bad.tex line 4: Use either `` or '' as an alternative to `"'.
Warning 11 in bad.tex line 4: You should use \ldots to achieve an ellipsis.
Warning 26 in bad.tex line 4: You ought to remove spaces in front of punctuation.
Warning 29 in bad.tex line 5: $\times$ may look prettier here.
Warning  8 in bad.tex line 7: Wrong length of dash may have been used.
Warning  9 in mm.tex  line 5: `itemize' expected, found `enumerate'.

lacheck is far more taciturn, and its role is correspondingly clear. Where chktex uses regular expressions to police habits of writing, lacheck checks the document's structural consistency. Hand it a file that closes \begin{itemize} with \end{enumerate} and it reports both ends as a pair: "mm.tex", line 5: <- unmatched "\end{enumerate}" and "mm.tex", line 3: -> unmatched "\begin{itemize}". chktex catches the same mistake as Warning 9, but points only at the closing end. In a long document, when the question is where the nesting first went wrong, lacheck gets you there faster. The right answer is to run both.

terminal
$ lacheck mm.tex
"mm.tex", line 5: <- unmatched "\end{enumerate}"
"mm.tex", line 3: -> unmatched "\begin{itemize}"

# chktex exits with the number of warnings, so CI can gate on it
$ chktex -q ref.tex >/dev/null; echo $?
2
# mute one check by number and it passes
$ chktex -q -n2 ref.tex >/dev/null; echo $?
0
# teach it your abbreviations via a local rc file
$ printf 'Abbrev { Fig. Eq. Sec. }\n' > my.chktexrc
$ chktex -q -l my.chktexrc ref.tex

That chktex exits with the number of warnings itself is what makes it useful in CI. In the run above, chktex -q ref.tex exited 2 — two warnings — and muting check number 2 with -n2 brought it to 0. So a policy of “we tolerate exactly this check” can be written down as repository configuration. Per-project settings go in a file loaded with -l my.chktexrc, or you can suppress locally with in-source directives such as % chktex-file 26.

Scolding obsolete commands and unused labels: nag and refcheck

nag flags constructions that still work but are long out of date, and it does so at compile time. Put \RequirePackage[l2tabu,orthodox]{nag} before \documentclass, compile, and the log fills with complaints: Package nag Warning: Command \bf is an old LaTeX 2.09 command. followed by Use \bfseries or \textbf instead on input line 5., then $$...$$ is obsolete. Use \[...\] et al. instead, Command \centerline is TeX. Use \centering or center environment instead, Package epsf is obsolete. Use the graphicx package instead., and finally Package nag Warning: 5 complaints in total. It pays for itself the first time you inherit a manuscript built on a decades-old template.

One more worth a single run before submission is refcheck (v1.9.1 in TeX Live 2024). Add \usepackage{refcheck}, compile twice, and it lists the labels nobody refers to: in an actual run it produced Package refcheck Warning: Unused label 'sec:unused' on input line 5. and Package refcheck Warning: Unused label 'eq:never' on input line 7. An equation that carries a number but is never cited is usually an equation that should not be numbered — and it is the first thing you can cut when an editor asks you to shorten the paper.

latex
\RequirePackage[l2tabu,orthodox]{nag}   % MUST come before \documentclass
\documentclass{article}
\usepackage{refcheck}                   % lists labels nobody refers to
% Then: pdflatex paper.tex && grep -E "nag Warning|refcheck Warning" paper.log

Running the review cycle end to end

Which tool to reach for is decided by who is going to look at what. To-dos that only you and your co-authors need are todonotes; edits that must carry an author's name are changes; showing a reviewer what moved since the previous version is latexdiff; and the fault-finding a machine can do is chktex, lacheck and nag. The four do not compete. Running them in this order avoids covering the same manuscript twice.

  • While writing, leave to-dos with todonotes\todo{...}, \missingfigure{...} — and count what is left with \listoftodos.
  • Before circulating, run chktex, lacheck and nag so the machine-findable faults are gone. Do not spend human attention on those.
  • When sending a draft out, build it with lineno and \linenumbers enabled. Add mathlines if the paper is maths-heavy.
  • Take the markup back through changes\added, \replaced, \deleted — and use \listofchanges so nothing goes unprocessed.
  • With every draft you hand over, ship a latexdiff --flatten old.tex new.tex > diff.tex build alongside it. The reader only has to open the diff.
  • Just before submission, clear unused labels with refcheck, then rebuild with todonotes set to disable and changes set to final.