通过检查命令是否存在来记录包含内容

通过检查命令是否存在来记录包含内容

我正在尝试利用该\ifdefined漏洞编写包含多个文件的文档。我的想法如下:我在主文档中定义\ifNotEmbedded\let\ifNotEmbedded\iffalse,并将每个包含文件的前言包装在检查中\ifNotEmbedded

例如主文件:

% main.tex
\let\ifNotEmbedded\iffalse
\documentclass{article}
\begin{document}
\input{introduction.tex}
\end{document}

以及包含的文件:

%introduction.tex
\ifdefined\ifNotEmbedded
\else
    \let\ifNotEmbedded\iftrue
\fi

\ifNotEmbedded
\documentclass{article}
\begin{document}
\fi
     The content of the introduction goes here.
\ifNotEmbedded
\end{document}
\fi

通过这样做,我可以像独立文档一样编写内容introduction.tex并对其进行测试,而不必main.tex一遍又一遍地编译更大的内容,当一切准备就绪时,我只需编译main.tex即可获得完整的文章。

我遇到的问题是:如果我introduction.tex单独编译,它可以完美运行,但是当我编译时main.tex,包含不起作用:我收到以下错误

!不完整的 \ifdefined;第 3 行之后的所有文本均被忽略。

我怎样才能使这个想法实现呢?

答案1

如果你的主文件是

\documentclass{article}

\begin{document}

\input{intro}
\end{document}

那么intro.tex可能是

\makeatletter
\ifx\documentclass\@twoclasseserror
  \typeout{skipping preamble}
  \long\def\zzbegin#1\begin#2{}
  \long\def\zzend#1#2{}
\else
  \typeout{using preamble}
  \let\zzbegin\relax
  \let\zzend\relax
\fi
\makeatother

\zzbegin
\documentclass{article}
\begin{document}

% The content of the introduction goes here
Foo stuff

\zzend
\end{document}

当然,您也可以使用标准\include机制,它的优点在于您可以处理各个部分,即使它们必须涉及\ref其他部分中的项目。

答案2

我正在复制评论中的@DavidCarlisle 解释并修复原始问题。@DavidCarlisle 解决方案应该是首选,因为它不依赖于 eTeX(也适用于 Knuth 的 TeX)。

主要问题是,内部的条件\else .. \fi也匹配以支持连续情况(#if ... #elseif ... #elseif ... #endif例如在 C++ 中)。在我的代码中,如果\ifNotEmbedded定义了(编译时main.tex),则\else不会看到\let但仍会看到条件,\ifNotEmbedded\iftrue因此它期望两个匹配\fi\fi

由于条件中的条件很脆弱,我原来的代码的一个简单修复是通过定义一个无意义的保护命令来避免它,然后\let\InMainFile\relax检查它是否在那些包含的文件中定义,即主文件

%main.tex
\let\InMainFile\relax
\documentclass{article}

\begin{document}
\input{introduction.tex}
\end{document}

以及包含的文件

%introduction.tex
\unless\ifdefined\InMainFile
\documentclass{article}
\begin{document}
\fi

The content of the introduction goes here.

\unless\ifdefined\InMainFile
\end{document}
\fi

如果熟悉 C/C++,这与使用 完全相同#ifdef。我想知道为什么 eTeX 不提供另一个原语\ifundefined

相关内容