[Tex/LaTex] How to make \lstinline function normally inside math mode

inline()listingsmath-mode

\lstinline of the listings package doesn't work in math mode. When I try to use it, I get the error that \ttfamily is invalid in math mode.

However, when reasoning about program semantics, it is often necessary to put snippets of program code inside mathematical constructs and, ideally, this would be done with \lstinline in order to keep a consistent style between inline snippets and larger code blocks.

There are several ad-hoc case-by-case solutions, of course. I've been able to make \lstinline work within a \text command, being extra careful to escape certain characters. Sometimes I don't use \lstinline at all and format the code snippet by hand. Neither is really convenient.

Is there a generally applicable solution? Ideally I could just use \lstinline in math mode (well, its \lstMakeShortInline shortcut anyway) without any error. I do occasionally use mathescape inside code snippets. Having that still work would be nice, but is not essential.

Best Answer

If you do not need the resizing feature of \text and a simple \hbox (\mbox) suffices, then the following redefinition patches the first \bgroup to add \hbox in math mode:

\documentclass{article}
\usepackage{listings}

\usepackage{letltxmacro}
\newcommand*{\SavedLstInline}{}
\LetLtxMacro\SavedLstInline\lstinline
\DeclareRobustCommand*{\lstinline}{%
  \ifmmode
    \let\SavedBGroup\bgroup
    \def\bgroup{%
      \let\bgroup\SavedBGroup
      \hbox\bgroup
    }%
  \fi
  \SavedLstInline
}

\lstset{basicstyle=\ttfamily}
\begin{document}
\centering
Text: \lstinline|\foo%&$bar|
\[
  x = \lstinline|\foo%&$bar|
\]
\end{document}

Result

Patching via package etoolbox:

\documentclass{article}
\usepackage{listings}

\usepackage{etoolbox}
\expandafter\patchcmd\csname \string\lstinline\endcsname{%
  \leavevmode
  \bgroup
}{%
  \leavevmode
  \ifmmode\hbox\fi
  \bgroup
}{}{%
  \typeout{Patching of \string\lstinline\space failed!}%
}

\lstset{basicstyle=\ttfamily}
\begin{document}
\centering
Text: \lstinline|\foo%&$bar|
\[
  x = \lstinline|\foo%&$bar|
\]
\end{document}