我正在使用纯 TeX / pdfTeX。
有没有办法构建一组宏,比如\showOn
/ \showOff
,这样
我可以嵌套它们
对于给定的一段文本,它会“查找解析树”,找到第一个
\showOn
/\showOff
父级,并且当且仅当它打开时才会显示?
例如:
Cat \showOff { dog \showOn {red \showOff {blue} green } superman} wonderwoman
会导致:
Cat [spacing for dog] red [spacing for blue] green [spacing for superman] wonderwoman
因此,我知道我可以通过使用幻影来实现没有显示部分的间距 - 但是,有没有办法以嵌套的方式打开/关闭幻影?
现在,我有:
\def\showOn#1{{#1}}
\def\showOff#2{\phantom{#2}}
\showOff {\showOn {foo}}
\bye
然而,这显然导致嵌套失败,因为
\showOff {\showOn {foo}}
不会输出foo
。
编辑:
我的错,没有早点把这个包括进去。颜色改变不起作用。文档到处都在改变颜色(在 pdfTeX 中)。
答案1
该答案不依赖于颜色并且允许逐字文本。
\catcode 64 11
\newif\if@inSO@
\def\ShowOff{\afterassignment\ShowOff@\setbox\z@\hbox}
\def\ShowOff@{\@inSO@true\aftergroup\ShowOff@@}
\def\ShowOff@@{\hskip\wd\z@}
\def\ShowOn{\if@inSO@\expandafter\ShowOn@\fi}
\def\ShowOn@#{\egroup\bgroup\aftergroup\ShowOn@@\let\next= }
\def\ShowOn@@{\ShowOff\bgroup}
\catcode 64 12
abcdefghijklmnop
coffin
abc\ShowOff{defg\ShowOn{hi\ShowOff{jk}lm}n}op
\ShowOn{co\ShowOff{f\ShowOn{f}i}n}
\end
它是如何\phantom
工作的?它将文本存储在一个框中,然后创建一个具有相同宽度、高度和深度的空框。以类似的方式,我将收集应该隐藏在框 0 中的文本,并生成与该框宽度相同的水平空间。所有要显示的文本都是直接排版的。
让我们分析一下例子\ShowOff{abc}
首先它变成
\afterassignment\ShowOff@ \setbox\z@\hbox{abc}
TeX 记住\ShowOff@
在下一个赋值之后使用,即\setbox
。 在 的情况下,“赋值后”标记的位置\setbox
有点棘手;在我们的例子中,它位于 后面的左括号之后。暂时\hbox
忽略。 将在正在构建的框结束后立即放置。反过来,此宏会插入框大小的水平跳跃。\@inSO@true
\aftergroup\ShowOff@@
\ShowOff@@
现在,\ShowOn
通过提前结束的框\ShowOff
(即在\egroup
中)来取消隐藏\ShowOn@
。然后在那里插入水平跳过。然后我们可以排版 的参数\ShowOn
,然后恢复隐藏。我本来可以定义\def\ShowOn@#1{\egroup#1\ShowOff\bgroup}
,但这会提前抓住参数,禁止逐字逐句。相反,我\aftergroup
再次使用: 的参数\ShowOn
以组的形式出现,{...}
。不知何故,我们想\aftergroup\ShowOn@@
在左括号后插入。打开一个括号(\bgroup
),然后删除用户放置的括号(\let\next=
)。
我仍需解释一下该@inSO@
开关。如果\ShowOn
出现在任何\ShowOff
命令之外,它应该对其参数不执行任何操作。否则,它的行为将如上一段所述。
编辑:我尝试在下面添加对数学模式的支持(没有将其合并到上面,因为宏变得丑陋)。
\catcode`@=11
\def\ShowOff
{%
\v@true\h@true
\ifmmode
\expandafter\mathpalette\expandafter\ShowOff@math
\else
\afterassignment\ShowOff@\setbox\z@\hbox
\fi
}
\def\ShowOff@{\let\ShowOn\ShowOn@\aftergroup\finph@nt}
\long\def\ShowOff@math#1{%
\setbox\z@\hbox\bgroup$\m@th #1%
\bgroup
\aftergroup\ShowOff@math@
\long\def\ShowOn##1{\egroup##1\ShowOff@math#1\bgroup}%
\let\next= }
\def\ShowOff@math@{$\egroup\finph@nt}
\let\ShowOn\relax
\def\ShowOn@#{\egroup\bgroup\aftergroup\ShowOn@@\let\next= }
\def\ShowOn@@{\ShowOff\bgroup}
\catcode`@=12
% Tests.
$abcdefg^h_{ijkl}mnop$ $co^{ffi}n$
$abc\ShowOff{defg\ShowOn{^h_{i\ShowOff{jk}l}m}n}op$
$\ShowOn{co^{\ShowOff{f\ShowOn{f}i}}n}$
abcdefghijklmnop coffin
abc\ShowOff{defg\ShowOn{hi\ShowOff{jk}lm}n}op
\ShowOn{co\ShowOff{f\ShowOn{f}i}n}
\bye
答案2
\input color
\def\showOn#1{\textcolor{black}{#1}}
\def\showOff#1{\textcolor{white}{#1}}
Cat \showOff { dog \showOn {red \showOff {blue} green } superman} wonderwoman
\bye
更新
这是不假设文本为黑色的解决方案。但是,它假设背景为白色。此外,内部任何显式的颜色变化\showOff
都会使文本可见。
\input color
\catcode`\@=11
\newif\ifinside@showoff
\def\showOff#1{\textcolor{white}{\inside@showofftrue#1}}
\def\showOn#1{\ifinside@showoff
\bgroup\inside@showofffalse\reset@color#1\egroup\color{white}%
\else#1\fi}
\color{green} Cat \showOff { dog \showOn {\textcolor{red}{red}
\showOff {blue} green } superman} wonderwoman
\bye