[Tex/LaTex] Different colors for default and language-specific listings

knitrlistingsliterate-programmingmarkdown

I'm generating pdf documents using knitr and pandoc. The conversion is mostly automated from R markdown -> markdown -> latex -> pdf. However, my documents combine R source code and its output, and I would like to differentiate the two kinds of code visually.

As an example, here's the generated tex:

\documentclass[]{article}

\usepackage{listings}
\usepackage[usenames,dvipsnames]{color}

\lstset{backgroundcolor=\color[gray]{0.95},
frame=single,columns=fixed,basicstyle=\ttfamily,
keepspaces=true,showstringspaces=false,numbers=none}

\begin{document}

Here's some regular text.

\begin{lstlisting}[language=R]
summary(cars)
\end{lstlisting}

\begin{lstlisting}
##      speed           dist    
##  Min.   : 4.0   Min.   :  2  
##  1st Qu.:12.0   1st Qu.: 26  
##  Median :15.0   Median : 36  
##  Mean   :15.4   Mean   : 43  
##  3rd Qu.:19.0   3rd Qu.: 56  
##  Max.   :25.0   Max.   :120
\end{lstlisting}

\end{document}

In the output pdf, both of the listings in this example are shaded gray. I'd like to have only one of them shaded, either the language=R block or the other one. I can easily add code to the header with templates, but modifying the individual blocks is not practical for auto-generated documents.

Is there some way to tell listings to apply one colour to an environment with a known language (in this case R), and a different (or no) colour to an environment with no language set?

CLARIFICATION

As the code is generated by other programs, I can't easily modify anything after the '\begin{document }' line. Is there a solution that only modifies the header? I'm trying to avoid manually altering the text after writing the initial .Rmd file.

Follow-up
So far I haven't found a way to do what I need using the built-in features of knitr and pandoc. The closest I've come is post-processing the pandoc-produced tex file to add the style options I need to implement the answer provided by @GonzaloMedina.

#!/bin/bash
fullname=$(basename "$1")
extension="${fullname##*.}"
filename="${fullname%.*}"
pandoc $fullname -o $filename.tex --template=ty --listings
sed -i 's/\\begin{lstlisting}\[language=R\]/\\begin{lstlisting}[language=R,style=myRstyle]/g' $filename.tex
pdflatex $filename.tex

From the command line, running this script as:

convert.sh my-source.md

This appends the style property to all the chunks with the language option set to R. The style itself is defined in ~/.pandoc/templates/ty.latex. The basic layout of that file can be crimped from the output of pandoc -D latex, and should include \lstdefinestyle{myRstyle}{...}, as in Gonzalo's example.

The script continues on to produce the pdf output, so now the problem is mostly solved. It will be less portable than something that uses pandoc or knitr directly, instead of sed, but maybe that's not possible.

Best Answer

With \lstdefinestyle you can define as many styles as you wish; then you can use \lstnewenvironment to define new listing environments using those new styles; in this way you can easily change the styles for your listings as required. You can still use \lstset to set general settings (applicable to all the listings). A simple example:

\documentclass[]{article}
\usepackage{listings}
\usepackage[dvipsnames]{xcolor}

\lstset{                   %<- general settings
  columns=fixed,
  basicstyle=\ttfamily,
  frame=single,
  keepspaces=true,
  showstringspaces=false,
  numbers=none}

\lstdefinestyle{myRstyle}{
  backgroundcolor=\color[gray]{0.95},
}
\lstdefinestyle{mySstyle}{
  backgroundcolor=\color{red!30},
}
\lstnewenvironment{myR}
  {\lstset{language=R,style=myRstyle}}
  {}
\lstnewenvironment{myS}
  {\lstset{language=R,style=mySstyle}}
  {}

\begin{document}

Here's some regular text.

\begin{lstlisting}
##      speed           dist    
##  Min.   : 4.0   Min.   :  2  
##  1st Qu.:12.0   1st Qu.: 26  
##  Median :15.0   Median : 36  
##  Mean   :15.4   Mean   : 43  
##  3rd Qu.:19.0   3rd Qu.: 56  
##  Max.   :25.0   Max.   :120
\end{lstlisting}

\begin{myR}
##      speed           dist    
##  Min.   : 4.0   Min.   :  2  
##  1st Qu.:12.0   1st Qu.: 26  
##  Median :15.0   Median : 36  
##  Mean   :15.4   Mean   : 43  
##  3rd Qu.:19.0   3rd Qu.: 56  
##  Max.   :25.0   Max.   :120
\end{myR}

\begin{myS}
##      speed           dist    
##  Min.   : 4.0   Min.   :  2  
##  1st Qu.:12.0   1st Qu.: 26  
##  Median :15.0   Median : 36  
##  Mean   :15.4   Mean   : 43  
##  3rd Qu.:19.0   3rd Qu.: 56  
##  Max.   :25.0   Max.   :120
\end{myS}

\end{document}

enter image description here

It's better to load xcolor instead of color; the usenames option for xcolor is deprecated and there's no need to use it.