定义宏,其参数是整个下一个单词(未被花括号括起来)

定义宏,其参数是整个下一个单词(未被花括号括起来)

我需要定义一个宏,其参数是下一个单词(单词后的第一个字符应该是一个空格、行尾或标点符号. , : ; ! ?

例如,假设我想要一个宏\Red,将下一个单词变为红色,然后恢复文本的原始颜色。

在以下文档示例中,\Red 宏仅对单词的首字母进行着色,正如预期的那样。如何修改定义以接受整个单词作为参数?

\documentclass{article}
\usepackage{color}
\def\Red#1{\begingroup\color{red} #1\endgroup}
\begin{document}
\Red Red word.
\end{document}

答案1

在这里我使用listofitems解析到下一个空格并采取相应措施。已编辑,以便宏将不再如果显式\par(甚至\end{document}立即地发生在被作用于的词之后\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}

在此处输入图片描述

现在进行脆弱性测试:

  1. \caption\Red必须受到保护。

  2. 如果的最后一个[悬垂]词\caption\Red,则必须在后面附加一个人工空格以及\unskip, 以便进行解析

  3. 在 内部tabular,如果\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}
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}

在此处输入图片描述

答案2

\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

答案3

您可以使用它\peek_regex_replace_once:nn,它基本上变成一行代码。

\documentclass{article}
\usepackage{xcolor}

\colorlet{nextred}{red!80!green}

\ExplSyntaxOn

\NewDocumentCommand{\Red}{}
 {
  \peek_regex_replace_once:nn { [^\s \. \, \; \: \! \? \c{par}]* } { \c{digitalink_red:n} \{\0\} }
 }

\cs_new_protected:Nn \digitalink_red:n { \textcolor{nextred}{#1} }

\ExplSyntaxOff

\begin{document}

\Red something and something else

\Red Period. Something else.

\Red Comma, something else.

\Red Semicolon; something else.

\Red Hey! Something else.

\Red Pardon? Something else.

\Red End%

\end{document}

在此处输入图片描述

相关内容