有没有办法让宏隐藏其输出但仍然使用计数器等执行逻辑?
我被困在下面的宏的定义上\dontoutput
。
% \documentclass, \usepackage, ...
\newcount\innercount
\def\dontoutput#1{#1} % ???
\long\def\inner#1{\advance\innercount 1\relax}
\long\def\outer#1{
\innercount 0\relax
\dontoutput{#1} % call it, increment counters in \inner, but don't output anything!
Inner called \the\innercount times.
\def\inner##1{##1} % we want to output it too now.
#1 % call again
}
\begin{document}
\outer{
a
\inner{b}
\inner{c}
\inner{d}
e
}
\end{document}
% Outputs: a e Inner called 3 times. abcde
% I'd like: Inner called 3 times. abcde
答案1
\newcounter{inner}
\def\inner#1{#1}
\def\outer#1{%
{\sbox0{\setcounter{inner}{0}\def\inner##1{\stepcounter{inner}}#1}}%
Inner called \theinner\ times. #1}
LaTeX 计数器上的命令是全局起作用的;因此,我们在一个框中排版了 的参数,\outer
在该框中我们将计数器设置为零,并定义\inner
来步进计数器。 的默认定义\inner
(在框外恢复)是排版其参数。
根据 Martin 的建议,我还将箱子分配放在一个组中,以提高安全性。该命令\sbox
构建一个箱子并将其保存到存储箱中,但不会在文档中排版任何内容。但是,所有命令都会执行,特别是我们可以重新定义\inner
为具有不同的含义,因为当我们输入箱子构造时,会打开另一个组。操作周围的组\sbox
确保存储箱将在组的末尾被遗忘。
通常人们会写
\newsavebox{\mybox}
在序言中,然后\sbox{\mybox}{...}
为了在\usebox{\mybox}
其他地方;但是,\mybox
仅指某个内部数字,而数字 0、2、4、6 和 8 则保留用于“刮擦盒”,人们可以自由地将它们用于诸如当前的目的。
答案2
您可以将内容存储到未使用的盒子中,正如 egreg 已经展示的那样。
您还可以使用\nullfont
来关闭任何文本输出。但是,据我所知,段落仍然插入,因此\let\par\relax
也很有用。最后,您想禁用任何命令再次切换到真实字体,因此也\let\selectfont\relax
应该添加。要么将它们放在一个组中,要么保存并恢复原始定义(先保存\let\origfoo\foo
,然后保存)。在后一种情况下,您应该在恢复后\let\foo\origfoo
使用。\normalfont
\selectfont
通常我猜使用盒子是更好的选择。