我一直在探索在某些条件下抑制环境内容的不同方法。环境的问题在于,由于环境扫描结束标记的方式,许多技巧都不起作用,因此抑制内容通常无法找到抑制的结束。例如:
\begin{document}
\newif\iftest
\testfalse
\newenvironment{testenv}{\iftest}{\fi}
\begin{document}
\begin{testenv}
text!
\end{testenv}
\end{document}
这将返回“incomplete iffalse”,因为它无法找到 \fi,因为它在寻找 \fi 时无法执行 \end{testenv}(因此找不到结尾。这部分我明白了。
我尝试过各种其他方法,但我想远离逐字环境,因为我最终想嵌套它,而嵌套逐字环境是一个巨大的麻烦。
但是后来,我偶然发现了这里的“抑制”命令:选择性地抑制排版输出的生成。
因此我编写了以下工作代码:
\documentclass{article}
\usepackage{amsthm}
\usepackage{environ}
\newif\iftest
\testfalse
\NewEnviron{testenv}{\iftest\BODY\else Nope! \fi}
\newcommand{\Test}{}
\makeatletter
\font\dummyft@=dummy \relax
\def\suppress{%
\begingroup\par
\parskip\z@
\offinterlineskip
\baselineskip=\z@skip
\lineskip=\z@skip
\lineskiplimit=\maxdimen
\dummyft@
\count@\sixt@@n
\loop\ifnum\count@ >\z@
\advance\count@\m@ne
\textfont\count@\dummyft@
\scriptfont\count@\dummyft@
\scriptscriptfont\count@\dummyft@
\repeat
\let\selectfont\relax
\let\mathversion\@gobble
\let\getanddefine@fonts\@gobbletwo
\tracinglostchars\z@
\frenchspacing
\hbadness\@M}
\def\endsuppress{\par\endgroup}
\makeatother
\newenvironment{testenvtwo}{
\iftest\else\suppress\fi
}{
\iftest\else\endsuppress\fi
}
\begin{document}
Th below should read "Nope"
\begin{testenv}
This shouldn't show!
\end{testenv}
\hrule
Below this should be nothing
\begin{testenvtwo}
This also shouldn't show!
\end{testenvtwo}
\hrule
\testtrue
Below this should be "This should show!"
\begin{testenv}
This should show!
\end{testenv}
\hrule
Below this should be "This also should show!"
\begin{testenvtwo}
This also should show!
\end{testenvtwo}
\hrule
\end{document}
那么,为什么当其他各种方法都失败时,这里的 \suppress 命令却能够正常工作?我真的不明白 \suppress 在实践中是如何工作的,但我认为它只是吞噬它看到的所有内容,直到 \endsuppress 可能?但这似乎应该与 \if \fi 类型结构存在相同的问题。
如果有人能告诉我为什么当 \fi 和来自 etoolbox 等的环境钩子失败时,这个命令会起作用,我将不胜感激。我希望将来能够执行这种命令,所以我正在尝试了解它的工作原理。
答案1
问题是\fi
从未见过的。
假设你有这个普通的 TeX 文件
\newif\iftest
\def\blurb{\fi}
\testtrue
\iftest
Yes
\blurb
\testfalse
No
\blurb
\bye
如果\iftest
返回 true,\blurb
则进行扩展,这样 TeX 就能够看到\fi
匹配的\iftest
。
什么时候\iftest
返回 false 时,TeX 会跳过 true 测试无扩展,因此它将处于\bye
尚未看到匹配的状态\fi
。
您的代码也出现了同样的情况。
\documentclass{article}
\begin{document}
\newif\iftest
\testfalse
\newenvironment{testenv}{\iftest}{\fi}
\begin{document}
\begin{testenv}
text!
\end{testenv}
\end{document}
当\begin{testenv}
执行时,TeX 会看到\iftest
,它返回 false,因此它将跳过标记,直到看到\else
或 标记\fi
。TeX 找不到任何标记,因为不扩展在此跳过标记阶段执行。跳过将到达文件末尾,除非出现一些明确的标记\else or
\fi` 恰好被扫描。显式是指不隐藏在宏中。
没有安全的方法来埋入\fi
环境\end
的一部分;只有条件返回真时,这种方法才会起作用。
它是如何\suppress
工作的?它只是选择一种没有任何字符的字体,并重新定义字体更改命令\selectfont
以不执行任何操作;数学字体也设置为无。但\rule{1cm}{1cm}
在环境中尝试,你会看到打印出一些东西。当然还有\rule
可以禁用。
条件没有问题,因为 TeX 会\iftest...\fi
在开始和结束部分看到完整。
答案2
如果您想要一个在条件为假时被抑制的环境,请使用environ
包来获取整个环境内容,并且仅在条件为真时显示它们。
\documentclass{article}
\newif\iftest
\testfalse
\usepackage{environ}
\NewEnviron{test}{\iftest\BODY\fi}
\begin{document}
\begin{test}
Should not appear
\end{test}
\testtrue
\begin{test}
Should appear
\end{test}
\end{document}