2011-11-25 First three words macro (en)

Today, I read a question on TeX.SE involving the following problem: how to take some text, cut it to three words if it has more of them (and add an ellipsis), or typeset it as-is if it’s three words or less?

It seems to me that writing a macro for an arbitrary number of words might be rather difficult – especially if the number of words exceeded 7 (see remarks in The TeXbook, Appendix D!), but for a fixed number of words it is relatively easy:

\documentclass{article}

\usepackage{etoolbox}% I need \ifblank to put \dots
                     % if something nonblank gets deleted

\makeatletter
\def\@threefirstwords #1 #2 #3 #4\\#5{%
  #1 #2 #3\ifblank{#4}{}{#5}%
}
\edef\threefirstwords#1#2{\noexpand\@threefirstwords
  #1\space\space\space\noexpand\\{#2}}
\makeatother

\begin{document}

\threefirstwords{This is a test}{\dots}\par
\threefirstwords{This is a}{\dots}\par
\threefirstwords{This is}{\dots}\par
\threefirstwords{This}{\dots}\par

\end{document}

Hopefully, the idea behind this is more or less self-explanatory, but there are a few twists here.

Firstly, I used the plain TeX’s delimited arguments: the macro \@threefirstwords takes 5 arguments: the first one is everything from the macro itself to the first space, the second is everything between the first and second space, and so on.

Secondly, in \threefirstwords, I need to put 3 explicit spaces in a row, so that everything goes fine if the first argument to this macro does not contain any space. But putting three spaces in a row in the source file won’t work, since TeX treats them as one; also, putting them in three consecutive lines, ended by % won’t work either, because TeX discards spaces at the beginning of the line. Nor would \obeyspaces work for us, since it changes the catcode of the space, and the parameter sequence takes catcodes into consideration. So I used another way: a macro \space, defined by \def\space{ } in LaTeX kernel. (I did not read all the source2e, of course, but I used the great macros2e by Martin Scharrer). Using \edef (and taking care so that only the \spaces get expanded) does the trick.

Now the author of the question wanted this to shorten long titles in bibliographies, but I can imagine other applications, too; after a slight modification (which I left as an exercise for the reader;)), this macro could be used to set the first three words of a chapter in small caps, for instance.

(Notice also that you can use either ~ or, say, a space in braces to “hide” a space from this command; another exercise could be: how to prepare the argument to \threefirstwords so that it typesets only two words? Of course, \threefirstwords{One {} two three} won’t work!)

CategoryEnglish, CategoryBlog, CategoryTeX, KategoriaTeX