# Creating a zebra effect using listings

This question led to a new package:
lstlinebgrd (lstaddons bundle)

Friends, consider the following example using the listings package:

\documentclass{article}

\usepackage[T1]{fontenc}
\usepackage{beramono}
\usepackage{listings}
\begin{document}

\begin{lstlisting}[language=C,basicstyle=\ttfamily]
/**
* Prints Hello World.
**/
#include <stdio.h>

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

\end{document}


The output is as we expect:

I was wondering if we could add something I know as zebra effect (pardon my possible misinterpretation of this term). I know this as a common style used in tables, where rows alternate colors, hence the name zebra. The previous example should look something like this:

Does anyone have any ideas?

-
I’m sorry that I can’t really help, but I googled “listings alternatin color“ and found a post in comp.text.tex with a solution for fancyverb –  Tobi May 24 '11 at 18:19
@Tobi interesting approach! I'm gonna take a look, probably we can come up with something similar for listings. =) –  Paulo Cereda May 24 '11 at 19:08
I had a look at listings and can’t find something similar to \FancyVerbFormatLine, sorry –  Tobi May 24 '11 at 20:29
I now released my solution as lstlinebgrd package on CTAN as part of the lstaddons bundle. –  Martin Scharrer May 3 '12 at 15:10

The following code is giving a zebra effect. See below for a description.

\documentclass{article}

\usepackage[T1]{fontenc}
\usepackage{beramono}
\usepackage{listings}
\usepackage{xcolor}

\newcommand\realnumberstyle[1]{}

\makeatletter
\newcommand{\zebra}[3]{%
{\realnumberstyle{#3}}%
\begingroup
\lst@basicstyle
\ifodd\value{lstnumber}%
\color{#1}%
\else
\color{#2}%
\fi
\rlap{\hspace*{\lst@numbersep}%
\color@block{\linewidth}{\ht\strutbox}{\dp\strutbox}%
}%
\endgroup
}
\makeatother

\begin{document}

\begin{lstlisting}[language=C,basicstyle=\ttfamily,numberstyle=\zebra{green!35}{yellow!35},numbers=left]
/**
* Prints Hello World.
**/
#include <stdio.h>

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

\bigskip

% If you want to make the bars shorter you need to use a minipage or similar environment:
\noindent
\begin{minipage}{.45\textwidth}
\begin{lstlisting}[language=C,basicstyle=\ttfamily,numberstyle=\zebra{green!25}{white},numbers=left]
/**
* Prints Hello World.
**/
#include <stdio.h>

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

\end{document}


My first idea was to use backgroundcolor with a conditional depending on the line number, but it seem only be used for boxing the whole listing. After studying the source code of listings a while to learn how to hack the line processing I came to the idea to (mis-)use the numberstyle for this. It is called with the line number register as argument and is typeset inside a \llap in a distance of numbersep. I just put a low-level command of \colorbox (xcolor package) called \color@block inside a \rlap to place the colored bars. This requires numbers=left. If you don't want lines numbers keep \realnumberstyle how it is, or redefine it otherwise.

If you only want one color you can use the following definition and numberstyle=\zebra{<color>}.

\newcommand{\zebra}[2]{%
{\realnumberstyle{#2}}%
\begingroup
\lst@basicstyle
\ifodd\value{lstnumber}%
\color{#1}%
\rlap{\hspace*{\lst@numbersep}%
\color@block{\linewidth}{\ht\strutbox}{\dp\strutbox}%
}%
\fi
\endgroup
}


In the meantime I had a second look on the listings source code, this time to the numbers key. The following package hacks this key to inserts its own handler without interfering with the numbering like the code above. It then provides a set of new listings keys/options called linebackground..., to the set background color but also the height, depth, width, separation or even the drawing command.

You can set the color using linebackgroundcolor=<some color code> which can hold a conditional. The default background color is -., i.e. the opposite (-) of the current foreground color (aliased as . by xcolor). The box drawing code follows after color code inside braces, so if not background is wanted (not even a white one) than the color code can simply gobble the box drawing code as an argument.

% lstlinebgrd.sty
\RequirePackage{listings}
\RequirePackage{xcolor}

% 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
}


### Usage:

\documentclass{article}

\usepackage{lstlinebgrd}

\begin{document}

\begin{lstlisting}[language=C,basicstyle=\ttfamily,linebackgroundcolor={\ifodd\value{lstnumber}\color{green}\fi}]
/**
* Prints Hello World.
**/
#include <stdio.h>

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

\begin{lstlisting}[language=C,basicstyle=\ttfamily\Large,linebackgroundcolor={\ifodd\value{lstnumber}\color{green}\else\color{yellow}\fi},linebackgroundsep=1em,linebackgroundwidth=18em]
/**
* Prints Hello World.
**/
#include <stdio.h>

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

\begin{lstlisting}[language=C,basicstyle=\ttfamily\tiny,linebackgroundcolor={\color{blue!\the\numexpr 5*\value{lstnumber}\relax}},linebackgroundheight=1.7ex,linebackgrounddepth=.4ex]
/**
* Prints Hello World.
**/
#include <stdio.h>

int main(void) {
printf("Hello World!");
return 0;
}
/**
* Prints Hello World.
**/
#include <stdio.h>

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

\end{document}


-
Wow Martin, that's a pretty impressive code! I thought about a conditional depending on the line number too, but I couldn't go any further. Your answer is highly technical and very didatic, thanks a million! Hats off to ya! =D –  Paulo Cereda May 24 '11 at 22:03
@Paulo: I just figured out a way to add this as normal listings settings. I will publish the code for that tomorrow. –  Martin Scharrer May 25 '11 at 12:02
Awesome! I'm very curious! –  Paulo Cereda May 26 '11 at 17:10
amazing code, I bow before your skills! In my first code sketch I was trying to get the current line number and check it, but I wasn't unable of finding it. Besides, I was tempted to hack the basicstyle key, but it happened to be only a big block for the whole listing. Again, your code is highly technical and didatic, thanks! BTW, I'm not sure if possible, but have you considered including this new package in the TeX-SX initiave? I'd be great! –  Paulo Cereda May 27 '11 at 8:55
Really slick. Can you update it to handle line breaks/wrapping as well? I can't figure it out. Thanks! –  uosɐſ Nov 13 '12 at 2:50