\@doendpe 到底起什么作用?

\@doendpe 到底起什么作用?

引自LaTeX2e 来源

[ \@endparenv\@doendpe]

为了在段落创建环境之后立即抑制文本中的段落缩进,\everypar被改为删除空格,并被\par重新定义为恢复\everypar。 不再重新定义\par\everpar,而是\@endparenv改为设置@endpe开关,让\end重新定义\par\everypar

这样,当段落制作环境被其他环境调用时,它就可以正常工作。(1986 年 10 月 27 日更改)

这些是相关的代码行(添加了换行符以提高可读性):

\def\@endparenv{%
  \addpenalty\@endparpenalty
  \addvspace\@topsepadd
  \@endpetrue
}
\def\@doendpe{%
  \@endpetrue% <---?
  \def\par{%
    \@restorepar
    \everypar{}%
    \par
    \@endpefalse% <---?
  }%
  \everypar{%
    {\setbox\z@\lastbox}%
    \everypar{}%
    \@endpefalse% <---?
  }%
}

虽然我大致理解了\@doendpe它的\everypar诡计,但我对两个细节感到困惑(<---?在上面的代码中用 标记):

  • \begin作为包含的定义\@endpefalse,为什么需要在/重新定义的\@endpefalse末尾进行设置?\@doendpe\par\everypar

  • \@endpetrue为什么需要在开始时进行设置?只有将开关设置为时\@doendpe才会调用吗?\@doendpe@endpetrue

我怀疑可能的答案涉及到(对我来说)关于“段落制作环境在被其他环境调用时正常工作”,但如果能提供完整的解释就更好了。

附加问题:如果我要定义一个自定义列表环境,并在其末尾设置\@endpefalse并改为(使用适当的)调用(比如说)\aftergroup的副本,那么上面标记的代码行在此副本中是有益的还是多余的?\@doendpe\@doendcustomenv<---?

答案1

就我们的目的而言,\begin{#1}大致是

\begingroup \@endpefalse \csname #1\endcsname

\end{#1}大致是

\csname end#1\endcsname\expandafter \endgroup \if@endpe \@doendpe \fi

由于在组结束前\expandafter展开\if@endpe,因此使用的开关值是环境内的值。如果是功能\csname #1\endcsname的一部分,则将展开。但是,它将展开\begin{#1}\@endpetrue\@doendpe环境之外,其中开关已恢复为其原来的值。

考虑以下文档。环境parenvA随后会抑制缩进。在第二种情况下,\@endparenv在两个组内调用,并导致\@doendpe仍在环境中调用parenvB。如果的定义\@doendpe没有\@endpetrue,那么它只会在环境中定义\par和。这些定义将在组末尾消失,下一段将缩进。因此,相反,确保将 switch 的真相带到环境边界之外,直到下一个或。\everyparparenvB\@doendpe\par\everypar

\documentclass{article}
\makeatletter
\newenvironment{parenvA}{}{\par\@endparenv}
\newenvironment{parenvB}{}{}
\makeatother
\usepackage{lipsum}
\begin{document}
% case 1
\begin{parenvA}
  \lipsum[1]
\end{parenvA}
\lipsum[2]
% case 2
\begin{parenvB}
  \begin{parenvA}
    \lipsum[3]
  \end{parenvA}
\end{parenvB}
\lipsum[4]
% case 3
\begin{parenvB}
  \begin{parenvA}
    \lipsum[5]
  \end{parenvA}
  \lipsum[6]
\end{parenvB}
\lipsum[7]
\end{document}

一旦建立了,\par和都\everypar必须具有\@endpefalse,否则上例中的最后一段将失去其缩进:事实上,环境\@doendpe外部触发的parenvA包含\@endpetrue,但我们不希望在之后抑制缩进\end{parenvB},因为已经有一个段落了。

现在,为什么我们需要同时使用\everypar\par?因为实际上有两种情况。如果用户在 之后没有留下空行\end{parenvA},那么第一个字母(对于 TeX 来说,它本来就是水平的)会导致\everypar被插入 ,并吃掉缩进(使用\lastbox)。但是,如果用户留下一个空行,TeX 的眼睛会用一个标记替换它,这会重置和\par的正常定义,并且不会吃掉任何缩进(尝试在上面的文件中添加一些空行,看看会发生什么)。\par\everypar

\par对于您的附加问题,如果您删除这些行,则只有当下一个(空白行)或(由水平材料触发)位于同一组/环境中时,缩进才会被删除\everypar。不一定是您想要的。

相关内容