[Tex/LaTex] Reliable code for automatic \noindent after specific environments

environmentsindentationparagraphspatching

This question led to a new package:
noindentafter

There are a number of environments which I never want to follow up with an indented paragraph. itemize, enumerate, theorem, definition, etc. I know there are people who think this is bad style. But it's a personal preference. Those environments basically always end a paragraph for me, so the visual clue is not needed in my case.

I've found several similar questions, but none of them do what I need:

That third one was actually most useful, but appears to be unreliable for patching existing environments with. It doesn't seem to be working in my memoir document.

To be clear, I don't want to remove the actual paragraph break. That's a semantic concept. I just want to patch the document style so that paragraphs following certain environments remain unindented.

I've tried the following two 'solutions' (which use etoolbox for patching):

\newcommand*{\noindentnext}{\everypar{{\setbox\z@\lastbox}\everypar{}}}
\newcommand*{\NoIndentAfterEnv}[1]{\AfterEndEnvironment{#1}{\noindentnext}}
\newcommand*{\NoIndentAfterCmd}[1]{\apptocmd{#1}{\noindentnext}{}{}}

\NoIndentAfterEnv{itemize}
\NoIndentAfterEnv{theorem}
...

This one is loosely based on the third post from the list above. It sometimes works. It sometimes does nothing. I'm unable to predict when it will fail. The second:

\let\old@par\par
\newcommand*{\noindentnextpar}{\def\par{\let\par\old@par\par\noindent}}
\newcommand*{\NoParIndentAfterEnv}[1]{\AfterEndEnvironment{#1}{\noindentnextpar}}
\newcommand*{\NoParIndentAfterCmd}[1]{\apptocmd{#1}{\noindentnextpar}{}{}}

I invented this one myself. It breaks when the patched environment is not followed by a paragraph. It has also shown itself to inexplicably fail in other situations.

Once and for all, I'd like to have a reliable way to do this.

Let me give an example of what I need, just to be clear:

\NoIndentAfterEnv{itemize}

\begin{itemize}
    \item ...
\end{itemize}

This starts a new paragraph. Note the empty line. But it should not be indented.

But this paragraph \emph{should} be indented.

Best Answer

You could make the following paragraph believe that it follows a heading where there's also no indent by appending \@afterindentfalse\@afterheading after the end of the environment. Package etoolbox provides the handy \AfterEndEnvironment which makes this an easy task. \@afterheading also temporarily sets \clubpenalty to \@M (10000), though. If you don't want this after the patched environment one could insert an adapted version of \@afterheading instead.

\documentclass{article}
% environment hooks and patching:
\usepackage{etoolbox}

\makeatletter
% uncomment the following if you don't want \clubpenalty\@M ...
% \let\nearly@afterheading\@afterheading
% \patchcmd\nearly@afterheading
%   {\@M}% original temporary setting for \clubpenalty replaced by ...
%   {\@clubpenalty}% ... or whichever value you deem right
%   {}{}
% ... and use \nearly@afterheading instead of \@afterheading here:
\newcommand*\NoIndentAfterEnv[1]{%
  \AfterEndEnvironment{#1}{\par\@afterindentfalse\@afterheading}}
\makeatother

\NoIndentAfterEnv{itemize}
% treat other environments you want to patch accordingly

% dummy text:
\usepackage{lipsum}
\begin{document}
\lipsum[1]

\begin{itemize}
  \item foo
  \item bar
\end{itemize}

\lipsum[1-2]
\end{document}

enter image description here