是否存在字体大小环境?

是否存在字体大小环境?

毫无疑问,字体大小开关以控制序列的形式存在(在这里例如。)但是,有时我会遇到使用环境版本的代码示例,例如\begin{small}...\end{small}。在成功测试这些代码后,我开始将它们合并到我的 TeX 词汇表中。

几天前@GonzaloMedina 在我的回答中评论说这些环境并不存在,依赖它们的构造纯属巧合。然后我试图了解更多关于这些不祥环境的信息。不祥是因为它们似乎没有以某种方式记录下来。(我发现的唯一试图以某种系统的方式解释它们的是一些 Wikibooks 资源。)

这些环境是真实的吗?

答案1

您可以使用LaTeX由定义的任何命令\newcommand并将\begin{}...\end{}其包装成一对,但是,我们不建议这样做,因为这不是一个环境。

然而有趣的是,分组无论如何都有效,但这是的结果\begin...\end

没有像\begin{small}etc 这样的字体大小环境,因为没有\begin{chapter}etc。

例如:

\documentclass{article}


\newcommand{\foo}{This does nothing}

\begin{document}
\begin{foo}

\end{foo}
\end{document}

编辑一些解释

此代码可以在中找到latex.ltx,参见第 4058f 行。

\def\begin#1{%
  \@ifundefined{#1}%
    {\def\reserved@a{\@latex@error{Environment #1 undefined}\@eha}}%
    {\def\reserved@a{\def\@currenvir{#1}%
     \edef\@currenvline{\on@line}%
     \csname #1\endcsname}}%
  \@ignorefalse
  \begingroup\@endpefalse\reserved@a}

可以看出,@ifundefined{foo}将会调用 ,这是错误的,因为它\foo已被定义,所以environment名称foo被设置并且\csname #1\endcsname(即\foo)被调用。

现在是\end{foo}: 部分

\def\end#1{%
  \csname end#1\endcsname\@checkend{#1}%
  \expandafter\endgroup\if@endpe\@doendpe\fi
  \if@ignore\@ignorefalse\ignorespaces\fi}

环境查找\end...代码,此处\endfoo未定义,但\csname endfoo\endcsname扩展为,\relax并且没有发生任何不好的事情。

需要注意的是,许多众所周知的环境并没有用 来定义\newenvironment。使用\foo命令 和就足够了,例如\def\endfoo参见\endequation或等。\endenumerate

答案2

任何命令都可以用作环境,如果围绕大块文本,通常很方便,因此

{\small  zzz\par}

\begin{small}%
zzzz

\end{small}

或多或少是等价的。

但请注意,与 不同,由于正常的 TeX 标记化规则,\small后面的空格不会被删除。此外,您几乎总是需要在 之前添加一个 或 空行,这在命令形式中也是如此,但在环境形式中更容易忘记,因为大多数自定义环境(例如)在其结束代码中包含一个隐式,但这里的情况并非如此。\begin{small}\par\endcenter\par

另请参阅以下讨论:

\end.... 宏名称在 LaTeX2e 中保留吗?

答案3

实际上,“LaTeXbook”(正确的名称应该是“LaTeX. 一种文档准备系统”,作者是 Leslie Lamport)支持使用此类环境:在第 27 页的末尾我们发现:

每个声明都有一个对应的同名环境(减去字符\)。输入

\begin{em} ... \end{em}

相当于输入{\em ... }

具体来说,“环境”形式会自动提供一个组,以保持声明的效果在本地,就像环境中总是发生的那样(\begin发出一个\begingroup,以及\end相应的\endgroup)。现在,\small是一个声明,因此上述内容适用。

这样做是故意的,因此我认为说这些环境“偶然”起作用是不对的;事实上,正如已经观察到的,缺少类似命令的定义\endsmall不会引起任何问题,因为它被称为\csname small\endcsname,因此等同于\relaxif undefined。

所以,最后我的回答是:“是的,这些环境是‘真实的’”(不管这意味着什么)。


添加

看到一些评论后,我觉得补充一些关于 LaTeX2e 中环境实现方式的细节可能会很有用(我不会谈论 LaTeX3,因为我没有足够的专业知识)。 Christian Hupfer 已经提供了确切的代码摘录latex.ltx,但也许有人会发现以下补充说明也很有用。

当您定义环境时FOO,LaTeX 只需定义两个新命令\FOO\endFOO:后者始终没有参数,而前者具有为环境指定的相同参数(如果有)FOO。 当\begin{FOO}遇到时,会发生以下事情(其中包括):

  • 一个组以 开始\begingroup

  • \begin(在本例中)的参数FOO被(本地)保存在宏中\@currenvir,以便稍后能够检查每个参数是否\end与正确的配对\begin

  • 该命令\FOO作为最后一项命令执行;因此,它将吸收后面的参数\begin{fOO}(如果存在)。

另一方面,当 LaTeX 出现时\end{FOO},会发生以下情况(除其他事项外):

  • \endFOO如果它被定义,则执行(如果它未被定义,则什么也不会发生,如上所述);

  • LaTeX 检查的参数\end是否等于\@currenvir ,如果不相等,则抛出错误;

  • \endgroup发出一个通知来关闭该群组。

实际上,当我基于另一个标准环境定义新环境时,我倾向于避免使用显式的\begin\end,这样 的值\@currenvir就不会改变。例如,假设我想定义一个quote环境变体,使其内容以斜体显示;我更喜欢,比如说,

\newenvironment{italquote}{%
  \quote
  \itshape
}{\endquote}

超过

\newenvironment{italquote}{%
  \begin{quote}%
  \itshape
}{\end{quote}}

尤其是如果我自己不打算使用环境的话。这样,如果用户在语句中拼错了环境的名称\end,他们就会收到有关错误终止环境的错误italquote,而这正是他们实际使用的环境,而不是有关错误终止环境的错误quote,因为他们可能不知道这一点。

相关内容