Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

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...)

share|improve this question
1  
Related: http://tex.stackexchange.com/q/8368/1235. –  Hendrik Vogt Jan 13 '11 at 9:54

3 Answers 3

up vote 19 down vote accepted

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 easily.

share|improve this answer
    
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á Jan 14 '11 at 4:30

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}
share|improve this answer
    
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 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 at 19:36

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

share|improve this answer
    
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 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 at 13:44

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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