8

I will start with an example of what I would like to do.

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.

The code above should produce the following output (notice the spacing between the lines at the end of the itemize).

In some situations, I want to insert an enumeration (itemize or enumerate) inside a paragraph, and sometimes I want to insert it in the end and start a new paragraph after it, leaving an empty space. What I call a "paragraph" is not something starting with \paragraph{title} but simply a block of text delimited by empty lines in the code, which produces also a block of text delimited by two empty spaces in the output.

The mental image I have is that an enumeration is a part of my paragraph and I want it to behave the same way as anything else I put inside of my paragraph. So if it's the last thing in it, there should be a space after, and if not, then there should be no space. (Also, I put no space before my enumeration.)

I know how to always put a space after an enumeration or to never put anything after. But I don't know how to adapt the behaviour in the same way as when a paragraph ends. The way I do it now is to put no space by default and to add some \vspace{\parskip} if I end a paragraph with an enumeration.

How can I achieve what I described?

Complete example:

\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}

Non-working example and manual correction

mforbes
  • 5,571
  • 1
    Using enumitem you can add after=\vspace{\parskip} just to the list that ends the paragraph. This isn't automatic though. – Alan Munn Nov 23 '20 at 00:49
  • @AlanMunn Yes, thank you! I was aware of this possibility though, this is what I meant by "I know how to always put a space after an enumeration". Thanks for the tagging also. – Dabouliplop Nov 23 '20 at 01:23
  • @Dabouliplop Did you ever find a solution? – mforbes Sep 22 '23 at 01:02
  • @mforbes Unfortunately no, I just add spacing each time I need it. – Dabouliplop Sep 23 '23 at 09:58
  • 3
    @mforbes Can somebody add a minimal example? By default in the standard classes, there is no additional vertical space at the end of a paragraph, so simply removing the additional space after these lists in all cases would satisfy the desiderata. Since that solution doesn't apparently satisfy them and since output you describe as showing a new paragraph doesn't show one with standard formatting, I assume you're using a non-standard class and/or non-standard settings. It's hard to recommend anything since you provide no information about this. – cfr Sep 24 '23 at 18:54
  • @cfr I added a mwe using enumitem. Slightly different than the OP's example, but hopefully clear. (The example is a little contrived and does not look ideal with short snipits of text... but should give the idea.) – mforbes Sep 24 '23 at 20:59
  • 1
    Essentially what is being asked for is that you want the effects of the parskip package but only after lists, not anywhere else? – Alan Munn Sep 24 '23 at 21:05
  • @AlanMunn Which is different from the original question, which wanted space between all paragraphs, but not after lists unless followed by a paragraph break? So we have two questions? – cfr Sep 24 '23 at 23:41
  • @mforbes Really, you should ask a new question as you want something different from the OP, if I've understood correctly. – cfr Sep 24 '23 at 23:45
  • 1
    @cfr I think both the OP and I are asking how to customize lists so that there is less space if the following text is part of the same paragraph, and more space if there is a new paragraph. I can try to craft a better MWE that matches the OP's output if that is confusing or ask a new question if the OP thinks my MWE does not answer the original question. – mforbes Sep 25 '23 at 02:41
  • @AlanMunn I added parskip to the MWE and think what the OP wants and what I want are the same: extra space when the list is followed by a new paragraph. Sorry for confusing matters with my MWE that had different formatting. – mforbes Sep 25 '23 at 02:54
  • @Dabouliplop If what my example demonstrates is somehow orthogonal to what you are asking, please let me know and I will open a new question. – mforbes Sep 25 '23 at 02:58
  • @mforbes That's what I wanted to ask for, yes. I forgot that I was using the parskip package, I should have added that information. Thank you a lot to have brought attention to this question! I was not hoping for anything anymore but Willie solved it for me. However, I don't understand what is being said in the comments under Willie's answer, and how what you asked for is different from what I asked for... – Dabouliplop Sep 25 '23 at 20:17
  • (I mean I understand the comments except the part that says that your question is not solved.) – Dabouliplop Sep 25 '23 at 20:25
  • 1
    @Dabouliplop Your case is solved because the extra spaces is already provided by \parskip which just needs to be suppressed. My case does not use \parskip and so I still need a way to add the extra space. See the questions I linked below the answer. – mforbes Sep 27 '23 at 00:11
  • @mforbes Got it, thanks. – Dabouliplop Sep 28 '23 at 17:11

1 Answers1

7

Would this do?

\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}

Explanation

  1. We are almost forced into loading enumitem, since we cannot easily change \topsep otherwise.
  2. First we set \topsep to negative of the \parskip; by default the lists leave a vertical space of \topsep + \parskip (and also \partopsep if your list starts a new paragraph) at the beginning and end of the list. So we set \topsep to cancel out that defaul \parskip.
  3. You don't want to use the \after code from enumitem, since this is executed before ending the list environment, which is too early. We want to throw something in right after ending the list environment.
  4. Next, we want to detect a blank line that follows. What is useful here is that the list environment ends a paragraph with \par and ends up in vertical mode. Usually whether you put in a blank line has zero impact because \par is ignored in vertical mode. So what we will do is to force ourselves back in horizontal mode with \leavevmode. But once we are in horizontal mode, spaces are starting to be seen, so to avoid spurious spaces at the beginning of the line it is useful to also instruct \ignorespacesafterend.
  5. The setting of \parskip to 10ex is just to make the effect more pronounced. Setting \parindent to 0pt is to mimic the desired output of shown by the OP where paragraphs are unindented.

mforbes asked in a comment for a solution when \parskip is not used. The following is one attempt at it.

It turns out that to test for characters automatically after the end of an environment is a bit difficult. This is because in latex.ltx you see that when you issue \end{envname} what happens at the end is

    ...
    \UseHook{env/envname/after}    %% This is when the \AfterEndEnvironment hooks are run
    \if@ignore\@ignorefalse\ignorespaces\fi  %% Mechanism for \ignorespacesafterend
}

Because of the \if@ignore...\fi it is not feasible to use any code in the After Environment Hook to detect subsequent \pars. This leads to our first observation:

To do what we want we have to modify the \end{envname} mechanism itself.

Next, I assume you would want \end{itemize}<space><newline><newline> and \end{itemize}<newline><newline> to behave the same. In other words, you would want to allow there to be spaces before the \par and still detect the \par; conversely, I also assume that in a situation where you don't want to ignore spaces, you wouldn't want this behavior either. So

Need to allow spaces to be gobbled. For this we refer to this previous answer. A side effect is that you have to issue \AtEndEnvironment{<envname>}{\ignorespacesafterend} to activate this mechanism.

More about the implementation:

  • We define a new Boolean \@envendextrapar; the code detects (after gobbling spaces) whether the next token is \par. If so, it sets this boolean to be true, and otherwise do nothing.
  • It is the user's responsibility to put code into \AfterEndEnvironment{<envname>}{...} using this boolean environment. For the example code below, if the \par is detected, an extra 2cm of space is added.
\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}

Willie Wong
  • 24,733
  • 8
  • 74
  • 106
  • 1
    That looks good to me! In my example, I can just add \AfterEndEnvironment{enumerate}{\leavevmode\ignorespacesafterend} from the etoolbox package and it seems to work well. Let's see if that answers the OP. – mforbes Sep 25 '23 at 03:52
  • 1
    @mforbes I don't think you need etoolbox any longer. But I can't get an example working to produce the output I thought you wanted - only the output the OP wanted. But maybe I misunderstood what you wanted. – cfr Sep 25 '23 at 04:40
  • @cfr I think you are right about both points. I thought I could use this, but I need to explore how parskip works more. I will ask a new question with a more complete example, but Willie provides a good hint about needing to insert things after the environment. – mforbes Sep 25 '23 at 06:53
  • @mforbes No problem. Absolutely agree this is useful and you could link to this question from your new one to help people who might try to answer. The \leavevmode seemed especially useful. I was already experimenting with hooks - not \AfterEndEnvironment: instead env/enumerate/end, env/enumerate/after and the corresponding paragraph hooks LaTeX now provides. But I can't get something to apply only to the paragraph you want .... – cfr Sep 25 '23 at 16:26
  • @cfr Will do. Probably won't get to this until tomorrow. Thanks! – mforbes Sep 25 '23 at 19:07
  • 1
    It looks like my question has been asked and has a partial answer: Is it possible to have \partopsep added below a list environment that is followed by a new paragraph? I need to investigate that first to see if my use case has anything new. – mforbes Sep 26 '23 at 22:56
  • Also relevant is the question about \bottomsep, which does not exist, but would probably help. – mforbes Sep 26 '23 at 23:02
  • @mforbes: see edit, which I think should give you some idea of what you can do. – Willie Wong Sep 27 '23 at 05:15
  • 1
    Just by way of explanation: my second attempt above (for addressing @mforbes) is based on trying to detect a trailing \par after the environment; the solution mentioned in this comment is based on having the next \par executed detect whether it is immediately after the end of the environment. – Willie Wong Sep 27 '23 at 05:48
  • And for the reasons explained here, it is likely that the \par approach is better. – Willie Wong Sep 27 '23 at 05:54
  • @WillieWong Thanks! I was just starting to play around with setting a flag at the end of the environment and then detecting this in \par. Those links really help. – mforbes Sep 27 '23 at 15:44
  • I still need a bit of work to get everything working with enumitem, but I think this will get me there. Thanks for the hints. I have awarded the bounty. – mforbes Sep 30 '23 at 20:04