我将从我想做的一个例子开始。
Here is some enumeration:
\begin{enumerate}
\item First item.
\item Second item.
\end{enumerate}
And the text continues in the same paragraph.
Here is some enumeration:
\begin{enumerate}
\item First item.
\item Second item.
\end{enumerate}
And the text continues, but in a new paragraph.
上述代码应产生以下输出(注意末尾行之间的间距itemize
)。
在某些情况下,我想插入一个枚举(逐项列举或枚举)里面一个段落,有时我想将其插入到末尾并在其后开始一个新段落,留下一个空格。我所说的“段落”不是开头,\paragraph{title}
而只是代码中由空行分隔的一段文本,这也会在输出中产生由两个空格分隔的一段文本。
我脑海中的画面是,枚举是段落的一部分,我希望它的行为与段落中放入的其他内容相同。因此,如果它是段落中的最后一个元素,后面应该有一个空格,如果不是,那么后面就不应该有空格。(另外,我没有放空格前我的枚举。)
我知道如何在枚举后始终添加空格或永远不添加任何内容。但我不知道如何以与段落结束时相同的方式调整行为。我现在的做法是默认不添加空格,如果\vspace{\parskip}
以枚举结尾段落,则添加一些空格。
我怎样才能实现我所描述的?
完整示例:
\documentclass{article}
\usepackage{parskip}
\usepackage{enumitem}
\setlist[1]{
label=(\arabic*),
% What do I do here to insert a space if there is a
% new paragraph
% after=\vspace{\parskip},
}
\begin{document}
\noindent
\section{Non-working example (no space)}
Here is some enumeration:
\begin{enumerate}
\item First item.
\item Second item.
\end{enumerate}
And the text continues in the same paragraph.
Here is some enumeration:
\begin{enumerate}
\item First item.
\item Second item.
\end{enumerate}
And the text continues, but in a new paragraph.
\section{Desired output (manual space)}
Here is some enumeration:
\begin{enumerate}
\item First item.
\item Second item.
\end{enumerate}
And the text continues in the same paragraph.
Here is some enumeration:
\begin{enumerate}
\item First item.
\item Second item.
\end{enumerate}
\vspace{\parskip}
And the text continues, but in a new paragraph.
\end{document}
答案1
这样可以吗?
\documentclass{article}
\usepackage{enumitem}
\setlength{\parskip}{10ex}
\setlength{\parindent}{0pt}
\newenvironment{enumerateD}{\begin{enumerate}[topsep=-\parskip]}
{\end{enumerate}\leavevmode\ignorespacesafterend}
\begin{document}
Test
\begin{enumerateD}
\item Item
\item Item 2
\end{enumerateD}
test\\
test
Test
\begin{enumerateD}
\item Item
\item Item2
\end{enumerateD}
Test
\end{document}
解释
- 我们几乎被迫加载
enumitem
,因为否则我们无法轻易改变\topsep
。 - 首先我们
\topsep
设定消极的;默认情况下,列表在列表的开头和结尾处\parskip
留出垂直空间\topsep + \parskip
(如果您的列表开始一个新段落也是如此)。因此我们设置取消该默认设置。\partopsep
\topsep
\parskip
- 您不想使用
\after
来自的代码enumitem
,因为这是执行的前结束列表环境,这还为时过早。我们想在后结束列表环境。 - 接下来,我们要检测后面的空行。这里有用的是列表环境以 结束一个段落
\par
并以垂直模式结束。通常,是否放入空行不会产生任何影响,因为\par
在垂直模式下会被忽略。所以我们要做的就是用 强制回到水平模式\leavevmode
。但是一旦我们处于水平模式,空格就会开始可见,因此为了避免在行首出现虚假空格,指示 也很有用\ignorespacesafterend
。 - 设置
\parskip
为10ex
只是为了使效果更明显。设置\parindent
为0pt
是为了模仿 OP 所示的段落不缩进的期望输出。
mforbes 问道在评论中不使用时的解决方案\parskip
。以下是一次尝试。
事实证明,在环境结束后自动测试字符有点困难。这是因为latex.ltx
当你发出时,你会看到\end{envname}
最后发生的事情是
...
\UseHook{env/envname/after} %% This is when the \AfterEndEnvironment hooks are run
\if@ignore\@ignorefalse\ignorespaces\fi %% Mechanism for \ignorespacesafterend
}
由于\if@ignore...\fi
无法使用 After Environment Hook 中的任何代码来检测后续\par
代码。这引出了我们的第一个观察结果:
为了达到我们想要的效果,我们必须修改
\end{envname}
机制本身。
接下来,我假设您希望\end{itemize}<space><newline><newline>
和\end{itemize}<newline><newline>
的行为相同。换句话说,您希望允许在之前有空格,\par
并且仍然检测到\par
;相反,我还假设在您不想忽略空格的情况下,您也不希望这种行为。所以
需要允许空间被吞噬。为此,我们参考先前的答案。副作用是你必须发出
\AtEndEnvironment{<envname>}{\ignorespacesafterend}
才能激活此机制。
有关实施的更多信息:
- 我们定义一个新的布尔值
\@envendextrapar
;代码检测(在吞噬空格之后)下一个标记是否为\par
。如果是,它将此布尔值设置为真,否则不执行任何操作。 - 用户有责任
\AfterEndEnvironment{<envname>}{...}
使用此布尔环境将代码放入。对于下面的示例代码,如果检测到,则会添加\par
额外的空间。2cm
\documentclass{article}
\makeatletter
%%% From https://tex.stackexchange.com/a/432246/119
%%% A version of \futurelet that gobbles spaces
\def\futureletignorespaces#1#2{\def\nextaction{#2}%
\def\checkspace{\ifx\nexttoken\@sptoken
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
{\afterassignment\futureletagain\let\nexttoken= }
{\futurelet#1\nextaction}}%
\futurelet\nexttoken\checkspace}
\def\futureletagain{\futurelet\nexttoken\checkspace}
\newif\if@envendextrapar
\@envendextraparfalse
\def\doEnvEnd#1{%
\ifx\@envendextrapartest\par\relax\@envendextrapartrue\fi%
\UseHook{env/#1/after}%
\@envendextraparfalse%
\if@ignore\@ignorefalse\ignorespaces\fi
}
\@namedef{end }#1{%
\romannumeral
\IfHookEmptyTF{env/#1/end}%
{\expandafter\z@}%
{\z@\UseHook{env/#1/end}}%
\csname end#1\endcsname\@checkend{#1}%
\expandafter\endgroup\if@endpe\@doendpe\fi
\if@ignore\def\@tempa{\doEnvEnd{#1}}%
\def\@tempb{\futureletignorespaces\@envendextrapartest\@tempa}%
\else\def\@tempb{\UseHook{env/#1/after}}\fi%
\@tempb
}
\AtEndEnvironment{itemize}{\ignorespacesafterend} %% Required, see explanation
\AfterEndEnvironment{itemize}{\if@envendextrapar \vspace{2cm}\fi}
\makeatother
\begin{document}
Test
\begin{itemize}
\item First item
\item Second item
\end{itemize}
Test again, no blank line.
Test start
\begin{itemize}
\item Third item
\item Fourth item
\end{itemize}
Test again, with blank line
\end{document}