6

I want to highlight either a whole line of code in a listing, or a part of line (a subexpression) using background color (to not interfere with syntax highlighting).

I use lstlistings environment from 'listings' package.

8

Listings allow escaping to TeX, so you can put a box in the background:

\documentclass{standalone}
\usepackage{listings,xcolor}
\lstset{language=c,escapechar=|}
\begin{document}
\begin{lstlisting}
int main (int argc, char ** argv)
{
  |\makebox[0pt]{\color{yellow}\rule[-0.1ex]{30em}{2ex}}|printf("Hello, world\n");
  exit(0);
}
\end{lstlisting}
\end{document}

enter image description here

  • if the listing environment has background, this solution may not work well -- there may be spaces that break the listing background. – An Cong Tran Feb 10 '14 at 3:48
3

Here is one easy-to-use solution built on posts from this site.

Sources :

  1. Creating a zebra effect using listings
  2. Listing, zebra effect and broken lines
  3. Highlighting line ranges in a lstlisting: partial solution, but expansion issues

The code:

\documentclass[10pt,a4paper]{article}
    \usepackage[utf8x]{inputenc}
    \usepackage{ucs}
    \usepackage{amsmath}
    \usepackage{amsfonts}
    \usepackage{amssymb}

    \usepackage{xcolor}
    \usepackage{listings}

    \usepackage{pgf}
    \usepackage{pgffor}

% Define backgroundcolor
    \usepackage[
        style=1,
        skipbelow=\topskip,
        skipabove=\topskip
    ]{mdframed}

    \definecolor{bggray}{rgb}{0.85, 0.85, 0.85}
    \mdfsetup{
        leftmargin = 20pt,
        rightmargin = 20pt,
        backgroundcolor = bggray,
        middlelinecolor = black,
        roundcorner = 15
    }
    \BeforeBeginEnvironment{lstlisting}{\begin{mdframed}\vskip-.5\baselineskip}
    \AfterEndEnvironment{lstlisting}{\end{mdframed}}

    \makeatletter
%
% \btIfInRange{number}{range list}{TRUE}{FALSE}
%
% Test if 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{range list}
%
        \newcommand{\btLstHL}[1]{%
            \btIfInRange{\value{lstnumber}}{#1}%
            {\color{blue!30}}%
            {\def\lst@linebgrd}%
        }%

%
% \btInputEmph[listing options]{range list}{file name}
%
        \newcommand{\btLstInputEmph}[3][\empty]{%
            \lstset{%
                linebackgroundcolor=\btLstHL{#2}%
                \lstinputlisting{#3}%
            }% \only
        }

% Patch line number key to call line background macro
        \lst@Key{numbers}{none}{%
            \def\lst@PlaceNumber{\lst@linebgrd}%
            \lstKV@SwitchCases{#1}{%
                none&\\%
                left&\def\lst@PlaceNumber{\llap{\normalfont
                \lst@numberstyle{\thelstnumber}\kern\lst@numbersep}\lst@linebgrd}\\%
                right&\def\lst@PlaceNumber{\rlap{\normalfont
                \kern\linewidth \kern\lst@numbersep
                \lst@numberstyle{\thelstnumber}}\lst@linebgrd}%
            }{%
                \PackageError{Listings}{Numbers #1 unknown}\@ehc%
            }%
        }

% New keys
        \lst@Key{linebackgroundcolor}{}{%
            \def\lst@linebgrdcolor{#1}%
        }
        \lst@Key{linebackgroundsep}{0pt}{%
            \def\lst@linebgrdsep{#1}%
        }
        \lst@Key{linebackgroundwidth}{\linewidth}{%
            \def\lst@linebgrdwidth{#1}%
        }
        \lst@Key{linebackgroundheight}{\ht\strutbox}{%
            \def\lst@linebgrdheight{#1}%
        }
        \lst@Key{linebackgrounddepth}{\dp\strutbox}{%
            \def\lst@linebgrddepth{#1}%
        }
        \lst@Key{linebackgroundcmd}{\color@block}{%
            \def\lst@linebgrdcmd{#1}%
        }

% Line Background macro
        \newcommand{\lst@linebgrd}{%
            \ifx\lst@linebgrdcolor\empty\else
                \rlap{%
                    \lst@basicstyle
                    \color{-.}% By default use the opposite (`-`) of the current color (`.`) as background
                    \lst@linebgrdcolor{%
                        \kern-\dimexpr\lst@linebgrdsep\relax%
                        \lst@linebgrdcmd{\lst@linebgrdwidth}{\lst@linebgrdheight}{\lst@linebgrddepth}%
                    }%
                }%
            \fi
        }

    \makeatother


\begin{document}

\begin{lstlisting}[
    language = C,
    linebackgroundcolor = {\btLstHL{4-6,9}},
]
/**
* Prints Hello World.
**/
#include <stdio.h>
}
int main(void) {
    printf("Hello World!");  
    return 0;
}
\end{lstlisting}

\end{document}

enter image description here

  • Was thinking about a similar solution, but realized that it will work only with highlighting full lines, not partial lines. Still very useful to have. One suggestion: can you make the sources on this site as part of the text (as opposed to part of the code) so that they are click able links, and post an image. – Peter Grill Dec 2 '11 at 18:16

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.