1

I'm trying to add latex code surrounding r-markdown (.Rmd) code chunks. I can do this by manually editing the .tex file generated by knitr as follows,

\usepackage{fancyvrb}
\usepackage{xcolor}
\usepackage{changepage}




{
\color{gray}
\footnotesize
\begin{adjustwidth}{2cm}{2cm}
\noindent\rule{1cm}{1.5pt} R code \noindent\rule{8cm}{0.3pt}
\begin{verbatim}

\end{verbatim}
\noindent\rule{8cm}{0.3pt}
\end{adjustwidth}
}

where \begin{verbatim} begins a code chunk that, in turn, ends with \end{verbatim}. I'd like to avoid manually re-coding this latex decoration manually each time I knit.

It appears that I can place the package information in the YAML header of the .Rmd:

---
header-includes:
  - \usepackage{fancyvrb}
  - \usepackage{xcolor}
  - \usepackage{changepage}
---

But I'm not getting the hook setup right. I've tried to modify the hook described here, as follows,

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)

def.chunk.hook  <- knitr::knit_hooks$get("chunk")

knitr::knit_hooks$set(chunk = function(x, options) {
  x <- def.chunk.hook(x, options)
  paste0(
"{\n\\color{gray}\n\\footnotesize\n\\begin{adjustwidth}{1cm}{1cm}\n\\noindent\\rule{1cm}{1.5pt} R code \\noindent\\rule{8cm}{0.3pt}\n",
x,
"\n\n\\noindent\\rule{8cm}{0.3pt}\n\\end{adjustwidth}\n}\n"
  )
}
)
```

which threw an error. Any suggestions appreciated.

UPDATE:

I am able to change R chunk font color, size and indention by adding the following to my YAML header:

header-includes:
  - \usepackage{changepage}
  - \usepackage{xcolor}
  - \usepackage{etoolbox}\BeforeBeginEnvironment{verbatim}{\begingroup\color{gray}\footnotesize\begin{adjustwidth}{.5cm}{.5cm}}\AfterEndEnvironment{verbatim}{\end{adjustwidth}\endgroup}

With that, I think there's no need to use the knitr hook function. Perhaps I've overlooked a cleaner approach, though, which allows me to make whatever mods I like.

ssp3nc3r
  • 3,662
  • 2
  • 13
  • 23

1 Answers1

1

When running from an Rnw, the knir hook is different

> def.chunk.hook
function (x, options) 
{
    ai = output_asis(x, options)
    col = if (!ai) 
        paste0(color_def(options$background), if (!is_tikz_dev(options)) 
            "\\color{fgcolor}")
    k1 = paste0(col, "\\begin{kframe}\n")
    k2 = "\\end{kframe}"
    x = .rm.empty.envir(paste0(k1, x, k2))
    size = if (options$size == "normalsize") 
        ""
    else sprintf("\\%s", options$size)
    if (!ai) 
        x = sprintf("\\begin{knitrout}%s\n%s\n\\end{knitrout}", 
            size, x)
    if (options$split) {
        name = fig_path(".tex", options, NULL)
        if (!file.exists(dirname(name))) 
            dir.create(dirname(name))
        cat(x, file = name)
        sprintf("\\input{%s}", name)
    }
    else x
}
<environment: namespace:knitr>

from that obtained when running Rmd>md>tex(pandoc)

function (x, options) 
{
    x = gsub(paste0("[\n]{2,}(", fence, "|    )"), "\n\n\\1", 
        x)
    x = gsub("[\n]+$", "", x)
    x = gsub("^[\n]+", "\n", x)
    if (isTRUE(options$collapse)) {
        x = gsub(paste0("\n([", fence_char, "]{3,})\n+\\1(", 
            tolower(options$engine), ")?\n"), "\n", x)
    }
    if (is.null(s <- options$indent)) 
        return(x)
    line_prompt(x, prompt = s, continue = s)
}
<environment: 0x000000003777c250>

While the tex file is structured ok

{
\color{gray}
\footnotesize
\begin{adjustwidth}{1cm}{1cm}
\noindent\rule{1cm}{1.5pt} R code \noindent\rule{8cm}{0.3pt}
\begin{knitrout}
\definecolor{shadecolor}{rgb}{0.969, 0.969, 0.969}\color{fgcolor}\begin{kframe}
\begin{alltt}
\hlstd{data} \hlkwb{<-} \hlnum{1}
\end{alltt}
\end{kframe}
\end{knitrout}

\noindent\rule{8cm}{0.3pt}
\end{adjustwidth}
}

And produces some expected output. code decoration the .md is not and will not easily be transfered to pdf (via tex).

{
\color{gray}
\footnotesize
\begin{adjustwidth}{1cm}{1cm}
\noindent\rule{1cm}{1.5pt} R code \noindent\rule{8cm}{0.3pt}

```r
data <- 1
```

\noindent\rule{8cm}{0.3pt}
\end{adjustwidth}

}

Cedric
  • 2,412
  • 17
  • 31
  • It looks like you separate the (Rmd) knitr hook from the tex I'd like to wrap the chunk. How does the function call the tex stuff. Should it be in a separate file and included in the YAML or something else? – ssp3nc3r Nov 28 '17 at 15:03
  • Also, by "not easily be transferred to pdf", do you mean that the solution will not ultimately decorate the chunk correctly when rendered to PDF? Perhaps I'm taking the wrong approach entirely, and I should do something like abandon Rmd in favor of Rnw ... hoping that's not the case because markdown is otherwise so clean for people to work with. – ssp3nc3r Nov 28 '17 at 15:09
  • The hook in rmd will not integrate the right code, so it will not decorate the chunks correctly. I will try to test if integrating the code from the other function (the one produced with .Rnw) works in Rmd. – Cedric Nov 28 '17 at 15:29
  • I've tried to adapt the other function, it does not work. I really think that knitr hooks for latex are meant to be used with .Rnw not .Rmd. Sorry... But I'm not an expert, just tried to help you. You will probably get a confirmation soon from Yihui Xie. Since you are trying to use LATEX code for decoration, perhaps you should switch to producing a LATEX report. It depends if you want to produce other formats as well, which .Rnw does not allow. – Cedric Nov 28 '17 at 16:24