在宏中切换幻影(纯 TeX)

在宏中切换幻影(纯 TeX)

我正在使用纯 TeX / pdfTeX。

有没有办法构建一组宏,比如\showOn/ \showOff,这样

  1. 我可以嵌套它们

  2. 对于给定的一段文本,它会“查找解析树”,找到第一个\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

相关内容