Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

incorporate code listings from an external file in knitr/markdown

I would like to incorporate listings of code drawn from external files in an Rmarkdown file. I would like it pretty (syntax highlighting, auto-indentation, etc.).

  • The code is not R code (otherwise I could use some of the existing tricks to pretty-print R functions) - specifically, it's BUGS and Stan code.
  • I'm not necessarily targeting LaTeX/PDF output: otherwise I could use the listings package.
  • I'd like to be able to incorporate the files without an unwieldy external cat firstpart.rmd codefile.rmd lastpart.rmd >wholefile.rmd system command, and without a pre-processing step: this question suggests that Markdown processors like Multimarkdown and Marked 2 have file inclusion syntax, but I think I'm stuck with pandoc.
  • At present I'm using code chunks like this
```{r jagsmodel, echo=FALSE, results="markup", comment=""}
cat(readLines("logist.bug"),sep="\n")
```

which works OK but doesn't get me syntax highlighting ...

like image 308
Ben Bolker Avatar asked Sep 30 '15 03:09

Ben Bolker


People also ask

How do I embed a link in R Markdown?

Hyperlinks are created using the syntax [text](link) , e.g., [RStudio](https://www.rstudio.com) . The syntax for images is similar: just add an exclamation mark, e.g., ![ alt text or image title](path/to/image) .


1 Answers

Here's one approach. You need pygments installed (pip install pygments) and it has to be able to put (it should on it's own) "pygmentize somewhere on your system. If you don't have python or can't install that module, then this answer is obviously not going to be an answer for you.

The following knitr chunks (all but the last one which is pure R) call pygmentize to create HTML markup for the code. It should be possible to modify https://github.com/hrbrmstr/knitrengines to make this more "automagical" but that's not on my short-term TODO.

---
title: "lexers"
output: 
  html_document:
    css: code.css
    keep_md: true
---

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

### Bugs

```{r bugs1, echo=FALSE, results="asis"}
tf <- tempfile(fileext=".html")
system(sprintf("/usr/local/bin/pygmentize -o %s incl.bug", tf))
cat(readLines(tf), sep="\n")
unlink(tf)
```

### Elixir

```{r elixir1, echo=FALSE, results="asis"}
tf <- tempfile(fileext=".html")
system(sprintf("/usr/local/bin/pygmentize -o %s incl.ex", tf))
cat(readLines(tf), sep="\n")
unlink(tf)
```

### Python

```{r py1, echo=FALSE, results="asis"}
tf <- tempfile(fileext=".html")
system(sprintf("/usr/local/bin/pygmentize -o %s incl.py", tf))
cat(readLines(tf), sep="\n")
unlink(tf)
```

### Plain ol' R

```{r}
summary(mtcars)
```

That makes:

enter image description here

You can use any pygments CSS file you like for a different scheme, this is what's in code.css:

<style>
.gl .hll { background-color: #ffffcc }
.highlight  { background: #f8f8f8; }
.highlight .c { color: #408080; font-style: italic } /* Comment */
.highlight .err { border: 1px solid #FF0000 } /* Error */
.highlight .k { color: #008000; font-weight: bold } /* Keyword */
.highlight .o { color: #666666 } /* Operator */
.highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */
.highlight .cp { color: #BC7A00 } /* Comment.Preproc */
.highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */
.highlight .cs { color: #408080; font-style: italic } /* Comment.Special */
.highlight .gd { color: #A00000 } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #FF0000 } /* Generic.Error */
.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
.highlight .gi { color: #00A000 } /* Generic.Inserted */
.highlight .go { color: #808080 } /* Generic.Output */
.highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
.highlight .gt { color: #0040D0 } /* Generic.Traceback */
.highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008000 } /* Keyword.Pseudo */
.highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #B00040 } /* Keyword.Type */
.highlight .m { color: #666666 } /* Literal.Number */
.highlight .s { color: #BA2121 } /* Literal.String */
.highlight .na { color: #7D9029 } /* Name.Attribute */
.highlight .nb { color: #008000 } /* Name.Builtin */
.highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */
.highlight .no { color: #880000 } /* Name.Constant */
.highlight .nd { color: #AA22FF } /* Name.Decorator */
.highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */
.highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0000FF } /* Name.Function */
.highlight .nl { color: #A0A000 } /* Name.Label */
.highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
.highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #19177C } /* Name.Variable */
.highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mf { color: #666666 } /* Literal.Number.Float */
.highlight .mh { color: #666666 } /* Literal.Number.Hex */
.highlight .mi { color: #666666 } /* Literal.Number.Integer */
.highlight .mo { color: #666666 } /* Literal.Number.Oct */
.highlight .sb { color: #BA2121 } /* Literal.String.Backtick */
.highlight .sc { color: #BA2121 } /* Literal.String.Char */
.highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
.highlight .s2 { color: #BA2121 } /* Literal.String.Double */
.highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
.highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */
.highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
.highlight .sx { color: #008000 } /* Literal.String.Other */
.highlight .sr { color: #BB6688 } /* Literal.String.Regex */
.highlight .s1 { color: #BA2121 } /* Literal.String.Single */
.highlight .ss { color: #19177C } /* Literal.String.Symbol */
.highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */
.highlight .vc { color: #19177C } /* Name.Variable.Class */
.highlight .vg { color: #19177C } /* Name.Variable.Global */
.highlight .vi { color: #19177C } /* Name.Variable.Instance */
.highlight .il { color: #666666 } /* Literal.Number.Integer.Long */
</style>
#

UPDATE

If you're willing to put the code (that won't get executed but will get formatted) inline, I just made an update to the aforementioned knitrengines package that lets you do this:

---
title: "pygtest"
output: html_document
---

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

```{pygments test, pyg.ext="py", pyg.sty="github"}
import something.please

print("Hello, world!")
```

```{pygments test2, pyg.ext="go", pyg.sty="github"}
package main

import "fmt"

func main() {

    s := make([]string, 3)
    fmt.Println("emp:", s)

    s[0] = "a"
    s[1] = "b"
    s[2] = "c"
    twoD := make([][]int, 3)
    for i := 0; i < 3; i++ {
        innerLen := i + 1
        twoD[i] = make([]int, innerLen)
        for j := 0; j < innerLen; j++ {
            twoD[i][j] = i + j
        }
    }
    fmt.Println("2d: ", twoD)
}
```

```{pygments test3, pyg.ext="ex", pyg.sty="github"}
defmodule Math do
  def sum(a, b) do
    a + b
  end
end

IO.puts "The answer is #{ Math.sum(4,3) }"    
```

and produces this:

enter image description here

I can make it use different styles per code block, but I barely had cycles to crank this out. It shouldn't be too much work tho.

like image 106
hrbrmstr Avatar answered Sep 21 '22 02:09

hrbrmstr