1

I need to be able to highlight added lines of code in a listing environment. Consider this example:

Let's create variables:

\begin{lstlisting}
let msg = "Hello";
let name = "Jody";
\end{lstlisting}

And then add the method for printing:

\begin{lstlisting}
let msg = "Hello";
let name = "Jody";

// My first hack
console.log(msg + " " + name);
\end{lstlisting}

In the second part, I would like to have in grey the two variables and in black the new lines added.

Important The formatting of keywords according to the language I use should be preserved.


A few notes

I have seen many ways to achieve this for single lines. I need to use this a lot, is there a way to encapsulate a block of code and set its color differently instead of acting for each single line? The approach I got suggested was to use:

\lstset{escapeinside={(*@}{@*)}}

And:

(*@\textcolor{black}{ <Different color code in here> }@*)

But this approach works per line and removes the language formatting inside \textcolor (if I typed: (*@\textcolor{black}{ function my() \{ \} }@*)), the keyword function would not appear in bold.

1 Answer 1

1

Edit: easier more robust method described here. Original answer below.

You can set the colors to custom commands like commentstyle=\mycommentcolor instead of directly using commentstyle=\color{colorname}, and then you can switch the definition of the commands during the listing using escapeinside.

MWE:

\documentclass{article}
\usepackage{listings}
\usepackage{xcolor}
\begin{document}
\def\setallcolors{%
\gdef\mybasiccolor{\color{black}}%
\gdef\mykwcolor{\color{blue}}%
\gdef\myndkwcolor{\color{darkgray}}%
\gdef\myidcolor{\color{black}}%
\gdef\mycommentcolor{\color{purple}}%
\gdef\mystringcolor{\color{red}}%
}
\def\setallgray{%
\gdef\mybasiccolor{\color{gray}}%
\gdef\mykwcolor{\color{gray}}%
\gdef\myndkwcolor{\color{gray}}%
\gdef\myidcolor{\color{gray}}%
\gdef\mycommentcolor{\color{gray}}%
\gdef\mystringcolor{\color{gray}}%
}
\setallcolors
\lstdefinelanguage{JavaScript}{
  basicstyle=\mybasiccolor,
  keywords={typeof, new, true, false, catch, function, return, null, catch, switch, var, let, if, in, while, do, else, case, break},
  keywordstyle=\mykwcolor\bfseries,
  ndkeywords={class, export, boolean, throw, implements, import, this},
  ndkeywordstyle=\myndkwcolor\bfseries,
  identifierstyle=\myidcolor,
  sensitive=false,
  comment=[l]{//},
  morecomment=[s]{/*}{*/},
  commentstyle=\mycommentcolor\ttfamily,
  stringstyle=\mystringcolor\ttfamily,
  morestring=[b]',
  morestring=[b]"
}
\lstset{numbers=left,escapeinside={(*@}{@*)}}
Let's create variables:

\begin{lstlisting}[language=JavaScript,name=Variables]
let msg = "Hello";
let name = "Jody";
\end{lstlisting}

And then add the method for printing:
\begin{lstlisting}[language=JavaScript,name=Printing]
(*@\setallgray@*)let msg = "Hello";
let name = "Jody";
(*@\setallcolors@*)// My first hack
console.log(msg + " " + name);
\end{lstlisting}
\end{document}

Result same as in the original answer below.


Original answer:

A possible approach is to define two languages, one in color or black and one in gray, and switch between these two. Some tricks are needed to make them appear as one listing, for example setting aboveskip and belowskip if needed, and resuming line numbers. The language definition is adapted from language option supported in listings. Alternatively you could try something like Automatic background coloring in listings using tikzmark or http://www.texample.net/tikz/examples/tikz-listings/.

MWE:

\documentclass{article}
\usepackage{listings}
\usepackage{xcolor}
\begin{document}
\lstdefinelanguage{JavaScript}{
  keywords={typeof, new, true, false, catch, function, return, null, catch, switch, var, let, if, in, while, do, else, case, break},
  keywordstyle=\color{blue}\bfseries,
  ndkeywords={class, export, boolean, throw, implements, import, this},
  ndkeywordstyle=\color{darkgray}\bfseries,
  identifierstyle=\color{black},
  sensitive=false,
  comment=[l]{//},
  morecomment=[s]{/*}{*/},
  commentstyle=\color{purple}\ttfamily,
  stringstyle=\color{red}\ttfamily,
  morestring=[b]',
  morestring=[b]"
}
\lstdefinelanguage{JavaScriptGray}{
  basicstyle=\color{gray},
  keywords={typeof, new, true, false, catch, function, return, null, catch, switch, var, let, if, in, while, do, else, case, break},
  keywordstyle=\color{gray}\bfseries,
  ndkeywords={class, export, boolean, throw, implements, import, this},
  ndkeywordstyle=\color{gray}\bfseries,
  identifierstyle=\color{gray},
  sensitive=false,
  comment=[l]{//},
  morecomment=[s]{/*}{*/},
  commentstyle=\color{gray}\ttfamily,
  stringstyle=\color{gray}\ttfamily,
  morestring=[b]',
  morestring=[b]",
  belowskip=-5pt
}
\lstset{numbers=left}
Let's create variables:

\begin{lstlisting}[language=JavaScript]
let msg = "Hello";
let name = "Jody";
\end{lstlisting}

And then add the method for printing:

\begin{lstlisting}[language=JavaScriptGray]
let msg = "Hello";
let name = "Jody";
\end{lstlisting}
\begin{lstlisting}[language=JavaScript,firstnumber=last]
// My first hack
console.log(msg + " " + name);
\end{lstlisting}
\end{document}

Result:

enter image description here

You must log in to answer this question.

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