我经常发现自己需要一个\noexpand
适用于 TeX 组而不是宏的实用程序。例如,在我当前的项目中,我有子程序:
% adds a box to the layer
\newcommand\addbox[1] {
\edef\drawboxcode{
{\noexpand\draw (...) node[
draw,
fill,
...] {#1};
}
}
\expandafter\addcodetolayer\drawboxcode
}
% pushes object code onto layer
\newcommand\addcodetolayer[1]
{\seq_gput_right:Nn\sq__layercmds{#1}}
% renders layer
\newcommand\renderlayer
{\seq_use:Nnnn \sq__layercmds{}{}{}}
我需要这些,因为我用来绘制 TikZ 对象的代码被分为子程序,这些子程序以交错的方式将内容放置在多个 PGF 层上(例如,一个层上的框,另一个层上的阴影),不幸的是,每次\begin{pgfonlayer}{foolayer}
使用环境时,它都会擦除foolayer
先前写入的层中的任何内容。
我的解决办法是按照以下方式使用上述子程序:
\begin{tikzpicture}
\addbox {Foo Box}
\addbox {Bar Box}
...
\begin{pgfonlayer}{boxlayer}
\renderlayer
\end{pgfonlayer}
\end{tikzpicture}
这种方法效果很好,但有一个突出的问题:如果 的参数\addbox
包含诸如 之类的宏\ref
,则必须手动\noexpand
修改这些宏以避免出现错误,即
\addbox {Foo Box (section~\ref{sec:foo})} % gives horrible cryptic LaTeX errors
\addbox {Foo Box (section~\noexpand\ref{sec:foo})} % works like a charm
理想情况下,我希望避免这种情况,但我不知道有什么好办法。最明显的解决办法是,如果\noexpand
可以对 TeX 组而不是宏起作用,但事实并非如此。使用
\edef\drawboxcode{
{\noexpand\draw (...) node[
draw,
fill,
...] {\noexpand{#1}};
}
}
例如,什么都不做。我也不能使用
\def\drawboxcontent{#1}
\edef\drawboxcode{
{\noexpand\draw (...) node[
draw,
fill,
...] {\noexpand\drawboxcontent};
}
}
因为当\drawboxcontent
最终展开时\renderlayer
,宏将只包含最后添加的框的内容。
这只是一个例子,说明防止\edef
扩展代码块(即 TeX 组)而不是宏的实用程序非常有用。
一个替代方案是允许如下代码的实用程序
\passbyvaluedef\drawboxcontent{#1}
\edef\drawboxcode{
{\noexpand\draw (...) node[
draw,
fill,
...] {\drawboxcontent};
}
}
其中\passbyvaluedef
将定义一个宏\drawboxcontent
,当展开时,它将展开为一些唯一的命令序列\drawboxcontentaaaa
无需进一步扩大,并将\drawboxcontentaaaa
包含 中的所有内容#1
。下一次\passbyvaluedef\drawboxcontent
调用 时,\drawboxcontent
将扩展为\drawboxcontentaaab
,依此类推,在每种情况下都返回唯一的 CS 名称。这不如基于组的 优雅\noexpand
,但它也能完成工作。
是否有任何 TeX/LaTeX 宏/包可以执行上述任何一项操作(有效地\noexpand
-ing 组,或建议的替代方法)?如果没有,是否有其他方法可以解决必须手动将 s 包含在我的框内容中的问题\noexpand
,还是我只能使用它们?
答案1
您可以使用\unexpanded{<balanced text>}
。这将避免在 中的扩展<balanced text>
。