50

I am preparing a presentation (using beamer) and I'll need to include many snippets of source-code. For including source code, I'll probably use listings package. (I know there is also minted package, but it's not available in my distro repositories, and thus it will be a lot harder and annoying to install).

However... In the middle of the source code, I want to highlight some lines, as I want to show which lines I've added, deleted or changed (when compared to the previous snippet). How can I do that?

In addition, maybe I might want to highlight some words from one line, but not the entire line.

(and by "highlight" I mean any kind of different style: maybe a background change, a font weight change, a color change...)

31

You can use any (All)TeX macro you wish within listings by enclosing it within escape brackets,

  (*@  \textcolor{blue}{code}  @*)

The funny eyes are the escapes you define them as follows:

\lstset{escapeinside={(*@}{@*)}}

For highlighting the soul package provides a nice highlight macro \hl, try it in the following minimal

\documentclass{article}
\usepackage{soul,listings,xcolor}

    \lstnewenvironment{teX}[1][]
      {\lstset{language=[LaTeX]TeX}\lstset{escapeinside={(*@}{@*)},
       numbers=left,numberstyle=\normalsize,stepnumber=1,numbersep=5pt,
       breaklines=true,
       %firstnumber=last,
           %frame=tblr,
           framesep=5pt,
           basicstyle=\normalsize\ttfamily,
           showstringspaces=false,
           keywordstyle=\itshape\color{blue},
          %identifierstyle=\ttfamily,
           stringstyle=\color{maroon},
        commentstyle=\color{black},
        rulecolor=\color{black},
        xleftmargin=0pt,
        xrightmargin=0pt,
        aboveskip=\medskipamount,
        belowskip=\medskipamount,
               backgroundcolor=\color{white}, #1
    }}
    {}
    \begin{document}


    \begin{teX}
      \test{this is some code}
      (*@  \textcolor{blue}{code}  @*)
      (*@  \hl{yellow code}  @*)
    \end{teX}
    \end{document}

I normally use an environment for "listings" settings, but you can use any other code style as well.

Another useful trick is to use the "listings" setting for emphasis in macros, like this:

\gdef\emphasis#1{\lstset{emph={begin,end,#1},
   emphstyle={\itshape\ttfamily\textcolor{blue}}}}

\gdef\hlemphasis#1{\lstset{emph={begin,end,#1},
   emphstyle={\hl{blue}}}}

This way you can emphasize keywords.

  • For highlighting, I've been using \structure{} and \alert{} commands from beamer package. And thank you for your answer! It was very helpful! – Denilson Sá Maia Jan 14 '11 at 4:30
24

The following is my approach to highlight complete lines or ranges/sets of lines in a listing in combination with beamer overlay specification.

The highlighting itself is done with Martin Scharrer's lstlinebgrd package, which adds a linebackgroundcolor key to the listings interface. In the following, I use this key together with a \btLstHL<overlay spec>{line range list} command, so that we set the color only on certain lines and only if the given <overlay spec> does match:

\begin{lstlisting}[
  linebackgroundcolor={%
    \btLstHL<1>{1-3}% on slide 1, highlight lines 1-3
    \btLstHL<2>{6,9}% on slide 2, highlight lines 6 and 9
    \btLstHL<3>{7}%
    \btLstHL<4>{8}%
  }]
    /**
    * Prints Hello World.
    **/
    #include <stdio.h>

    int main(void) {
       printf("Hello World!");  
       return 0;
    }
\end{lstlisting}

We get the following result:

enter image description here

The complete code:

\documentclass[dvipsnames,cmyk]{beamer}
\usepackage{pgf, pgffor}
\usepackage{listings}
\usepackage{lstlinebgrd} % see http://www.ctan.org/pkg/lstaddons

\makeatletter
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% \btIfInRange{number}{range list}{TRUE}{FALSE}
%
% Test in int number <number> is element of a (comma separated) list of ranges
% (such as: {1,3-5,7,10-12,14}) and processes <TRUE> or <FALSE> respectively

\newcount\bt@rangea
\newcount\bt@rangeb

\newcommand\btIfInRange[2]{%
    \global\let\bt@inrange\@secondoftwo%
    \edef\bt@rangelist{#2}%
    \foreach \range in \bt@rangelist {%
        \afterassignment\bt@getrangeb%
        \bt@rangea=0\range\relax%
        \pgfmathtruncatemacro\result{ ( #1 >= \bt@rangea) && (#1 <= \bt@rangeb) }%
        \ifnum\result=1\relax%
            \breakforeach%
            \global\let\bt@inrange\@firstoftwo%
        \fi%
    }%
    \bt@inrange%
}
\newcommand\bt@getrangeb{%
    \@ifnextchar\relax%
        {\bt@rangeb=\bt@rangea}%
        {\@getrangeb}%
}
\def\@getrangeb-#1\relax{%
    \ifx\relax#1\relax%
        \bt@rangeb=100000%   \maxdimen is too large for pgfmath
    \else%
        \bt@rangeb=#1\relax%
    \fi%
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% \btLstHL<overlay spec>{range list}
%
% TODO BUG: \btLstHL commands can not yet be accumulated if more than one overlay spec match.
% 
\newcommand<>{\btLstHL}[1]{%
  \only#2{\btIfInRange{\value{lstnumber}}{#1}{\color{orange!30}\def\lst@linebgrdcmd{\color@block}}{\def\lst@linebgrdcmd####1####2####3{}}}%
}%
\makeatother

\begin{document}

\begin{frame}[fragile]{MyListing}
  \lstset{language=C, numbers=left}
  \begin{lstlisting}[
    gobble=4,
    linebackgroundcolor={%
      \btLstHL<1>{1-3}%
      \btLstHL<2>{6,9}%
      \btLstHL<3>{7}%
      \btLstHL<4>{8}%
    }]
      /**
      * Prints Hello World.
      **/
      #include <stdio.h>

      int main(void) {
         printf("Hello World!");  
         return 0;
      }
  \end{lstlisting}
\end{frame}
\end{document}
  • Hi Daniel, thanks for your nice code. Can you give me one more option that make a box around some lines of code instead of highlighting them. Many thanks. – An Cong Tran Jan 7 '14 at 16:32
  • @AnCongTran: That is a bit more than a small addition and this question is specifically about highlighting. To keep topics concise, please ask a new question (including an MWE, and, maybe, a link to this answer. – Daniel Jan 7 '14 at 19:36
15

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}

enter image description here

  • Nice. But when I use an option like pin=foo in the option list for \btHL, I get Giving up on this path. Did you forget a semicolon?. – any ideas? – Joachim Breitner Feb 3 '14 at 13:35
  • @JoachimBreitner: I have tried a couple of things, but no idea yet. It works for other options, so I guess it is the pin/label-specific parser that somehow breaks it. – Daniel Feb 3 '14 at 13:44
  • Note, be careful about inserting \lstMakeShortInline{!} in your own header, because that will easily break your document if you are using exclamation marks somewhere! The rest of the code doesn't depend on this line. – coldfix Dec 9 '16 at 10:47
4

I like lstlinebgrd as well. I know OP was looking for a solution to use with Beamer, but when I only need to highlight a line of code in a static document I use an even simpler version of Daniel's suggestion. Add this to your preamble:

\usepackage{lstlinebgrd}

and then in the document:

\begin{lstlisting}[ 
    linebackgroundcolor={%
    \ifnum\value{lstnumber}=2
            \color{green!35}
    \fi
    \ifnum\value{lstnumber}=3
            \color{blue!10}
    \fi
    \ifnum\value{lstnumber}=4
            \color{blue!45}
    \fi
    }
    ]
// normal line of code
// highlighted line of code
// lighter blue highlight
// darker blue highlight

\end{lstlisting}

You might have to fiddle with the line numbers a few times to get it right but it works and you don't have to mess with macros.

Ends up looking like this:

enter image description here

3

I like the simplicity of this answer.

1) before \begin{document} put:

 \usepackage{color}

2) In your listings use colorbox like this:

\begin{lstlisting}[escapechar=!] 

...not highlighted... !\colorbox{yellow}{...**HIGHLIGHTED**...}! ...not highlighted...


\end{lstlisting}
  • Thanks for reporting it, I think this is the most convenient solution. – Clément Sep 22 '16 at 16:55
  • I think that the accepted answer has a similarly good result but does not add the extra spacing that \colorbox adds. – Raffi Khatchadourian Dec 5 '16 at 22:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.