我正在尝试定义一个宏,它将接受一个字符串并绘制其结尾,例如:
\def\paintString#1{%
\saveexploremode%
\exploregroups%
\textcolor{white}{\StrGobbleRight{#1}{5}}%
\StrGobbleRight{#1}{2}[\tmp]%
\textcolor{yellow}{\StrRight{\tmp}{3}}%
\textcolor{white}{\StrRight{#1}{2}}%
\restoreexploremode%
}
这与普通文本的预期效果相同(所有内容均为白色,右侧第 4-5 个字符除外,这些字符为黄色)。但是,如果参数包含公式或以下内容,则会出现问题\cite{}
:
\paintString{Blah \cite{reference}}
\paintString{Blah $\Sigma$}
对此,LaTeX 报告
Argument of \XC@col@rlet has an extra }.
我认为发生这种情况的原因是因为我破坏了公式(或\cite
)并将其放入\textcolor{...}{
内部和相应的}
外部。
有没有办法强制扩展,使得这些特殊的东西被xstring
宏视为单个字符?
我需要明确地添加某种扩展(因此\exploregroups
),因为没有它,字符串就无法正确解析。此外,这是 Beamer 主题,调用它的地方之一是框架标题,如果未扩展,则报告\StrLength
1,因此上述绘制根本不会发生。
编辑:使用起来更安全一些:
\def\paintString#1{%
\saveexploremode%
\exploregroups%
{\color{white}\StrGobbleRight{#1}{5}%
\StrGobbleRight{#1}{2}[\tmp]%
\color{yellow}\StrRight{\tmp}{3}%
\StrRight{#1}{2}}%
\restoreexploremode%
}
但是,它仍然失败\cite
。
答案1
这是一个令人满意的解决方案:
\def\paintString#1{%
\IfSubStr{\expandafter\detokenize\expandafter{#1}}{\detokenize{\paintString}}{%
#1%
}{%
\saveexploremode%
\exploregroups%
{\color{white}\StrGobbleRight{#1}{5}%
\StrGobbleRight{#1}{2}[\tmp]%
\color{yellow}\StrRight{\tmp}{3}%
\color{white}\StrRight{#1}{2}}%
\restoreexploremode%
}%
}
这正如我在之前对这个问题的评论中所建议的那样:
处理此问题的另一种方法可能是以某种方式实现
\paintString{some text}
已处理但\paintString{some \paintString{already painted} text}
按原样返回,因此“一些”和“文本”不是特别绘制的,但“已绘制”是。这将为用户提供一种简单的方法来控制有问题的文本块。
因此,我可以自由地放置\frametitle{Some text}
(\frametitle
重新定义为\painString
用于标题)并且像以前一样正确地绘制它。
但是,\frametitle{Author \cite{reference}}
仍然会失败,因此我用 来解决它\frametitle{\paintString{Author} \cite{reference}}
,从而绘制“作者”并保持\cite{reference}
原样(即,仅将其附加到绘制的作者姓名之后)。
为了更加安全,我添加了一些额外的代码,完全抑制了绘画,甚至没有检查参数的值:
\def\paintString#1{%
\ifnum\suppressPainting=0%
\IfSubStr{\expandafter\detokenize\expandafter{#1}}{\detokenize{\paintString}}{%
#1%
}{%
\saveexploremode%
\exploregroups%
{\color{white}\StrGobbleRight{#1}{5}%
\StrGobbleRight{#1}{2}[\tmp]%
\color{yellow}\StrRight{\tmp}{3}%
\color{white}\StrRight{#1}{2}}%
\restoreexploremode%
}%
\else%
{\color{white}#1}%
\fi%
}
因此,\def\suppressPainting{1}
无论参数值如何,将某个位置放在框架之前都会抑制绘画。 可能有一点 TeX-ier 解决方案,但我不知道。
当然,自动解决方案(不需要用户干预,只需手动调用\paintString
)会更好,但我不认为这是不可能的(正如@egreg 在上面的评论中所建议的那样),所以这可能是处理问题的最佳方法。