问题
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 ...
回答1:
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:
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:
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.
来源:https://stackoverflow.com/questions/32857212/incorporate-code-listings-from-an-external-file-in-knitr-markdown