13

Martin Scharrer posted a very elegant answer for the question "Creating a zebra effect using listings". I want to extend that code to highlight only lines given in a comma separated list. The motivations is that I want to highlight certain lines of fully functional C code inputed from a file without using any escape chars

That means that I need a command

\ifinrange{<num>}{<range>}{<TRUE>}{<FALSE>}% num>=0

where range {-2,4,8-10, 15-} is {0,1,2,4,8,9,10,15,16,...}

\ifinrange{ 0}{-2,4,8-10, 15-}{TRUE}{FALSE}  -> TRUE
\ifinrange{ 3}{-2,4,8-10, 15-}{TRUE}{FALSE}  -> FALSE
\ifinrange{ 4}{-2,4,8-10, 15-}{TRUE}{FALSE}  -> TRUE
\ifinrange{ 9}{-2,4,8-10, 15-}{TRUE}{FALSE}  -> TRUE    %% EDIT: changed 7 to 9
\ifinrange{11}{-2,4,8-10, 15-}{TRUE}{FALSE}  -> FALSE
\ifinrange{20}{-2,4,8-10, 15-}{TRUE}{FALSE}  -> TRUE

The following code

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{beramono}
\usepackage{listings}
\usepackage{xcolor}
\makeatletter
\newcommand\realnumberstyle[1]{}
\newcommand{\HighLight}[3]{%
    {\realnumberstyle{#3}}%
    \begingroup
    \lst@basicstyle
    \ifinrange{\value{lstnumber}}{#2}{%
        \color{#1}%
        \rlap{\hspace*{\lst@numbersep}%
        \color@block{\linewidth}{\ht\strutbox}{\dp\strutbox}}}{}%
    \endgroup}
\newcommand{\ifinrange}[4]{}%%<<<<<<<<<<<<<<<<<
\makeatother
\begin{document}
\begin{lstlisting}[language=C,
                   basicstyle=\ttfamily,
                   numberstyle=\HighLight{green!35}{-3,6},
                   numbers=left]
/**
* Prints Hello World.
**/
#include <stdio.h>

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

must produce

enter image description here

3
  • I would name this question more after the inline macro required. The exact application is only secondary here. Commented May 25, 2011 at 6:47
  • @Martin Scharrer: You are right. I have changed the title
    – Danie Els
    Commented May 25, 2011 at 7:29
  • \ifinrange{ 7}{-2,4,8-10, 15-}{TRUE}{FALSE} -> TRUE should be FALSE instead. Commented May 25, 2011 at 8:06

1 Answer 1

10

Here a basic solution which works with your input. It might break on spaces at the wrong positions, so avoid them.

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{beramono}
\usepackage{listings}
\usepackage{xcolor}
\makeatletter
\newcommand\realnumberstyle[1]{}
\newcommand{\HighLight}[3]{%
    {\realnumberstyle{#3}}%
    \begingroup
    \lst@basicstyle
    \ifinrange{\value{lstnumber}}{#2}{%
        \color{#1}%
        \rlap{\hspace*{\lst@numbersep}%
        \color@block{\linewidth}{\ht\strutbox}{\dp\strutbox}}}{}%
    \endgroup}

\usepackage{pgf}
\usepackage{pgffor}

\newcount\rangea
\newcount\rangeb

\newcommand\ifinrange[2]{%
    \global\let\inrange\@secondoftwo
    \foreach \range in {#2} {%
        \afterassignment\getrangeb
        \rangea=0\range\relax
        \pgfmathtruncatemacro\result{ ( #1 >= \rangea) && (#1 <= \rangeb) }%
        \ifnum\result=1\relax
            \breakforeach
            \global\let\inrange\@firstoftwo
        \fi
    }%
    \inrange
}
\newcommand\getrangeb{%
    \@ifnextchar\relax
        {\rangeb=\rangea}%
        {\@getrangeb}%
}
\def\@getrangeb-#1\relax{%
    \ifx\relax#1\relax
        \rangeb=100000%   \maxdimen is too large for pgfmath
    \else
        \rangeb=#1\relax
    \fi
}

\makeatother
\begin{document}
\begin{lstlisting}[language=C,
                   basicstyle=\ttfamily,
                   numberstyle=\HighLight{green!35}{-3,6},
                   numbers=left]
/**
* Prints Hello World.
**/
#include <stdio.h>

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

Result

1
  • 1
    I'd do also \global\let\inrange\@secondoftwo, to prevent save stack buildup.
    – egreg
    Commented May 25, 2011 at 8:25

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .