# Reliable code for automatic \noindent after specific environments?

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.

-
Sorry my first attempt was a big flaw. I tried \newcommand*{\noindentnext}{\def\par{\@@par\noindent\let\par\@@par}} but you have the same. What do you mean it breaks? –  Marco Daniel May 4 '13 at 17:05
Well, I'm not exactly sure. But I remember that I had to be careful in a lot of situations or I'd get errors. An example: I get a missing \item error if a proof environment ends while the augmented \par is still in effect. I also remember getting errors if several augmented environments followed each other without a paragraph inbetween, but I can't seem to reproduce this right now. –  mhelvens May 4 '13 at 17:19
I've made the following rather invasive patch to fix these errors: \let\@old@end\end\renewcommand{\end}[1]{\let\par\@@par\@old@end{#1}}. Seems like I shouldn't be able to get away with it, but I did. –  mhelvens May 4 '13 at 17:41
FWIW, ConTeXt provides an indentnext key to control the indentation after an environment. See this article on ConTeXt wiki for details. This is an old feature that works with MkII (pdftex/xetex) as well as MkIV (luatex). –  Aditya Aug 2 '13 at 14:51

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 ...
%   {\@M}% original temporary setting for \clubpenalty replaced by ...
%   {\@clubpenalty}% ... or whichever value you deem right
%   {}{}
\newcommand*\NoIndentAfterEnv[1]{%
\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}


-
Wow. Pretty short! :-) It seems to work as expected in all cases that I could come up with. Furthermore, page breaks still seem to be allowed at the point of patching (why did you think they wouldn't be?) --- If there's one thing that keeps this solution from being perfect, it's the fact that the semantic distinction of paragraph breaks is now lost. A paragraph break is now applied even where I don't insert an empty line. This might affect documents that do other stuff at paragraph breaks. --- But that's just nitpicking. This solution will be just fine! –  mhelvens Aug 2 '13 at 16:02
»A paragraph break is now applied even where I don't insert an empty line.« -- But didn't you say Those environments basically always end a paragraph for me, anyway? ;) –  clemens Aug 2 '13 at 16:10
BTW: I'm not sure if the \clubpenalty\@M actually has any unwanted effects or not but I still wanted to point it out. –  clemens Aug 2 '13 at 16:13
@lockstep that's funny... well, badges, who knows what they're good for, anyway ;) –  clemens Aug 2 '13 at 16:22
There, package finished. Until it is available on CTAN, you can find the code here. –  mhelvens Aug 2 '13 at 19:50

The correct way to unconditionally remove indentation after list environments (note that quotes and theorems are also based on list) seems to be to change the definition of \@doendpe, specifically, to remove the code where "\par is redefined to restore \everypar" (source2e). See What exactly does \@doendpe do? for details.

\documentclass{article}

\newtheorem{theorem}{Theorem}

\newcommand*{\sometext}{Hello, here is some text without a meaning. This
text should show, how a printed text will look like at this place.
If you read this text, you will get no information.}

\makeatletter
\def\@doendpe{%
\@endpetrue
%  \def\par{% REMOVED
%    \@restorepar% REMOVED
%    \everypar{}% REMOVED
%    \par% REMOVED
%    \@endpefalse% REMOVED
%  }% REMOVED
\everypar{%
{\setbox\z@\lastbox}%
\everypar{}%
\@endpefalse
}%
}
\makeatother

\begin{document}

\sometext

\begin{itemize}
\item \sometext
\end{itemize}

\sometext

\begin{quote}
\sometext
\end{quote}

\sometext

\begin{theorem}
\sometext
\end{theorem}

\sometext

\end{document}


Should you want to remove indentation only after specific list-based (!) environments, you can incorporate a new \noindentafter switch into \@doendpe and use etoolbox' \BeforeBeginEnvironment to set the switch to true for the respective environments.

\documentclass{article}

\newcommand*{\sometext}{Hello, here is some text without a meaning. This
text should show, how a printed text will look like at this place.
If you read this text, you will get no information.}

\newif\ifnoindentafter
\noindentafterfalse

\makeatletter
\def\@doendpe{%
\@endpetrue
\def\par{%
\@restorepar
\everypar{}
\par
\@endpefalse
}%
\everypar{%
{\setbox\z@\lastbox}%
\everypar{}%
\@endpefalse
}%
}
\makeatother

\usepackage{etoolbox}
\BeforeBeginEnvironment{itemize}{\noindentaftertrue}

\begin{document}

\sometext

\begin{itemize}
\item \sometext
\end{itemize}

\sometext

\begin{enumerate}
\item \sometext
\end{enumerate}

\sometext

\end{document}


-
good try, but it doesn't work with amsthm. (although that isn't exactly what was requested.) –  barbara beeton Aug 2 '13 at 14:53
@barbarabeeton I know that the AMS classes are special: tex.stackexchange.com/a/36835/510 –  lockstep Aug 2 '13 at 14:58
@lockstep Great solution! It makes a lot of sense to take away the code that inserts the indentation rather than to add extra code to remove it again. And I see you even made it selective now! --- However, there are two reasons why I'm going with cgnieders solution: (1) It applies to any environment or command I want; not just list-based environments and (2) it's so much shorter and less invasive. --- Nonetheless, I found your answer very instructive. –  mhelvens Aug 2 '13 at 16:07
@mhelvens I was aware of (1), but since all your example environments were based on list, I decided to write an answer anyway. –  lockstep Aug 2 '13 at 16:09
@lockstep You're right. But as it happens, there's one command I still wanted to patch: \] :-) –  mhelvens Aug 2 '13 at 16:14