![定义宏,其参数是整个下一个单词(未被花括号括起来)](https://linux22.com/image/379811/%E5%AE%9A%E4%B9%89%E5%AE%8F%EF%BC%8C%E5%85%B6%E5%8F%82%E6%95%B0%E6%98%AF%E6%95%B4%E4%B8%AA%E4%B8%8B%E4%B8%80%E4%B8%AA%E5%8D%95%E8%AF%8D%EF%BC%88%E6%9C%AA%E8%A2%AB%E8%8A%B1%E6%8B%AC%E5%8F%B7%E6%8B%AC%E8%B5%B7%E6%9D%A5%EF%BC%89.png)
我需要定义一个宏,其参数是下一个单词(单词后的第一个字符应该是一个空格、行尾或标点符号. , : ; ! ?
。
例如,假设我想要一个宏\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}
现在进行脆弱性测试:
在
\caption
,\Red
必须受到保护。如果的最后一个[悬垂]词
\caption
是\Red
,则必须在后面附加一个人工空格以及\unskip
, 以便进行解析在 内部
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}