In my quest for a better solution for How to change appearance of a particular line when using \lstincludelisting, I came across the linebackground= option Martin Scharrer added to the listings package in his answer to Creating a zebra effect using listings.
The basic idea is to have a macro
% \btLstHL<overlay spec>{range list}
\newcommand<>{\btLstHL}[1]{%
\only#2{\btIfInRange{\value{lstnumber}}{#1}{\color{blue!30}}{}}%
}%
that expands to a \color{blue!30} if the current line fits into the range or to \empty (?) otherwise. This is then used together with linebackground
\begin{lstlisting}[language=C, gobble=6,linebackgroundcolor={%
\btLstHL{4}%
\btLstHL<1>{1-2,5-6}%
\btLstHL<2>{7}%
}]
/**
* Prints Hello World.
**/
#include <stdio.h>
int main(void) {
printf("Hello World!");
return 0;
}
\end{lstlisting}
This, however, does not work as intended, as all nonselected lines now get a white background:

The culprit, I guess, is in the implementation of lstlinebackground and how btLstHL gets expanded in its processing.:
\lst@Key{linebackgroundcolor}{}{%
\def\lst@linebgrdcolor{#1}%
}
\newcommand{\lst@linebgrd}{%
\ifx\lst@linebgrdcolor\empty\else % PROBLEM: for \btLstHL does not expand to \empty ???
\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
}
Apparently, \btLstHL expands to "nothing", but not \empty for nonselected lines, which causes \lst@linebgrd to highlight the background, but with its default color, which is the opposite of the current text color (black).
And at this point I am lost :-(
So how to define \btLstHL that it expands to \empty if the line is not within the given range?
Complete MWE:
\documentclass{beamer}
% beamer class setup
\usecolortheme{rose}
\setbeamertemplate{navigation symbols}{}
% we use UTF8
\usepackage[utf8]{inputenc}
% font setup
\usepackage[T1]{fontenc}
\usepackage[scaled=0.85]{beramono}
\usepackage{xcolor,listings, pgffor}
\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<overlay spec>{range list}
%
\newcommand<>{\btLstHL}[1]{%
\only#2{\btIfInRange{\value{lstnumber}}{#1}{\color{blue!30}}{}}%
}%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% \btInputEmph<overlay spec>[listing options]{range list}{file name}
%
\newcommand<>{\btLstInputEmph}[3][\empty]{%
\only#4{%
\lstset{linebackgroundcolor=\btLstHL{#2}}%
\lstinputlisting{#3}%
}% \only
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% lstlinebgrd.sty
%% see: https://tex.stackexchange.com/questions/18969/creating-a-zebra-effect-using-listings/18989#18989
%%
%% This small package is not yet published/not commonly available.
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 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{frame}[fragile]{Problem}
\begin{alertblock}{A cool app; unfortunately it has a white background}
\begin{lstlisting}[language=C, gobble=6,linebackgroundcolor={%
\btLstHL{4}%
\btLstHL<1>{1-2,5-6}%
\btLstHL<2>{7}%
}]
/**
* Prints Hello World.
**/
#include <stdio.h>
int main(void) {
printf("Hello World!");
return 0;
}
\end{lstlisting}
\end{alertblock}
\end{frame}
\end{document}
\btLstHLto expand to\empty. If you change your MWE to use\emptyas the linebackgroundcolor you get the same problem with white lines. To make it expand to \empty, you would only need to place that in the 4th argument, instead of leaving it actually empty as it is now. – Roelof Spijker Oct 11 '11 at 12:12\btIfInRange(among them{},{\empty},\empty) without any success. On the other hand, if one writesbackgroundcolor={}this works as expected (that is, the\ifx\lst@linebgrdcolor\emptyin\lst@linebgrdtakes the if-branch), so I concluded that{}vs.\emptyis not the root of the issue here. I assume that\ifxdoes not really expand its argument, but merrily checks for some kind of equivalence or so :-( – Daniel Oct 11 '11 at 12:53\ifxgoes to the true branch if and only if Both arguments are macros AND their first level expansion is identical AND they have the same status with respect to \long and \outer. Source. The first level expansion is most likely where it goes wrong. Not sure how to remedy that, yet. – Roelof Spijker Oct 11 '11 at 14:46I added
\show\lst@linebgrdcolor%right above theifxtest in the definition of\lst@linebgrd.Also, the true branch of your conditional doesn't have a token. Not sure if that's legal or not.
– Justin Bailey Oct 11 '11 at 15:15