1

What is the best way to get git-latexdiff to work nicely with texcount to view changed and deleted word counts between two commits?

1

It took me a long time to get this working, so just in case someone else comes looking for this in the future!

The first thing I did was use this answer so that texcount will use the formatting of latexdiff to be able to count added and deleted words.

There are several problems using this with git-latexdiff, however. The first is that gitlatex-diff uses latexpand to flatten any files that are included with \input or \include into one large .tex file. By default, this also removes any comments, including those %TC: comments for texcount formatting. So you will want to pass --latexpand --keep-comments to git-latexdiff.

The second issue is that git-latexdiff will make a temporary directory to store the diff files. You can tell git-latexdiff where to put these directories using the --tmpdirprefix, however the individual directories that are created each time you run git-latexdiff are named based upon the PID of the process. Therefore they are not easy to identify in order to run texcount on the generated diff files.

So based upon this answer I decided to put the word count in the document itself on the first page. This way when git-latexdiff runs, it will call texcount automatically and put the word counts in the document. Then you can tell git-latexdiff to output that file somewhere (or just view it in the viewer) and see the word counts. This answer gives some good insight on making a template for texcount. I used this to make it output in a format that I could include in a .tex file so that it would look good in the pdf (adding new line characters, etc).

But that answer requires that output to be saved in a file and then input using the \input command. The problem is that the first time that git-latex runs, it will compile the document once, which will create the word count file, and then it will flatten the doc before sending it to latexdiff. When it flattens the document, it will put the contents of the word count file directly in the flattened document. This will have the total number of words correct, but it will not show any added or deleted words since the diff file has not been made by latexdiff yet. And it will not input the contents of the word count file after this, because latexpand has already flattened the document. Note that if you give git-latexdiff the --no-flatten option, it will indeed leave the individual files; however, it will not send all the files to latexdiff (See this issue). It will only diff the top level file. For a large document, this is useless since all the content is likely in separate .tex files.

I could not find a way to get latexpand to ignore this input. I also tried putting the texcount command directly in the document using this answer, but latexpand still expands this and puts it in the document (I am using XeLaTeX). I could not find a way to get latexpand to ignore this command. (According to the code, it also expands \input commands that are in verbatim environments).

To solve this, I used the import package, which provides a command \import that \latexpand does not expand. This way the word count file can be generated each time the document is compiled (importantly: on the final diff document from latexdiff.)

The last thing I did was to only do this when the document is in draft mode. If the document is being edited and changed and you want to see this changes, it makes sense that it only happens in draft mode. See this answer for a list of things that draft mode changes. I added the command from this answer so that I could do stuff only in draft mode. I always want my pdf to have a TOC (since it is quite large), so I added this answer as well so that hyperref will always generate a TOC.

So in the end I added this to my preamble:

\makeatletter
\def\ifdraft{\ifdim\overfullrule>\z@
  \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi}
\makeatother

\hypersetup{final}
\ifdraft{\usepackage{import}}{}

And then at the beginning of my document I added:

%TC:newcounter add Added
%TC:newcounter del Deleted
%TC:macro \DIFadd [add]
%TC:macro \DIFdel [del]
%TC:ignore 
\immediate\write18{texcount -relaxed -sum -total -utf8 -opt=tc_template.cfg -merge \jobname.tex > 'WC.txt'}
\ifdraft{
{\LARGE \import{}{WC.txt}}
\clearpage}{}

For completeness, here is the content ot tc_template.cfg:

-template=
\Total Words: \textcolor{blue}{{sum}}\n\n
\Words in Text: {text}\n\n
\Words in Footnotes: {otherword}\n\n
\Words Added: \textcolor{green}{{add}}\n\n
\Words Deleted: \textcolor{red}{{del}}\n\n
\\rule{2.5in}{0.75pt}\n\n
\Words in Headers: {headerword}\n\n
\Num Headers: {header};  Floats: {float}\n\n
\Num Inline Math: {inline};  Display Math: {displaymath}\n\n

(I know that otherword in texcount can be things other than footnotes; but for my doc, it is nearly all footnotes. I also know that I could have put the %TC: macros in the config file. But I have lots of other %TC: comments in my document so that texcount ignores my preamble instead of parsing it, etc. So I just left them.)

The function that I call is:

git latexdiff --biber --xelatex --latexopt -shell-escape --main $1 --latexpand --keep-comments HEAD^1

I give it the name of the main .tex file. Since this solution uses \write18, remember that you will need to send the -shell-escape command to xelatex.

And that seems to work well. It puts the final word count and the added and deleted words in the final doc, which you can then peruse to see the differences in the last commit.

I might one day put this in CI in gitlab so that it generates this document automatically so that people can easily see what was changed, etc. That is for another day.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.