# Dynamically count and return number of words in a section

I am writing a proposal for which it is required to give the number of words of the main section in the proposal itself. I found this answer on how I can get a word count on a LaTeX document:

Is there any way to do a correct word count of a LaTeX document?

But this is only for entire documents. I was wondering if it is possible to get a word count in a LaTeX document of a section/part of text and actually return this in the text as well.

I am open to suggestions with Sweave. One thing I could think of is to write the entire section in a Sweave block in an R character string. Then simply get the word count from that and return the string. This would however include all LaTeX codes used and not only intended words. Another solution I thought of was to extend this R code to wrap the string in an empty document, compile that and use tools available to get a wordcount from that, then return it. This seems like it could work but I am hoping there is a simpler solution.

You can use texcount to count the words. It automatically produces subcounts for the sections.

Here's a new macro that calls texcount, extracts the subcount for the current section, and then inserts the word count into the document. It requires write18 to be enabled, and texcount must be in your path (or you have to include the full path to the executable in the macro).

\documentclass{article}
\newcommand\wordcount{
\immediate\write18{texcount -sub=section \jobname.tex  | grep "Section" | sed -e 's/+.*//' | sed -n \thesection p > 'count.txt'}
(\input{count.txt}words)}

\begin{document}
\section{Introduction}
In publishing and graphic design, lorem ipsum is placeholder text (filler text) commonly used to demonstrate the graphics elements of a document or visual presentation, such as font, typography, and layout. The lorem ipsum text is typically a section of a Latin text by Cicero with words altered, added and removed that make it nonsensical in meaning and not proper Latin.

\wordcount
\section{Main Stuff}
Even though "lorem ipsum" may arouse curiosity because of its resemblance to classical Latin, it is not intended to have meaning. Where text is comprehensible in a document, people tend to focus on the textual content rather than upon overall presentation, so publishers use lorem ipsum when displaying a typeface or design elements and page layout in order to direct the focus to the publication style and not the meaning of the text. In spite of its basis in Latin, use of lorem ipsum is often referred to as greeking, from the phrase "it's all Greek to me," which indicates that this is not meant to be readable text.

\wordcount
\section{Conclusion}
Today's popular version of lorem ipsum was first created for Aldus Corporation's first desktop publishing program Aldus PageMaker in the mid-1980s for the Apple Macintosh. Art director Laura Perry adapted older forms of the lorem text from typography samples — it was, for example, widely used in Letraset catalogs in the 1960s and 1970s (anecdotes suggest that the original use of the "Lorem ipsum" text was by Letraset, which was used for print layouts by advertising agencies as early as the 1970s.) The text was frequently used in PageMaker templates.

\wordcount
\end{document}


• I tried this but it didn't work when there was a subsection in the section. You probably need a grep '\\<section\>' or equivalent.
– user10274
Feb 15 '12 at 10:46
• Awesome, thanks! Only tried it on whole sections and that works just fine. Feb 15 '12 at 10:52
• @MarcvanDongen: If you have subsections, you should add sub=section to the texcount command.
– Jake
Feb 15 '12 at 11:44
• Could someone briefly describe how that line of TeX/Shell-fu works in plain english? Very interesting. Particularly curious why there's an '18' there. Feb 15 '12 at 16:46
• @ Jake, Sorry I was trying to do that in windows. May be this is applicable for Linux. Sep 28 '12 at 1:09

Here is a pure LaTeX solution to the problem, using my tokcycle package (I even offer a pure TeX solution at the end!!). You will need the new version from 2021-03-10, because I define my environment using the new \xtokcycleenvironment feature, which allows not only the definition of the token-cycle directives, but additional "set-up" and "close-out" code to be executed before and after the token-cycle.

I note that even in the more extensively answered question, Is there any way to do a correct word count of a LaTeX document?, there are no other pure-latex solutions to the problem.

This approach introduces the pseudoenvironment \countem...\endcountem which will count both words (defined as strings of cat-11 tokens bounded by anything other than a cat-11 token---thus, hyphenated-compound-words are each counted separately) as well as letters (only cat-11 tokens count as letters). Because it is an environment, you can apply it to a portion of a document, and apply it several times within a document.

In it's simplest usage, the environment will populate two counters, wordcount and lettercount with values that you can test, typeset, or whatever. But it offers several advanced features.

1. If you set the counter wordlimit to a positive number, it will change the color of the counted text to \limitcolor (default red) when the running word count exceeds \value{wordlimit}

2. If you set \runningcounttrue, you will get a superscripted word and letter count typeset after each word.

3. If you set \summarycounttrue, you will get the total word and letter counts typeset at the conclusion of the environment.

The environment can digest and process macros in the input stream, essentially echoing them to the output (and not counting the macro token as a letter or word). But beware! Macro arguments containing cat-11 tokens will count as letters and words. Furthermore, if \runningcountrue, the added superscripts will pollute the macro argument. The solution to these problems is to use the tokcycle escape feature, |...|, which will echo the ... tokens to the output without processing them through the token cycle directives. Example: counted input |\rule{2ex}{1ex}| more counted input.

A very nice feature (enable by the tokcycle logic) is that groups pose no problem to the features. For example, if you exceed wordlimit inside of a \textit argument, the color will change there and continue changed even as the \textit argument is exited.

If one wanted a count for the whole document, one would merely start \countem immediately after \begin{document} and then \endcountem immediately prior to \end{document}.

\documentclass{article}
\usepackage{tokcycle}[2021-03-10]
\usepackage{xcolor}
\newcounter{wordcount}
\newcounter{lettercount}
\newcounter{wordlimit}
\newif\ifinword
% USER PARAMETERS
\newif\ifrunningcount
\newif\ifsummarycount
\def\limitcolor{red}
\setcounter{wordlimit}{0}
%%
\makeatletter
% \tc@defx is like \def, but expands the replacement text once prior to assignment
\tc@defx\currentcolor{#1}}}
\makeatother
\newcommand\dumpword{%
\ifinword\stepcounter{wordcount}
\ifrunningcount\addcytoks[x]{$^{\thewordcount,\thelettercount}$}\fi
\ifnum\thewordcount=\value{wordlimit}\relax\changecolor{\limitcolor}\fi
\fi%
\inwordfalse
\def\accumword{}}
\tctestifcatnx A#1{\stepcounter{lettercount}\inwordtrue}{\dumpword}%
\xtokcycleenvironment\countem
{\dumpword\groupedcytoks{\processtoks{##1}\dumpword\expandafter}\expandafter
\changecolor\expandafter{\currentcolor}}
{\stripgroupingtrue\def\accumword{}\def\currentcolor{.}
\setcounter{wordcount}{0}\setcounter{lettercount}{0}}
{\dumpword\ifsummarycount\tcafterenv{%
\par(Wordcount=\thewordcount, Lettercount=\thelettercount)}\fi}
\begin{document}
\countem
This is a test if word counting occurs.
\endcountem
I know there were \thewordcount{} words and \thelettercount{} letters in the
prior sentence.

\bigskip\setcounter{wordlimit}{7}
\countem
This is a test if color changes after seven words.
\endcountem

\bigskip\runningcounttrue
\countem
This is a running count.

But...punctuation does not count as characters.
\endcountem

\bigskip
\countem
This \textbf{is a} running count. |\textsc{Skipping macros
\rule{1ex}{1.5ex}/other text}|

But...\textit{punctuation does} not count as characters.
\endcountem

\bigskip\runningcountfalse\summarycounttrue\setcounter{wordlimit}{125}
\countem
As any dedicated reader can clearly see, the Ideal of
practical reason is a representation of, as far as I know, the things
in themselves; as I have shown elsewhere, the phenomena should only be
used as a canon for our understanding. The paralogisms of practical
reason are what first give rise to the architectonic of practical
reason. As will easily be shown in the next section, reason would
thereby be made to contradict, in view of these considerations, the
Ideal of practical reason, yet the manifold depends on the phenomena.
Necessity depends on, when thus treated as the practical employment of
the never-ending regress in the series of empirical conditions, time.
Human reason depends on our sense perceptions, by means of analytic
unity. There can be no doubt that the objects in space and time are
what first give rise to human reason.

Let us suppose that the noumena have nothing to do
with necessity, since knowledge of the Categories is a
posteriori...
\endcountem
\end{document}


In the MWE, the first example is the basic one. The words and letters of the sentence are counted and made available in wordcount and lettercount.

In the 2nd example, wordlimit is set, and we observe the color of the text to change after 7 words.

In the 3rd example, the running count is enabled. One can observe that spaces and punctuation are not counted as letters but can serve to separate words (in the case of ...).

In the 4th example, several additional features are demonstrated: text containing a macro sequence is escaped between |...| delimiters, to avoid polluting the macro arguments. Additionally, we note the color changes inside an italicized group of text. Nonetheless, the group-ending behavior is as expected, and there is no disruption to the word/letter counts nor the limitcolor.

In the 5th and last example, because the text block is longer, we raise the wordlimit and turn off the running count, and instead employ a summary count of the \countem text block.

BONUS: PURE TeX SOLUTION!!

Here is the above answer adapted for Plain TeX. (Thanks to David for chat help with \input color)

%%%
% MAKE COLOR AVAILABLE
\input color
%%%
%%% COLOR INPUT COMPLETE, NOW LET"S CREATE A TOKEN-CYCLE
%
\input tokcycle
\newcount\wordcount
\newcount\lettercount
\newcount\wordlimit
\newif\ifinword
% USER PARAMETERS
\newif\ifrunningcount
\newif\ifsummarycount
\def\limitcolor{red}
\wordlimit=0\relax
%%
\catcode@=11
% \tc@defx is like \def, but expands the replacement text once prior to assignment
\tc@defx\countemcurrentcolor{#1}}}
\catcode@=12
\def\dumpword{%
\ifrunningcount\addcytoks[x]{$^{\the\wordcount,\the\lettercount}$}\fi
\ifnum\wordcount=\wordlimit\relax\changecolor{\limitcolor}\fi
\fi%
\inwordfalse
\def\accumword{}}
\xtokcycleenvironment\countem
{\dumpword\groupedcytoks{\processtoks{##1}\dumpword\expandafter}\expandafter
\changecolor\expandafter{\countemcurrentcolor}}
{\stripgroupingtrue\def\accumword{}\def\countemcurrentcolor{.}
\global\wordcount=0\relax\global\lettercount 0\relax}
{\dumpword\ifsummarycount\tcafterenv{%
\par(Wordcount=\the\wordcount, Lettercount=\the\lettercount)}\fi}

% SETUP COMPLETE.  NOW FOR THE DOCUMENT

\countem
This is a test if word counting occurs.
\endcountem
I know there were \the\wordcount{} words and \the\lettercount{} letters in the
prior sentence.

\bigskip\wordlimit=7\relax
\countem
This is a test if color changes after seven words.
\endcountem

\bigskip\runningcounttrue
\countem
This is a running count.

But...punctuation does not count as characters.
\endcountem

\bigskip
\countem
This {\bf is a} running count. |{Skipping macros
rule{1ex}{1.5ex}/other text}|

But...{\it punctuation does} not count as characters.
\endcountem

\bigskip\runningcountfalse\summarycounttrue\wordlimit=125\relax
\countem
As any dedicated reader can clearly see, the Ideal of
practical reason is a representation of, as far as I know, the things
in themselves; as I have shown elsewhere, the phenomena should only be
used as a canon for our understanding. The paralogisms of practical
reason are what first give rise to the architectonic of practical
reason. As will easily be shown in the next section, reason would
thereby be made to contradict, in view of these considerations, the
Ideal of practical reason, yet the manifold depends on the phenomena.
Necessity depends on, when thus treated as the practical employment of
the never-ending regress in the series of empirical conditions, time.
Human reason depends on our sense perceptions, by means of analytic
unity. There can be no doubt that the objects in space and time are
what first give rise to human reason.

Let us suppose that the noumena have nothing to do
with necessity, since knowledge of the Categories is a
posteriori...
\endcountem
\bye


You asked for a LaTeX solution, but for completion I'll provide a ConTeXt solution as well, it might be helpful for someone. It does not rely on external programs.

\startluacode
userdata = userdata or { }

function userdata.wordcount(listname)
if lfs.isfile(filename) then
local w = dofile(filename)
if w then
if type(w.categories[listname]) == "table" then
context(w.categories[listname].total)
else
context(w.total)
end
context.par()
end
end
end
\stopluacode

\def\wordcount{%
\dosingleempty\dowordcount}

\def\dowordcount[#1]{%
\ctxlua{userdata.wordcount("#1")}}

\starttext

% Set up the word count
\ctxlua{languages.words.threshold=2}
\setupspellchecking [state=start, method=2]

\setupspellchecking [list=foo]
\startsection [title=Foo]
Foo Bar
\stopsection

\setupspellchecking [list=lorem]
\startsection [title=Lorem]
Lorem ipsum dolor sit
\stopsection

\setupspellchecking [list=stop]

\startsubject [title=Statistics]
Words in Foo:   \wordcount [foo]
Words in Lorem: \wordcount [lorem]
\stopsubject

\stoptext


The result:

The lua function reads in the external file \jobname.words that is created by the \setupspellchecking command. It returns a a lua table with some statistical information and extracts the relevant data. \wordcount is just a nice wrapper to keep the interface “contextish”.

By default only words with at least four characters are being counted. In the example I set the threshold to two characters.

Notes: In the example the text in the section heading is counted as well. Unlike the usual ConTeXt behaviour, this word count implementation needs two context runs.

The code is a modified version of the one found in the ConTeXt distribution (s-lan-03).

If you are on windows, you can visit this site and install winedt. It has a built in word count feature (Document->word count). To count words in a para or section, you have to select that section and perform the count.

• Does it expand macros and count the resulting words?
– user10274
Feb 15 '12 at 10:25
• Fortunately I am on Linux :) But I have a Windows machine available so I'll look into it. Thanks. Feb 15 '12 at 10:38
• @Marc, I have not tested the macro thing but I think it is doing good at this.
– user11232
Feb 15 '12 at 11:02

If you are using Emacs with Auctex, you can select the text of the current region and run Latex on that (usually via the C-c C-r keybinding, which maps to TeX-command-region). This will create a file _region_.tex that can be compiled or texcount-ed whose body contains just the part of the Latex document that was highlighted; likewise tools such as tex4ht or PDF tools that can word count the output can be used to generate a wide variety of estimates of the word count.

Several other Latex editors support similar "region compilation", e.g., Kile. See LaTeX Editors/IDEs

Counting words from chapters and in windows enviroment (without e.g. Cygwin).

\newcommand\wordcount{
%\immediate\write18{texcount -sub=chapter \jobname.tex  | grep "Chapter" | sed -e 's/+.*//' | sed -n \thechapter p > count.txt}
\immediate\write18{powershell -command " & { texcount -sub=chapter \jobname.tex  | findstr "Chapter" | ForEach-Object {\$_.substring(0,3)} | Select -Index (\thechapter - 1) }" > count.txt}
(\input{count.txt}words)}

• I get the error Undefined control sequence. \wordcount. May 3 '20 at 18:18