Tim
Tim

Reputation: 79

knitr set Latex definecolor using hooks

TL;DR

I want some latex commands (in this case \definecolor) to change in certain cases, so I want to create the text for these commands in R and have them written to the markup file during markup. I can't yet get it working perfectly using knitr hooks.

More Detail:

The number (and style) of colors I want to define in a .rnw file varies so I am avoiding hard-coding the \definecolor calls in the .rnw document.

It seems like I can do this with knitr hooks, and I'm very close. But I'm confused about a couple of things.

Here's a reproducible example. R file first

library(RColorBrewer)
library(knitr)

colNames <- c("one","two","three")
txtColors <- sub("#","",brewer.pal(6, "Dark2")[1:3])

# set the knitr hook to create color definitions within the rnw file
knitr::knit_hooks$set(setColors = function(before, options, envir) {
  if (!before){
    defs <- vector("list",length(txtColors))
    for(i in 1:length(txtColors)){
      defs[[i]] <- paste0("\\definecolor{",colNames[[i]],"Color}{HTML}{",txtColors[[i]],"}")
    } 
    return(paste0("\\xglobal",unlist(defs), "\n"))
  }   
})

setwd(file.path("G:", "my", "working", "dir"))
knit2pdf("testColors_s.rnw")

and here an rnw file to go with it (name it "testColors_s.rnw")

\documentclass{article}
\usepackage{xcolor}
\begin{document}

<<setColorHook, setColors = TRUE>>=

@

\textcolor{oneColor}{The first color}
\textcolor{twoColor}{The second color}
\textcolor{threeColor}{The third color}

\end{document}

Question #1. I have to set the colors globally with \xglobal because (I guess) that knitr is putting these calls inside a kframe. Can I make a hook that avoids the kframe? Or doesn't require the xglobal call?

Question #2. I get this warning on run: Warning message: Package xcolor Warning: Incompatible color definition on input line 57. This is a color definition done by knitr, not me. Here is the offending line in the tex file:

\definecolor{shadecolor}{rgb}{0.969, 0.969, 0.969}\color{fgcolor}\begin{kframe}

How can I avoid this warning or keep knitr from creating this line?

Any tips on doing any part of this would be greatly appreciated. Thanks in advance.

Upvotes: 0

Views: 240

Answers (1)

Tim
Tim

Reputation: 79

This seems like kind of a hack, but I figured out a solution using the document hook instead of a chunk hook. This fixes both problems (xglobal not longer needed and the extra definecolor is not created). Better solutions are welcome.

Reproducible example, R file:

library(RColorBrewer)
library(knitr)

colNames <- c("one","two","three")
txtColors <- sub("#","",brewer.pal(6, "Dark2")[1:3])

defs <- vector("list",length(txtColors))
for(i in 1:length(txtColors)){
  defs[[i]] <- paste0("\\\\definecolor{",colNames[[i]],"Color}{HTML}{",txtColors[[i]],"}")
} 

knit_hooks$set(document = function(x) {
  sub('%CustomColorDefsHere', paste0(unlist(defs), "\n", collapse = ""), x)
})


setwd(file.path("G:", "my", "working", "dir"))
knit2pdf("testColors_s.rnw")

and the rnw file

\documentclass{article}
\usepackage{xcolor}
%CustomColorDefsHere

\begin{document}

\textcolor{oneColor}{The first color}
\textcolor{twoColor}{The second color}
\textcolor{threeColor}{The third color}

\end{document}

I hope this is useful for someone ...

Upvotes: 1

Related Questions