如何确定自定义环境后面是否有一个新段落?

如何确定自定义环境后面是否有一个新段落?

我正在编写一个使用 minipages 显示其内容的自定义命令:

\newcommand{\example}[1]{\noindent\begin{minipage}{\linewidth}#1\end{minipage}}

此命令周围的间距应与环境的间距相似align\abovedisplayskip上方和\belowdisplayskip之后,因此我添加了\par\vspace{…}之前和之后:

\newcommand{\example}[1]{%
  \par\vspace{\abovedisplayskip}
  \noindent\begin{minipage}{\linewidth}#1\end{minipage}
  \par\addvspace{\belowdisplayskip}}

但这并不完美:\parskip即使命令周围没有空行,它也会在内容前后添加额外内容:

AAA % too much space (extra \parskip) after this
\example{\lipsum[1]}
BBB % too much space (extra \parskip) before that

我可以通过将定义更改为以下内容来删除第一个:

\newcommand{\example}[1]{%
  \ifvmode\else\par\vspace{-\parskip}\fi\vspace{\abovedisplayskip}
  \noindent\begin{minipage}{\linewidth}#1\end{minipage}
  \par\addvspace{\belowdisplayskip}}

但是命令底部的等效修复是什么?如果我使用负空格,将\parskip始终被抑制。理想情况下,我希望命令后面的文本不缩进,就像 一样\[\]

这是一个简单的例子:

\documentclass{minimal}

\usepackage{lipsum}
\setlength{\parskip}{50pt}

\newcommand{\example}[1]{%
  \ifvmode\else\par\vspace{-\parskip}\fi\vspace{\abovedisplayskip}
  \noindent\begin{minipage}{\linewidth}#1\end{minipage}
  \par\addvspace{\belowdisplayskip}}

\begin{document}

% There should be small spaces after AAA and before BBB
AAA
\example{\lipsum[1]}
BBB

% There should be a large space after AAA and a small one before BBB
% And BBB shouldn't be indented
AAA

\example{\lipsum[1]}
BBB

% There should be a small space after AAA and a large one before BBB
AAA
\example{\lipsum[1]}

BBB
\end{document} 

答案1

执行此操作的标准方法是将您的环境定义为trivlist,几乎所有的乳胶显示环境(逐字,中心,引用,..)都被定义为trivlists(特殊的单项版本列表)正是出于这个原因。

trivlist 代码检测列表前是否有段落分隔符,如果有,则前后是否有段落间距,但如果列表前没有段落分隔符,则列表\par后的内部将被隐藏,并且以下文本的段落缩进将被抑制。

\begin{center}\end{center}例如定义为

\def\center{\trivlist \centering\item\relax}
\def\endcenter{\endtrivlist}

答案2

这是一个可能的解决方案。我正在定义一个宏\tentativepar,它将和插入并\par设置为。此外,它还临时重新定义和(插入在每个段落的开头)以重置原始值(及其本身)。\parskip\parindent0pt\par\everypar

最终效果是\tentativepar将插入一个段落分隔符,而不会跳过或缩进除非紧接着是另一个\par

以下是一个例子:

\documentclass{article}

\setlength{\parskip}{50pt}

%% vv We need to store a couple of values
\newskip\savedparskip
\newskip\savedparindent
\newtoks\savedeverypar

\makeatletter
\newcommand*\tentativepar{%
  \par
  \savedparskip\parskip         %% <- store original parskip
  \savedparindent\parindent     %% <- store original parindent
  \expandafter\savedeverypar\expandafter{\the\everypar}
  %% ^^ store original \everypar
  \parskip0pt                   %% <- set parskip to 0pt
  \parindent0pt                 %% <- set parindent to 0pt
  %% vv restore everything that was saved after the first \par
  \def\par{%
    \@restorepar                  %% <- restore original \par
    \expandafter\everypar\expandafter{\the\savedeverypar}%
    \parskip\savedparskip         %% <- reset parskip
    \parindent\savedparindent     %% <- reset parindent
    \par                          %% still insert a paragraph break
  }%
  %% vv or at the stat of the next paragraph
  \expandafter\everypar\expandafter{%
    \the\savedeverypar
    \@restorepar                  %% <- restore original \par
    \expandafter\everypar\expandafter{\the\savedeverypar}%
    \parskip\savedparskip         %% <- reset parskip
    \parindent\savedparindent     %% <- reset parindent
  }
}
\makeatother

\newcommand{\example}[1]{%
  \ifvmode\else\tentativepar\fi
  \vspace{\abovedisplayskip}
  \noindent\begin{minipage}{.5\linewidth}#1\end{minipage}%
  \vspace{\belowdisplayskip}
  \tentativepar
}

\begin{document}

AAA
\example{There should be small spaces after AAA and before BBB}
BBB

AAA

\example{There should be a large space after AAA and a small one before BBB. And BBB shouldn't be indented.}
BBB

AAA
\example{There should be a small space after AAA and a large one before BBB}

BBB

CCC

\end{document}

输出

相关内容