4

I need to define a macro whose argument is the next word (the first character after the word should be a blank space, the end of the line, or a punctuation mark from . , : ; ! ?.

For example, let's assume that I want to have a macro \Red which colors the next word in red, then resumes the original coloring of the text.

In the following document sample, the \Red macro only colors the first letter of the word, as expected. How to modify the definition to accept the entire word as argument?

\documentclass{article}
\usepackage{color}
\def\Red#1{\begingroup\color{red} #1\endgroup}
\begin{document}
\Red Red word.
\end{document}
  • Is using \Red{Red} an option? – Peter Grill Jul 23 '18 at 9:26
  • 3
    it is possible but fragile and goes against all latex syntax guiedlines, also at the start of the paragraph it is much better to use \textcolor or you will get weird spacing effects, why not use \textcolor{red}{word} – David Carlisle Jul 23 '18 at 9:26
  • I still would prefer \Red word instead of \textcolor{red}{word} or \Red{word}. – digital-Ink Jul 23 '18 at 10:06
  • 3
    you need to read token by token checking for catcode 11 characters, but that doesn't allow accented letters or hyphenated words, allowing those as well would be a massive amount of work for something that should never be done in latex anyway. One of the main aims of latex is to give a consistent syntax to document markup based on a tex implementation. It goes to some effort to for example replace \hskip 3cm by \hspace{3cm} to enforce this {} syntax, – David Carlisle Jul 23 '18 at 10:12
  • You mention "end of line" as a delimiter. What did you have in mind? End of the line in the editor? End of the line in the TeX output? End of the paragraph? – Steven B. Segletes Jul 23 '18 at 18:44
3

Here I use listofitems to parse up to the next space and act accordingly. EDITED so that the macro will no longer fail if an explicit \par (or even \end{document}) immediately occurs following the word acted upon by \Red.

\documentclass{article}
\usepackage{xcolor,listofitems}
\long\def\Red#1 {%
  \setsepchar{.||,||!||:||;||\par}% <- SEARCH LIST OF PUNCTUATION
  \readlist\nextword{#1}%
  \foreachitem\x\in\nextword[]{%
    \ifnum\xcnt=1\relax\textcolor{red}{\x}\else\x\fi%
    \nextwordsep[\xcnt]%
  } %
}
\begin{document}
\Red test of this

test of \Red this

here \Red word. and \Red other; words \Red here.with.no.spaces.

this will no longer break \Red this\par

try again at the very \Red end\end{document}

enter image description here

And now for the fragility test:

  1. In \caption, \Red must be protected.

  2. If last [dangling] word of \caption is to be \Red, then an artificial space must be appended along with an \unskip, to allow parsing

  3. Inside tabular, if \Red occurs immediately before a & or \\, a space must be inserted before the separator.

The MWE:

\documentclass{article}
\usepackage{xcolor,listofitems}
\long\def\Red#1 {%
  \setsepchar{.||,||!||:||;||\par}% <- SEARCH LIST OF PUNCTUATION
  \readlist\nextword{#1}%
  \foreachitem\x\in\nextword[]{%
    \ifnum\xcnt=1\relax\textcolor{red}{\x}\else\x\fi%
    \nextwordsep[\xcnt]%
  } %
}
\begin{document}
Here is a table:

\begin{table}[ht]
\centering
\caption{This \protect\Red is a \protect\Red test \unskip}% <-EOL KLUDGE
\begin{tabular}{|c|c|}
\hline
\Red Red &\Red red \\% MUST have space before separators and \\
\hline
\end{tabular}
\end{table}

Done.
\end{document}

enter image description here

3
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand \colornextword { m }
 {
  \tl_clear:N \l_tmpa_tl
  \digitalink_weird_color:Nnw \l_tmpa_tl { #1 }
 }
\tl_const:Nx \c_digitalink_punct_tl { . , \token_to_str:N : ; }
\cs_new_protected:Npn \digitalink_weird_color:Nnw #1 #2
 {
  \peek_N_type:TF
   {
    \digitalink_weird_color_grab:NnN #1 {#2}
   }
   {
    \textcolor{#2}{ \tl_use:N #1 }
   }
 }
\cs_new_protected:Npn \digitalink_weird_color_grab:NnN #1 #2 #3
 {
  \tl_if_in:NnTF \c_digitalink_punct_tl { #3 }
   { \textcolor{#2}{ \tl_use:N #1 } #3 }
   {
    \tl_put_right:Nn #1 { #3 }
    \digitalink_weird_color:Nnw #1 { #2 }
   }
 }

\def\Red{\colornextword{red}}

\ExplSyntaxOff
  • 1
    \def seems quite out of place. ;-) There's a problem with the colon, though. Define \tl_const:Nx \c_digitalink_punct_tl { . , \token_to_str:N : ; } and then use \tl_if_in:VnTF \c_digitalink_punct_tl { #3 } ... – egreg Jul 23 '18 at 13:12
  • Yes, but I chose that to mix with OP code, of course other options are better, for example \NewDocumentCommand or \newcommand, hehe And about the second point yes, totally forgot about that and didn't check for each case (actually I just compiled once to see if I had syntax errors :P). – Manuel Jul 23 '18 at 13:44
  • How should I use/include your code in a tex file? – digital-Ink Jul 23 '18 at 14:13
  • Just copy the code in the preamble. It just loads a package and makes the definitions (see the last one is the one in your code \def\Red{\colornextword{red}}) – Manuel Jul 23 '18 at 15:05
  • 1
    @digital-Ink Manuel forgot the \usepackage{expl3} that you need for this code. – David Carlisle Jul 23 '18 at 18:22

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.