[Tex/LaTex] How to redefine \lstinline to automatically highlight or draw frames around all inline code snippets

highlightinginline()listingstikz-pgf

How to redefine \lstinline to automatically highlight or draw frames around all inline code snippets? E.g. using \bh and \eh commands from Highlight text in code listing while also keeping syntax highlighting ?
(I like the tikz solution since \f[color]box doesn't work with some characters sequences in code, like ^^^)

Added:

Minimal example:

\documentclass{article}
\usepackage{listings}
% (definitions from https://tex.stackexchange.com/questions/15237/highlight-text-in-code-listing-while-also-keeping-syntax-highlighting/18890#18890 should be inserted here)

% how to redefine the \lstinline command?

% Where to insert \bh and \eh commands?

\makeatletter
% \renewcommand\lstinline[1][]{%
%     \leavevmode\bgroup % \hbox\bgroup --> \bgroup
%       \def\lst@boxpos{b}%
%       \lsthk@PreSet\lstset{flexiblecolumns,#1}%            <-- \bh can be here (before '%')
%       \lsthk@TextStyle \lsthk@Endgroup\@empty
%       \@ifnextchar\bgroup{\afterassignment\lst@InlineG \let\@let@token}%
%                          \lstinline@}                      <-- but where to place \eh ???
\makeatother

\begin{document}

The following \emph{inline} code snippet should appear
in a frame (or highlighted) if lstinline command is properly redefined above:
\lstinline´chainl1(term, "+" ^^^ Add | "-" ^^^ Sub)´

\end{document}

I.e. how to achieve that inline code snippets in the whole document will be displayed inside small frames (or highlighted) without adding anything to \lstinline|xxx| commands in the document but only via redefinition of the \lstinline command itself? Is it possible?

Best Answer

One way to automatically apply the solutions form Highlight text in code listing while also keeping syntax highlighting around each lstinline is to redefine some of the internal macros from the listings package to include a \bh{} at the beginning of the listing and a \eh{}. To ensure that this only applies to inline listings, we use iftoggle from the etoolbox package to produce:

enter image description here

Known Issues:

  • Highlighting does not span line breaks correctly.

Code:

\documentclass{article}
\usepackage{etoolbox}
\usepackage{atbegshi,ifthen,listings,tikz}

% change this to customize the appearance of the highlight
\tikzstyle{highlighter} = [
  yellow,
  line width = \baselineskip,
]

% enable these two lines for a more human-looking highlight
%\usetikzlibrary{decorations.pathmorphing}
%\tikzstyle{highlighter} += [decorate, decoration = random steps]

% implementation of the core highlighting logic; do not change!
\newcounter{highlight}[page]
\newcommand{\tikzhighlightanchor}[1]{\ensuremath{\vcenter{\hbox{\tikz[remember picture, overlay]{\coordinate (#1 highlight \arabic{highlight});}}}}}
\newcommand{\bh}[0]{\stepcounter{highlight}\tikzhighlightanchor{begin}}
\newcommand{\eh}[0]{\tikzhighlightanchor{end}}
\AtBeginShipout{\AtBeginShipoutUpperLeft{\ifthenelse{\value{highlight} > 0}{\tikz[remember picture, overlay]{\foreach \stroke in {1,...,\arabic{highlight}} \draw[highlighter] (begin highlight \stroke) -- (end highlight \stroke);}}{}}}
%--------------------------


\makeatletter %   Redefine macros from listings package:
\newtoggle{@InInlineListing}%
\togglefalse{@InInlineListing}%

\renewcommand\lstinline[1][]{%
    \leavevmode\bgroup\toggletrue{@InInlineListing}\bh % \hbox\bgroup --> \bgroup
      \def\lst@boxpos{b}%
      \lsthk@PreSet\lstset{flexiblecolumns,#1}%
      \lsthk@TextStyle
      \@ifnextchar\bgroup{\afterassignment\lst@InlineG \let\@let@token}%
                         \lstinline@}%

\def\lst@LeaveAllModes{%
    \ifnum\lst@mode=\lst@nomode
        \expandafter\lsthk@EndGroup\iftoggle{@InInlineListing}{\eh{}}{}%
    \else
        \expandafter\egroup\expandafter\lst@LeaveAllModes
    \fi%
    }
\makeatother


\lstset{backgroundcolor=\color{green!10}}%

\begin{document}
The following \emph{inline} code snippet should appear
in a frame (or highlighted) if lstinline command is properly redefined above:
\lstinline´chainl1(term, "+" ^^^ Add | "-" ^^^ Sub)´Now back to regular text

\bigskip
The lstlisting environment is not affected:
\begin{lstlisting}
    chainl1(term, "+" ^^^ Add | "-" ^^^ Sub)
\end{lstlisting}
\end{document}