# Latex: Highlight areas in listing using different backgroundcolor

I'd like to highlight areas in a listing using different background colors. It should look something like this:

This is a basic example with a background color for the whole listing:

\documentclass{beamer}

\usepackage{listings}

\begin{document}

\begin{frame}[fragile]{Title}
\begin{lstlisting}[backgroundcolor=\color{yellow}]
function f() {
var x = 0;
return function g() {
var y = 0;
return [x, y];
}
}
\end{lstlisting}
\end{frame}

\end{document}


It looks like this:

How can I highlight the areas using different background colors?

• Please see the answers of Listing background broken by \colorbox and \framebox, especially the one of egreg
– Ñako
Jun 22, 2019 at 19:47
• Possible duplicate of Listing background broken by \colorbox and \framebox
– Ñako
Jun 22, 2019 at 19:47
• @Ñako I'm not really sure this is a real duplicate, could the answer to the other question work across lines starting and ending in the middle, and nested, such as the pink on orange on yellow as in the example here? Jun 22, 2019 at 20:35
• That answer does not work well in my case. You see a line (in the color of the background) between consecutive lines if you highlight them. Further, the color box ends where the code ends. It does not span the remaining space of the listing. Besides, it clutters the code of the listing quite much. Jun 22, 2019 at 20:45

Concerning the doubts raised in the comments of the question. I think it is other people's opinion and not mine to make the final decision of whether it is a duplicate of egreg´s answer to Listing background broken by \colorbox and \framebox or not. At first it seemed to me that it was.

I have found four approaches to achieve your output (and I am sure that there are more). And yes, you are completely right. They clutter the code of the listing quite much, you have to adjust position and dimensions, but at the end they do their work. Therefore, they are not improvements (since they can be surely also improved), they are just another way to reach the solution.

# 1. Egreg´s answer: Box-based approach

Starting with the egreg´s idea of using \colorbox with the package tcolorbox and its tcb library listings is actually almost possible to achieve the desired output.

The inter-line skip between the boxes can be turned off with \offinterlineskip and \par at the very end of the macro (Note: I have renamed the egreg´s \lcolorbox macro with \clbox and deleted the commands for adjusting the horizontal position \hspace*{-\fboxsep}):

\newcommand{\clbox}[2]{%
\offinterlineskip\colorbox{#1}{#2}\par%
}


To adjust the dimensions of a colorbox as well as to insert a new line (for nested boxes), you can include a \parbox inside of the \colorbox:

\newcommand{\clbox}[3]{%
\offinterlineskip\colorbox{#2}{%
\parbox[c][][c]{#1}{#3}}\par%
}


Output:

Code:

\documentclass{beamer}

\usepackage{tcolorbox}
\tcbuselibrary{listings}
\usepackage{xcolor}
\usepackage{varwidth}

\newsavebox{\myparbox}
\newlength{\myparboxwidth}
\newcommand{\autwidthparbox}[3][\myparboxwidth]{%
\sbox{\myparbox}{\begin{varwidth}{\dimexpr\textwidth-\fboxsep\relax}#3\end{varwidth}}%
\settowidth{\myparboxwidth}{\usebox{\myparbox}}%
\offinterlineskip\colorbox{#2}{%
\parbox[c][][c]{#1}{#3}}%
}

\newcommand{\clbox}[3][0]{%
\offinterlineskip\colorbox{#2}{%
\parbox[c][][c]{\dimexpr0.5\textwidth+#1em\relax}{#3}}\par%
}
\begin{document}
\begin{frame}[fragile]
\frametitle{Title}
\lstset{escapechar=§}

\begin{tcblisting}{
listing only,
colback=white,
colframe=white,
}
§\autwidthparbox{yellow}{%
function~f\clbox[-5.5]{orange}{() \{}%
\clbox[-0.5]{orange}{\hspace{1.0em} var x = 0;\\%
\hspace*{1.0em} return function g\clbox[-11.1]{red}{() \}}%
\hspace*{1.0em}\clbox[-2.1]{red}{\hspace{1.0em} var y = 0;\\%
\hspace*{1em} return [x, y];}%
\hspace*{1.0em}\colorbox{red}{\}}%
}%
\colorbox{orange}{\}}%
}§
\end{tcblisting}
\end{frame}

\end{document}


# 2. Tikz approaches

Taking as a starting point the answer to the question Is it possible to use tikz to draw a background on the printed page?, there are at least three possibilities:

## 2a. Based on \tikzmark tikz library code without background package

Output:

Code:

\documentclass{beamer}

\usepackage{tikz}
\usetikzlibrary{positioning,fit}
\usepackage{listings}

%https://tex.stackexchange.com/questions/86693/is-it-possible-to-use-tikz-to-draw-a-background-on-the-printed-page
\makeatletter
\tikzset{%
remember picture with id/.style={%
remember picture,
overlay,
save picture id=#1,
},
save picture id/.code={%
\edef\pgf@temp{#1}%
\immediate\write\pgfutil@auxout{%
\noexpand\savepointas{\pgf@temp}{\pgfpictureid}}%
},
if picture id/.code args={#1#2#3}{%
\@ifundefined{save@pt@#1}{%
\pgfkeysalso{#3}%
}{
\pgfkeysalso{#2}%
}
}
}

\def\savepointas#1#2{%
\expandafter\gdef\csname save@pt@#1\endcsname{#2}%
}
\def\tmk@labeldef#1,#2\@nil{%
\def\tmk@label{#1}%
\def\tmk@def{#2}%
}

\tikzdeclarecoordinatesystem{pic}{%
\pgfutil@in@,{#1}%
\ifpgfutil@in@%
\tmk@labeldef#1\@nil
\else
\tmk@labeldef#1,(0pt,0pt)\@nil
\fi
\@ifundefined{save@pt@\tmk@label}{%
\tikz@scan@one@point\pgfutil@firstofone\tmk@def
}{%
\pgfsys@getposition{\csname save@pt@\tmk@label\endcsname}\save@orig@pic%
\pgfsys@getposition{\pgfpictureid}\save@this@pic%
\pgf@process{\pgfpointorigin\save@this@pic}%
\pgf@xa=\pgf@x
\pgf@ya=\pgf@y
\pgf@process{\pgfpointorigin\save@orig@pic}%
}%
}

\newcommand\tikzmark[2][]{%
\tikz[remember picture with id=#2] #1;}
\makeatother

\begin{document}
\begin{frame}[fragile]{Title}
\noindent\begin{tikzpicture}[remember picture, overlay]
\node[preaction={fill=yellow},fit={(pic cs:a) (pic cs:e1) (pic cs:c)},inner ysep=0.85em,inner xsep=.5em,yshift=0.35em,xshift=0.2em] {};
\path[draw=none,preaction={fill=orange},]([shift={(0.em,-0.5em)}]pic cs:a) -| ([shift={(0em,-0.3em)}]pic cs:e1) -| ([shift={(0em,0.75em)}]pic cs:e2) -| ([shift={(0.4em,0em)}]pic cs:c) |- ([shift={(0.em,0.85em)}]pic cs:a);
\path[draw=none,preaction={fill=red},]([shift={(0.em,-0.5em)}]pic cs:g) -| ([shift={(0em,-0.35em)}]pic cs:d1) -| ([shift={(0em,0.75em)}]pic cs:d2) -| ([shift={(0.1em,0em)}]pic cs:c) |- ([shift={(0.em,0.85em)}]pic cs:g);
\end{tikzpicture}%
%
\begin{lstlisting}[, linewidth=0.5\textwidth,escapechar=§]
function f§\tikzmark{a}§() {
§\tikzmark{b}§var x = 0;
return function g§\tikzmark{g}§() {§\tikzmark{c}§
§\tikzmark{f}§var y = 0;
return [x, y];
§\tikzmark{d1}§}§\tikzmark{d2}§
§\tikzmark{e1}§}§\tikzmark{e2}§
\end{lstlisting}
\end{frame}
\end{document}


## 2b. Based on \tikzmark tikz library with background package

Output:

Code:

\documentclass{beamer}

\usepackage{tikz}
\usetikzlibrary{positioning,fit,tikzmark}
\usepackage{listings}
\usepackage[pages=some]{background}
\tikzset{every tikzmarknode/.style={minimum width=0pt}}
\begin{document}
\usebackgroundtemplate{%
\noindent\begin{tikzpicture}[remember picture, overlay]
\node[preaction={fill=yellow},fit={(a) (e) (c)},inner ysep=0.85em,inner xsep=.45em,yshift=0.35em,xshift=0em] {};
\path[draw=none,preaction={fill=orange},]([shift={(0em,-0.5em)}]a.north) -| ([shift={(0.0em,-0.25em)}]e.south) -| ([shift={(0.5em,0.85em)}]e.east) -| ([shift={(0.15em,0em)}]c.east) |- ([shift={(0em,0.85em)}]a.north);
\path[draw=none,preaction={fill=red},]([shift={(0em,-0.5em)}]g.north) -| ([shift={(0em,-0.25em)}]d.south) -| ([shift={(0.5em,0.85em)}]d.east) -| ([shift={(-0.15em,0em)}]c.east) |- ([shift={(0em,0.85em)}]g.north);
\end{tikzpicture}%
}%
\begin{frame}[fragile]{Title}
\begin{lstlisting}[, linewidth=0.5\textwidth,escapechar=§]
function f§\tikzmarknode{a}{}§() {
§\tikzmarknode{b}{}§var x = 0;
return function g§\tikzmarknode{g}{}§() {§\tikzmarknode{c}{}§
§\tikzmarknode{f}{}§var y = 0;
return [x, y];
§\tikzmarknode{d}{}§}
§\tikzmarknode{e}{}§}
\end{lstlisting}
\end{frame}
\end{document}


## 2c. Based on \tikz with background package

Output:

Code:

\documentclass{beamer}

\usepackage{tikz}
\usetikzlibrary{positioning,fit}
\usepackage{listings}
\usepackage[pages=some]{background}

%https://tex.stackexchange.com/questions/86693/is-it-possible-to-use-tikz-to-draw-a-background-on-the-printed-pag
\def\p#1{\tikz[remember picture, overlay, anchor=base, baseline]\node[anchor=base,minimum width=0pt,] (#1) {};}

\begin{document}
\usebackgroundtemplate{%
\noindent\begin{tikzpicture}[remember picture, overlay]
\node[preaction={fill=yellow},fit={(a) (e) (c)},inner ysep=0.5em,inner xsep=.1em,yshift=0.25em,xshift=0.1em] {};
\path[draw=none,preaction={fill=orange},]([shift={(0em,-0.75em)}]a.north) -| ([shift={(0em,0em)}]e.south) -| ([shift={(0.25em,0.85em)}]e.east) -| ([shift={(0em,0em)}]c.east) |- ([shift={(0em,0.5em)}]a.north);
\path[draw=none,preaction={fill=red},]([shift={(0em,-0.75em)}]g.north) -| ([shift={(0em,0em)}]d.south) -| ([shift={(0.25em,0.85em)}]d.east) -| ([shift={(-0.25em,0em)}]c.east) |- ([shift={(0em,0.5em)}]g.north);
\end{tikzpicture}%
}
\begin{frame}[fragile]{Title} % backgroundcolor=\color{yellow}
\begin{lstlisting}[, linewidth=0.5\textwidth,escapechar=§]
function f§\p{a}§() {
§\p{b}§var x = 0;
return function g§\p{g}§() {§\p{c}§
§\p{f}§var y = 0;
return [x, y];
§\p{d}§}
§\p{e}§}
\end{lstlisting}
\end{frame}
\end{document}


I have a working solution that uses Tikz to draw the box above the listing. It is quite hacky. Feel free to submit improvements.

\documentclass{beamer}

\usepackage{listings}
\lstset{
escapechar=§,
basicstyle=\ttfamily,
keepspaces=true,
}

\usepackage{tikz}
\usetikzlibrary{positioning}

\usepackage{keyval,xparse}% http://ctan.org/pkg/{keyval,xparse}

\makeatletter
% ========= KEY DEFINITIONS =========
\define@key{colorCodeBlock}{color}{\def\mm@color{#1}}
\define@key{colorCodeBlock}{columns}{\def\mm@columns{#1}}
\define@key{colorCodeBlock}{startLine}{\def\mm@startLine{#1}}
\define@key{colorCodeBlock}{startColumn}{\def\mm@startColumn{#1}}
\define@key{colorCodeBlock}{endLine}{\def\mm@endLine{#1}}
\define@key{colorCodeBlock}{endColumn}{\def\mm@endColumn{#1}}
\DeclareDocumentCommand{\colorCodeBlock}{m}{%
\begingroup%
% ========= KEY DEFAULTS + new ones =========
\setkeys{colorCodeBlock}{color={yellow},columns={27},startLine={1},startColumn={11},endLine={7},endColumn={1},#1}%
\def\ccbWidth{\mm@columns * \lstCharWidth}
\def\ccbBlockSideHeight{(\mm@endLine - \mm@startLine) * \lstLineHeight}
\def\ccbTy{\firstLineTy - \mm@startLine * \lstLineHeight + \lstLineHeight}
\def\ccbRx{\lstCharWidth + \ccbWidth}
\def\ccbTMx{\mm@startColumn * \lstCharWidth}
\coordinate (ccbTRL) at (\ccbTMx,\ccbTy);
\coordinate (ccbTR) at (\ccbRx,\ccbTy);
\coordinate[below=\ccbBlockSideHeight of ccbTR] (ccbBR);
\coordinate[left=(\ccbWidth - \mm@endColumn * \lstCharWidth) of ccbBR] (ccbBRL);
\coordinate[below=\lstLineHeight of ccbBRL] (ccbBLR);
\coordinate[left=\lstCharWidth of ccbBLR] (ccbBL);
\coordinate[above=\ccbBlockSideHeight of ccbBL] (ccbTL);
\coordinate[below=\lstLineHeight of ccbTRL] (ccbTLR);
\filldraw[\mm@color] (ccbTRL) -- (ccbTR) -- (ccbBR) -- (ccbBRL) -- (ccbBLR) -- (ccbBL) -- (ccbTL) -- (ccbTLR) -- cycle;
\endgroup%
}
\makeatother

\def\lstInnerSep{3mm}
\def\lstLineHeight{4.8mm}
\def\lstCharWidth{2.7mm}

\begin{document}

\begin{frame}[fragile]{Title}
\begin{tikzpicture}[x=1mm,y=1mm]
\def\lstInnerSep{3mm}
\def\lstLineHeight{4.8mm}
\def\lstCharWidth{2.7mm}

\def\lineCount{7}
\def\firstLineTy{\lineCount * \lstLineHeight + \lstInnerSep}
\filldraw[yellow] (0,0) rectangle (23 * \lstCharWidth + \lstInnerSep, \firstLineTy + \lstInnerSep);

\colorCodeBlock{
color=orange,
columns=22,
startLine=1,
startColumn=10,
endLine=7,
endColumn=1
}
\colorCodeBlock{
color=red,
columns=21,
startLine=3,
startColumn=18,
endLine=6,
endColumn=3
}

\node[anchor=south west,inner sep=\lstInnerSep] at (0,0) {
\begin{lstlisting}
function f() {
var x = 0;
return function g() {
var y = 0;
return [x, y];
}
}
\end{lstlisting}
};
\end{tikzpicture}
\end{frame}

\end{document}