[Tex/LaTex] Highlight text in code listing while also keeping syntax highlighting

highlightinglistingssoul

I’m using the listings package for code listings. Now I try to highlight some part of the code using \hl from the soul package.

Here’s an example of a resulting query where the injected part of a SQL injection should be highlighted:

\begin{lstlisting}[escapechar=@,language=SQL]
SELECT name, password FROM users WHERE name='@\hl{' UNION SELECT "10", 1 \#}@';
\end{lstlisting}

But inside the highlighted part the SQL syntax highlighting is not applied.

So I tried to use \lstlinline for the code part inside \hl as well but it didn’t work:

\begin{lstlisting}[escapechar=@,language=SQL]
SELECT name, password FROM users WHERE name='@\hl{\lstinline[language=SQL]$' UNION SELECT "10", 1 #$}@';
\end{lstlisting}

Although this \lstinline part works outside the lstlisting block, it doesn’t work inside it. The error I get for that particular line is:

Extra }, or forgotten \endgroup.

Maybe I’m just missing just some special syntax to get this working. Or is it not possible at all to get proper syntax highlighting for the \hl-highlighted part as well?

Best Answer

It's almost a year later, but as the OP has not yet accepted an answer, I still see my chance :-)

In the following, I use the same basic principle as in my other answer, that is, employ listings moredelim=** option to define delimiters, which styles then apply on top of all other formattings, so that the syntax formatting is kept.

However, instead of being limited to a standard font command for the delimiter style, I now use an lrbox to grab the content of the current group. The resulting box holds the (syntax-formatted) output of listings, which can be used to implement more fancy highlighting styles.

In the example code, the implementation of the \btHL command employs TikZ to typeset the lrbox into a TikZ node. Additional TikZ/PGF options to both, the tikzpicture and the node can be given in the optional argument (such as \btHL[fill=red!20,draw=red]), which provides for pretty flexible highlighters.

(Note: when the optional argument is used inside some listings argument, the whole \btHL[<key>=<value>,...] command has to be put into curly braces in order to not confuse the listings key=value parser.)

The \btHL command can as well be used inside normal text. It does, however, not work across line breaks, which is a possible disadvantage compared to the approach that culminated from Bens answer. Insides of listings, however, this usually is not an issue.

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{listings,xcolor,beramono}
\usepackage{tikz}


\makeatletter
\newenvironment{btHighlight}[1][]
{\begingroup\tikzset{bt@Highlight@par/.style={#1}}\begin{lrbox}{\@tempboxa}}
{\end{lrbox}\bt@HL@box[bt@Highlight@par]{\@tempboxa}\endgroup}

\newcommand\btHL[1][]{%
  \begin{btHighlight}[#1]\bgroup\aftergroup\bt@HL@endenv%
}
\def\bt@HL@endenv{%
  \end{btHighlight}%   
  \egroup
}
\newcommand{\bt@HL@box}[2][]{%
  \tikz[#1]{%
    \pgfpathrectangle{\pgfpoint{1pt}{0pt}}{\pgfpoint{\wd #2}{\ht #2}}%
    \pgfusepath{use as bounding box}%
    \node[anchor=base west, fill=orange!30,outer sep=0pt,inner xsep=1pt, inner ysep=0pt, rounded corners=3pt, minimum height=\ht\strutbox+1pt,#1]{\raisebox{1pt}{\strut}\strut\usebox{#2}};
  }%
}
\makeatother

\lstdefinestyle{SQL}{
    language={SQL},basicstyle=\ttfamily, 
    moredelim=**[is][\btHL]{`}{`},
    moredelim=**[is][{\btHL[fill=green!30,draw=red,dashed,thin]}]{@}{@},
}

\begin{document}

A listing with {\btHL highlighting of all \textbf{important} elements} looks as follows:

\begin{lstlisting}[style=SQL]
SELECT name, password `FROM` users @WHERE@ name=@UNION SELECT@
\end{lstlisting}

enter image description here