Section 15.1 Register a custom language engine (*)
You can register a custom language engine via the method
knitr::knit_engines$set(). It accepts a function as its input, e.g.,
knitr::knit_engines$set(foo = function(options) {
# the source code is in options$code;
# just do whatever you want with it
})
This registers the
foo engine, and you will be able to use a code chunk that starts with ```{foo}.
The engine function has one argument,
options, which is a list of chunk options of the code chunk. You can access the source code of the chunk as a character vector in options$code. For example, for the code chunk:
```{foo}
1 + 1
2 + 2
```
Language engines do not really have to deal with computer languages, but can process any text in a code chunk. First, we show a simple example of an engine that converts the content of a code chunk to uppercase:
knitr::knit_engines$set(upper = function(options) {
code <- paste(options$code, collapse = '\n')
if (options$eval) toupper(code) else code
})
The key is that we apply the function
toupper to the βcodeβ, and return the result as a single character string (by concatenating all lines of code by \n). Note that toupper() is applied only when the chunk option eval = TRUE, otherwise the original string is returned. This shows you how to make use of chunk options like eval inside the engine function. Similarly, you may consider adding if (options$results == 'hide') return() to the function body to hide the output when the chunk option results = 'hide'. Below is an example chunk that uses the upper engine, with its output:
```{upper}
Hello, **knitr** engines!
```
HELLO, **KNITR** ENGINES!
Next we show an example of an alternative Python engine named
β1β
In practice, you should use the built-in
python engine instead, which is based on the reticulate package and supports Python code chunks much better (see SectionΒ 15.2).
py. This engine is implemented by simply calling the python command via the R function system2():
knitr::knit_engines$set(py = function(options) {
code <- paste(options$code, collapse = '\n')
out <- system2(
'python', c('-c', shQuote(code)), stdout = TRUE
)
knitr::engine_output(options, code, out)
})
To fully understand the above engine function, you need to know the following:
-
Given Python code as a character string (
codein the above function), we can execute the code via a command-line callpython -c 'code'. That is whatsystem2()does. We collect the (text) output by specifyingstdout = TRUEinsystem2(). -
You can pass the chunk options, source code, and text output to the function
knitr::engine_output()to generate the final output. This function deals with common chunk options likeecho = FALSEandresults = 'hide', so you do not need to take care of these cases.
A lot of language engines in knitr are defined in this way (i.e., using
system2() to execute commands corresponding to languages). If you are curious about the technical details, you may check out the source code of most language engines in the R source code here: https://github.com/yihui/knitr/blob/master/R/engine.R.
Now we can use the new engine
py, e.g.,
```{py}
print(1 + 1)
```
2
You can even override existing language engines in knitr via
knitr::knit_engines$set(), if you are sure that your versions are necessary or better than the existing ones. Usually we do not recommend that you do this because it may surprise users who are familiar with existing engines, but we want to make you aware of this possibility anyway.
