我正在尝试创建一个命令\mymodule_add_text_style:nn
,用于向现有文本宏添加额外的样式。从以下 MWE 中可以看到,它可以成功将样式添加\textsc
到\mytext
。但是,如果要向同一宏添加另一种样式,该命令不起作用。为什么会失败以及如何修复?
\documentclass{article}
\usepackage{xcolor}
\def\mytext{My text}
\ExplSyntaxOn
\cs_new:Nn \mymodule_add_text_style:nn
{
\tl_gset:cx { #1 } { \exp_not:n { #2 } { \use:c { #1 } } }
}
\mymodule_add_text_style:nn
{ mytext }
{ \textsc }
% \mymodule_add_text_style:nn
% { mytext }
% { \textcolor {red} }
\ExplSyntaxOff
\begin{document}
\mytext{} and more text.
\end{document}
答案1
在这种情况下,你试图x
扩展可能无法生存的东西\textsc
(但\textcolor
如果你想再次添加一些东西)。为了实现你的目标,你需要更好地控制扩展,做确切地\mytext
重新定义它时的一次扩展。
但是你的电话应该是这样的
\mymodule_add_text_style:cn
{ mytext }
{ \textsc }
因为您使用的mytext
是 csname。此处的函数是 的变体\mymodule_add_text_style:Nn
,因此您也可以调用
\mymodule_add_text_style:Nn \mytext { \textsc }
无需使用\exp_not:n
或其变体:只需使用变体。不进行x
-expansion 更安全。
\documentclass{article}
\usepackage{xcolor}
\newcommand\mytext{My text}
\ExplSyntaxOn
\cs_new_protected:Nn \mymodule_add_text_style:Nn
{
\__mymodule_add_text_style:Non #1 { #1 } { #2 }
}
\cs_generate_variant:Nn \mymodule_add_text_style:Nn { c }
\cs_new_protected:Nn \__mymodule_add_text_style:Nnn
{
\tl_gset:Nn #1 { #3 { #2 } }
}
\cs_generate_variant:Nn \__mymodule_add_text_style:Nnn { No }
\mymodule_add_text_style:cn
{ mytext }
{ \textsc }
\mymodule_add_text_style:cn
{ mytext }
{ \textcolor {red} }
\ExplSyntaxOff
\begin{document}
\show\mytext
\mytext{} and more text.
\end{document}
控制台将显示
> \mytext=macro:
->\textcolor {red}{\textsc {My text}}.
如预期的。
你看出来其中的窍门了吗?你传递了#1
两次,但传递给辅助函数的变体,其中第二个参数被扩展了一次。
还请注意任何执行分配的函数应该是protected
。
略有不同的提议
由于您使用它\mytext
作为标记列表变量(这有点延伸,但也不是那么多),使用V
类型会很好:
\cs_new_protected:Nn \mymodule_add_text_style:Nn
{
\__mymodule_add_text_style:NVn #1 #1 { #2 }
}
\cs_generate_variant:Nn \mymodule_add_text_style:Nn { c }
\cs_new_protected:Nn \__mymodule_add_text_style:Nnn
{
\tl_gset:Nn #1 { #3 { #2 } }
}
\cs_generate_variant:Nn \__mymodule_add_text_style:Nnn { NV }
答案2
您可以使用 TeX 基元创建宏,\addstyle \macro {style}
无需任何 expl3。它执行相同的工作:
\def\addstyle#1{\expandafter\addstyleA\expandafter{#1}#1}
\def\addstyleA#1#2#3{\def#2{#3{#1}}}
\def\mytext{My text}
\addstyle \mytext {\textsc}
\addstyle \mytext {\textcolor{red}}
\meaning\mytext % macro:->\textcolor {red}{\textsc {My text}}
\bye
答案3
首次使用后
\textsc {My text}
\textsc
使用 LaTeX 机制保护\protect
,但不能在\edef
或其他扩展上下文(例如x
参数)中使用。
\documentclass{article}
\usepackage{xcolor}
\def\mytext{My text}
\ExplSyntaxOn
\cs_new:Nn \mymodule_add_text_style:Nn
{
\tl_set:Nx #1 { \exp_not:n { #2}{\exp_not:o { #1 }}}
}
\cs_generate_variant:Nn\mymodule_add_text_style:Nn {c}
\mymodule_add_text_style:cn
{ mytext }
{ \textsc }
\show\mytext
\mymodule_add_text_style:cn
{ mytext }
{ \textcolor {red} }
\show\mytext
\ExplSyntaxOff
\begin{document}
\mytext{} and more text.
\end{document}
两人\show
表演
> \mytext=macro:
->\textsc {My text}.
l.20 \show\mytext
?
> \mytext=macro:
->\textcolor {red}{\textsc {My text}}.
l.26 \show\mytext
?