[Tex/LaTex] How to highlight a block of source code in LaTeX

codehighlightingpackagessourcecode

I have many blocks of source code in my document (each of them is at least 40 lines). I would like to format parts of these code blocks, preferably with some annotations on the right. I was thinking about simply putting a coloured frame around some of the lines.

Is there some canonical way to do this? Are there any packages I could use?

Right now I am using listings package and the source code in my document is inserted in the following way:

\begin{lstlisting}
#include <stdio.h>
#define N 10
/* Block
 * comment */

int main()
{
    int i;

    // Line comment.
    puts("Hello world!");

    for (i = 0; i < N; i++)
    {
        puts("LaTeX is also great for programmers!");
    }

    return 0;
}
\end{lstlisting}

\lstinputlisting{hello.c}

Best Answer

With the verbatimbox package, optional arguments (in the form of macros) can be passed to the package's verbatim environments. This allows all sorts of customization. In my MWE below, I test the code line number. If it is in the range 8-18, it applies a background \colorfield to the listing. Also, I apply red line numbers if the code line number is in that range, or black numbers if it is outside of it (the default is no line numbers).

In addition, I check that if on code line 11, I call attention to that line with a boxed comment.

You can choose the background color method, the colorized line number method, the highlighted box method, all three, some combination thereof, or something completely different, all of which are customized through your macro definitions. The package keeps track of line numbers through the counter VerbboxLineNo, which may be utilized in your macros.

\documentclass{article}
\usepackage{verbatimbox,xcolor,lipsum}
% VERBATIMBOX PREP
\usepackage{verbatimbox}
\def\codesize{\footnotesize}
\newsavebox\thecolorfield
\newcommand\setcolorfield[1][blue!19!gray!18]{%
  \savebox{\thecolorfield}{\codesize%
    \makebox[0pt][l]{\textcolor{#1}{%
    \rule[-\dp\strutbox]{\textwidth}{\dimexpr\ht\strutbox+\dp\strutbox}}}}%
}

\def\colorfield{\usebox{\thecolorfield}}

\setcolorfield

\newcommand*\ifline[4]{%
  \ifnum\value{VerbboxLineNo}<#1#4\else
    \ifnum\value{VerbboxLineNo}>#2#4\else#3\fi
  \fi
}

\newcommand\rednum{\makebox[0ex][r]{\color{red}\arabic{VerbboxLineNo}:}\hspace{1ex}}

\newcommand\blacknum{\makebox[0ex][r]{\arabic{VerbboxLineNo}:}\hspace{1ex}}

\newcommand\boxcomment[1]{\fboxsep=1pt\smash{\rlap{%
    \textcolor{red!30}{\rule[-1pt]{.75\textwidth}{1pt}}%
    \colorbox{red!30}{\fbox{\parbox[b]{.2\textwidth}{\rmfamily #1}}%
  }}}%
}
\newcommand\commentA{\boxcomment{I am drawing attention to ``Hello World''}}
\begin{document}
\lipsum[3]
\begin{verbnobox%
  }[\codesize\ifline{8}{18}{\colorfield\rednum}{\blacknum}\ttfamily\ifline{11}{11}{\commentA}{}]
#include <stdio.h>
#define N 10
/* Block
 * comment */

int main()
{
    int i;

    // Line comment.
    puts("Hello world!");

    for (i = 0; i < N; i++)
    {
        puts("LaTeX is also great for programmers!");
    }

    return 0;
}
\end{verbnobox}
\lipsum[4]
\end{document}

enter image description here

Related Question