breaklines=true does not work next to wrapfigure

I have some text with code next to a figure.

I am currently using \begin{wrapfigure} with 0.5\textwidth and lstinline[breaklines=true], but my code won't break:

\paragraph{Rx-Pipeline}
\begin{wrapfigure}{r}{0.5\textwidth}
\begin{center}
\includegraphics[width=0.47\textwidth]{Inhalt/Bilder/marbles.png}
\end{center}
\caption{\label{fig:pipeline}Hier wird ein Bild mit wrapfig eingebunden}
\end{wrapfigure}

Die Rx-Pipeline für die Indexierung neuer Nextcloud-Daten ist, wie in \autoref{fig:pipeline} schematisch dargestellt,
in sieben einzelne Schritte unterteilt:

Zunächst wird die Liste an \lstinline[breaklines=true]|IndexingActions|, die der DataFetcher zurückgibt, in eine Reihe einzelner
\lstinline[breaklines=true]{Observables} verwandelt, um diese einzeln reaktiv abarbeiten zu können.

Im nächsten Schritt werden diejenigen \lstinline[breaklines=true]{IndexingAction}s gefiltert, deren Operation den Wert
\lstinline[breaklines=true]{INSERT} hat (wir befinden uns dann speziell in der Abarbeitung der neu hinzugefügten Dateien).

\blindtext[1]


Does the code breaking not work next to an image? I don't experience this anywhere else in my document.

What can I do to fix this? Break it manually?

• The problem is not wrapfigure, but that IndexingActions has no break points. Same would happen at end of line – wang ki wun Aug 23 '19 at 15:55

As mentioned in the comments, the cause of this problem is that listings doesn't find a proper place to break the inline listing. As a solution the code below defines a new listings option softbreaks[=false|true] that replaces each occurrence of the sequence \- in an inline listing by a new optional breakpoint. If the breakpoint was considered for a line break, a hyphen is printed, otherwise nothing is printed.

listings only inserts possible line break points (in form of \discretionary items) at the borders between the following tokens:

• Identifiers/keywords, i.e. a letter character followed by a series of letter or digit characters;
• numbers, symbols etc., i.e. a series of digit or other characters, not started by a letter;
• a series of whitespace/space characters; or
• a series of characters that form a sequence to be replaced by a literate item.

We can use the latter fact to define literate items that are not printed visibly but only add new optional breakpoints for the line breaking algorithm. In this case an optional hyphen is useful. However, as usual, things are not that easy with listings. We cannot just put an extra \discretionary into the literate item's replacement text, because a box is wrapped around that text.

We instead add a new hook into the internal \lst@Literate command, that is executed before the actual typesetting of the literate code is run. It's necessary to disable the usual discretionary insertion because otherwise a sequence <token>\-<token> would be processed as <token><discretionary><new discretionary><token>, so the <new discretionary> would never be used for a line break.

In the new hook we do a check whether the found literate sequence is the \- one, and if so, we temporarily disable the discretionary insertion. When the literate replacement is actually processed afterwards, the insertion is enabled again, but with a new routine that tests if a global switch \if@usesoftbreak is set to true. This only happens when \- is replaced, so other literate items are surrounded by the normal discretionary items. <token>\-<token> then is correctly processed as <token><new discretionary><token>.

Full code with examples

The most relevant column in the output is the last one where \- is used. Unfortunately, I wasn't able to figure out why the vertical spacing is slightly different for the boxes where softbreaks is enabled.

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{listings}
\usepackage{etoolbox}

\makeatletter

\newif\if@usesoftbreak

\let\lst@olddiscretionary=\lst@@discretionary
\def\lst@softbreak{\discretionary{-}{}{}}

\def\lst@newdiscretionary{%
%    \rule[-0.4ex]{0.4pt}{2ex}%
\if@usesoftbreak
\lst@softbreak
\else
\lst@olddiscretionary
\fi
\global\@usesoftbreakfalse
}

\patchcmd\lst@Literate{\ifx\lst@OutputBox\@gobble}%
{\lst@hkBeforeLiterate{#2}\ifx\lst@OutputBox\@gobble}{}{}

\global\@usesoftbreakfalse
\global\let\lst@@discretionary=\lst@olddiscretionary
}

\def\lst@hkBeforeLiterate#1{%
\def\@tempa{\lst@dosoftbreak}%
\def\@tempb{#1}%
\ifx\tempa\tempb
\global\let\lst@@discretionary=\relax
\fi
}

\lst@Key{softbreaks}{false}[t]{%
\lstKV@SetIf{#1}\lst@ifsoftbreaks
\lst@ifsoftbreaks
\global\let\lst@@discretionary=\lst@newdiscretionary
\lstset{breaklines}%
\expandafter\def\expandafter\lst@literate\expandafter
{\lst@literate{\\-}{\lst@dosoftbreak}1}%
\fi
}

\def\lst@dosoftbreak{%
\global\let\lst@@discretionary=\lst@newdiscretionary
\global\@usesoftbreaktrue
}

\makeatother

\lstset{
basicstyle=\ttfamily,
}

\newbox\demobox
\def\db#1{%
\begin{lrbox}{\demobox}%
\begin{minipage}{#1}%
\raggedright
}
\def\enddb{%
\end{minipage}%
\end{lrbox}%
\fbox{\usebox\demobox}%
}

\def\demo#1{%
[#1]\par
\smallskip
\scantokens{%
\db{5em}\lstinline[#1]|IndexingActions|\enddb \hspace{3em}%
\db{5em}\lstinline[#1]|Indexing Actions|\enddb \hspace{3em}%
\db{5em}\lstinline[#1]|Indexing-Actions|\enddb \hspace{3em}%
\db{5em}\lstinline[#1]|Indexing\-Actions|\enddb \par
\smallskip
\db{13.6em}\lstinline[#1]|IndexingActions|\enddb \hspace{3em}%
\db{13.6em}\lstinline[#1]|Indexing\-Actions|\enddb \par
}%
}

\begin{document}
\parindent=0pt
\ttfamily

\demo{ }
\bigskip
\demo{breaklines}
\bigskip
\demo{softbreaks}
\bigskip
\demo{literate={A}{a}1,softbreaks}
\bigskip
\demo{breaklines}

\end{document}