The following is a solution for the highlighting of parts of a line. It is a combination of the approches I have suggested in:
Basically, I use the listings moredelim=**
option to define delimiters, which styles then apply on top of all other formattings, so that the syntax formatting is kept.
To be not limited to a standard font command for the delimiter style, I 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, beamer overlay specifications and TikZ/PGF options to both, the tikzpicture and the node can be given in the optional argument (such as \btHL<1->[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.
\documentclass{beamer}
\usepackage[T1]{fontenc}
\usepackage{beramono}
\usepackage{listings}
\lstset{
basicstyle=\scriptsize\ttfamily,language=[LaTeX]Tex,breaklines=true,
breakautoindent=true,breakindent=2ex,
}
\lstMakeShortInline{!}
\usepackage{tikz}
\usetikzlibrary{positioning,calc}
\tikzset{onslide/.code args={<#1>#2}{%
\only<#1>{\pgfkeysalso{#2}} % \pgfkeysalso doesn't change the path
}}
\makeatletter
\newenvironment<>{btHighlight}[1][]
{\begin{onlyenv}#2\begingroup\tikzset{bt@Highlight@par/.style={#1}}\begin{lrbox}{\@tempboxa}}
{\end{lrbox}\bt@HL@box[bt@Highlight@par]{\@tempboxa}\endgroup\end{onlyenv}}
\newcommand<>\btHL[1][]{%
\only#2{\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
\begin{document}
\begin{frame}[fragile]{Highlighting single elements in listings}
\scriptsize !\btHL<overlay spec>[tikz key=val list]! highlights till the end of a group (no line breaks, though). Hence, it can be used as a ordinary font command with listings:
\par
\bigskip
\lstset{language=C, gobble=4}
\begin{lstlisting}[
moredelim={**[is][\btHL<1>]{@1}{@}},
moredelim={**[is][{\btHL<2>}]{@2}{@}}
]
#include @2<stdio.h>@
int @1main@(void) {
@2printf("Hello World!")@;
return 0;
}
\end{lstlisting}
\end{frame}
\begin{frame}[fragile]{Highlighting single elements in listings}
\scriptsize !\btHL<overlay spec>[tikz key=val list]! actually draws the content inside a TikZ node, so you can play with named nodes and other options:
\par
\bigskip
\begin{lstlisting}[language=C, gobble=4, numbers=left,
moredelim={**[is][{%
\btHL[name=X, remember picture, onslide=<2->{fill=red!50}]%
}]{@}{@}},
]
@int main (void)@ {
printf("Hello World!");
return 0;
}
\end{lstlisting}
% main() is typset into the node (X):
\tikz[remember picture, overlay]{
\path<2> node[red, above right=3mm of X](L){This is the entry point};
\draw<2>[->, red, shorten >=5pt] (L.west)--(X);
}
\end{frame}
\end{document}
