如何检测自己是否处于序言中?

如何检测自己是否处于序言中?

在 LaTeX 中,我想知道文档类是否已加载,以及代码是否在 内\begin{document}。换句话说,是否有\ifpreamble类似于\ifvmode和 朋友?

部分原因是好奇,部分原因是为了让图表更容易编译为独立图表或包含在某个较大的文档中。过去,我让包含文档定义一个宏,然后图表对其进行测试,但如果图表可以自己弄清楚就好了。

不起作用的东西(因为它们没有被\documentclass或改变\begin{document}):

  • \ifvmode立即生效
  • \@currenvir立即是“文件”
  • \normalsize立即定义

答案1

LaTeX 定义了许多宏,这些宏仅应在文档的前言中使用(例如\usepackage,但也有一些内部内核宏)。它通过 来实现这一点\@onlypreamble\SomeMacro。这通过添加\SomeMacro到列表中来实现,其中\begin{document}所有设置为\@notprerr,这是一个生成错误的宏。特别是,内核声明\@onlypreamble\@onlypreamble。这意味着我们可以通过执行以下操作来测试我们是否在前言中

\ifx\@onlypreamble\@notprerr (document)\else (preamble)\fi

如果我们在包中,想知道是在声明之前还是之后加载的\documentclass,我们可以看看\documentclass做了什么:除了其他许多事情之外,它还说\let\documentclass\@twoclasseserror(这可以防止调用\documentclass两次)。因此,测试 if\documentclass是否等于 ifx-equal 可以\@twoclasseserror解决这个问题。

\makeatletter
\def\MakeTest#1{%
  \edef#1{%
  \ifx\documentclass\@twoclasseserror % after \documentclass
    \ifx\@onlypreamble\@notprerr % after \begin{document}
      Hello
    \else % before \begin{document}
      Howdy
    \fi
  \else % before \documentclass
    Hi!
  \fi}}
\makeatother
\MakeTest\foo

\documentclass{minimal}

\MakeTest\bar

\begin{document}
\MakeTest\baz

foo says \foo; bar says \bar; baz says \baz
\end{document}

我认为这是非常强大的;我不认为任何包会发生改变\documentclass\@onlypreamble在它们被改变之后会产生错误的含义。

电子工具箱添加\AfterEndPreamble。中的代码\AfterEndPreamble{...}将被检测为“之后\begin{document}”(如艾哈迈德·穆萨在评论中)。

一方面,根据定义,\AfterEndPreamble代码是在\begin{document},参见http://mirrors.ctan.org/macros/latex/contrib/etoolbox/etoolbox.pdf

\AtEndPreamble代码是序言的一部分;\AfterEndPreamble 代码是文档主体的一部分,可能包含要在文档最开始排版的可打印文本。总而言之,LaTeX 将在“内部”执行以下任务\begin{document}

  • 执行任意\AtEndPreamble代码
  • 开始初始化文档主体(页面布局、默认字体等)
  • 加载上一次 LaTeX 传递过程中编写的主要辅助文件
  • 打开主辅助文件以在当前过程中进行写入
  • 继续初始化文档主体
  • 执行任意\AtBeginDocument代码
  • 完成文档主体的初始化
  • 禁用所有\@onlypreamble命令
  • 执行任意\AfterEndPreamble代码

另一方面,它仍然在之后输入的任何代码之前执行\begin{document}

答案2

如果全部你需要这个来允许你从主文档中单独编译组件文件,那么你可以看看Martin Scharrer 的standalone包裹,其设计目的正是实现这一目标。

相关内容