Is it a listings package bug?
Yes, it's a bug and a very old one.
The lstlisting
environment does, at the end, \let\if@nobreak\iffalse
, which is wrong because it's a local assignment, whereas the kernel command \@nobreakfalse
does the job globally.
\documentclass{article}
\usepackage{listings}
\makeatletter
\let\lstlisting\relax
\let\lstlisting@\relax
\lstnewenvironment{lstlisting}[2][]{%
\lst@TestEOLChar{#2}%
\lstset{#1}%
\csname\@lst @SetFirstNumber\endcsname
}{%
\@nobreakfalse
\csname\@lst @SaveFirstNumber\endcsname
}
\makeatother
\begin{document}
\section{Title}
\begin{lstlisting}
lstlisting content
\end{lstlisting}
text
\section{Title}
text
\begin{lstlisting}
lstlisting content
\end{lstlisting}
text
\section{Title}
text
\end{document}
This seems to be related to the way listings places its output if it is the first box after a section title (I didn't really investigate). You can work around this by placing a \leavevmode
after \section
and before \begin{lstlisting}
:
\documentclass{article}
\usepackage{listings}
\begin{document}
\section{Title}
\leavevmode
\begin{lstlisting}
lstlisting content
\end{lstlisting}
text
\section{Title}
text
\begin{lstlisting}
lstlisting content
\end{lstlisting}
text
\section{Title}
text
\end{document}