Reputation: 6302
I am using .Rnw files to produce a report with LaTeX and knitr.
My knitr_setup
looks as follows:
<<knitr_setup, echo=FALSE>>=
library(knitr)
opts_chunk$set(highlight = TRUE, cache = TRUE, eval = FALSE, size = "small")
options(width = 60)
opts_knit$set(out.format = "latex")
@
<<theme, cache=FALSE, echo=FALSE>>=
thm = knit_theme$get("olive")
knit_theme$set(thm)
@
I tested several syntax highlighting themes. Previews are provided here.
However, changing the themes in knit_theme$get()
only results in a different background (for some) in the final pdf. Syntax highlighting stays with the default colors.
R-Version: 3.3.1
RStudio Version: 0.99.1280 (Preview)
knitr-Version: 1.13
What is wrong in my setup?
Upvotes: 2
Views: 734
Reputation: 14957
The problem: You have a document with several calls to knit_theme$set()
and expect syntax highlighting to change accordingly, on a per-chunk basis.
Syntax highlighting stays with the default colors.
Each call to knit_theme$set()
supersedes the previous call. This is because the colors for syntax highlighting are defined just once, in the LaTeX preamble (e.g. \newcommand{\hlnum}[1]{\textcolor[rgb]{0.529,0.875,0.443}{#1}}
).
However, changing the themes in knit_theme$get() only results in a different background (for some) in the final pdf.
Unlike highlighting of keywords, the background color is defined for each chunk (look for \definecolor{shadecolor}{rgb}{0.961, 0.961, 0.961}
). (Exception: Chunks with results = "asis"
.)
The solution (concept):
Using \renewcommand
, the syntax highlighting commands can be "updated" mid-document. We can therefore set a new theme, extract its syntax highlighting definitions, replace newcommand
by renewcommand
and write the definitions to the document. All subsequent chunks will use the new theme.
At the end of the document, restore the default theme; otherwise, all chunks before the first change of theme will use the last theme set.
Implementation:
setThemeInline <- function(theme) {
knit_theme$set(knit_theme$get(theme))
header <- opts_knit$get("header")["highlight"]
header <- gsub(pattern = "newcommand",
replacement = "renewcommand",
x = header)
cat(header)
}
Usage:
Note that setThemeInline
must be called in an asis
chunk. Don't forget to restore the theme (see last chunk). Only chunks after the chunk where setThemeInline
was called will be affected.
\documentclass{article}
\begin{document}
<<setup>>=
library(knitr)
setThemeInline <- function(theme) {
knit_theme$set(knit_theme$get(theme))
header <- opts_knit$get("header")["highlight"]
header <- gsub(pattern = "newcommand",
replacement = "renewcommand",
x = header)
cat(header)
# for chunks with results = "asis"
shadecolor <- col2rgb(opts_chunk$get("background")) / 255
cat(sprintf("\\definecolor{shadecolor}{rgb}{%s, %s, %s}",
shadecolor[1, 1], shadecolor[2, 1], shadecolor[3, 1]))
}
@
<<theme, results='asis'>>=
setThemeInline("denim")
@
<<>>=
getAnswer <- function(question) {
if (missing(question)) {
stop("Ask something!")
}
return(42)
}
@
<<results='asis'>>=
setThemeInline("vampire")
@
<<>>=
getAnswer <- function(question) {
if (missing(question)) {
stop("Ask something!")
}
return(42)
}
@
<<restore>>=
knit_theme$set(knit_theme$get("default"))
@
\end{document}
Output:
Upvotes: 2