引自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
@endpe
true
我怀疑可能的答案涉及到(对我来说)关于“段落制作环境在被其他环境调用时正常工作”,但如果能提供完整的解释就更好了。
附加问题:如果我要定义一个自定义列表环境,并在其末尾设置\@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 的真相带到环境边界之外,直到下一个或。\everypar
parenvB
\@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
。不一定是您想要的。