Summary - is there any way for the code run when setting knitr chunk options to know the language of the contained chunk?
Detail:
I have a knitr (in fact Quarto) book in which I have both R and Python chunks, where the Python chunks run via Reticulate.
In fact the R chunks are for an R edition of the book, and the Python chunks for a Python edition.
I'd like to tell knitr to eval=FALSE, echo=FALSE
for the R chunks, when building the Python edition, and vice versa for the Python edition.
Is there a way for me to detect the chunk language at chunk option evaluation time, in order to do something like this?
# My document
```{r, setup, include=FALSE}
is_py_ed <- TRUE # Worked out elsewhere.
is_r_ed <- FALSE # Worked out elsewhere.
knitr::opts_chunk$set(
eval=(this_is_python_chunk & is_py_ed) | (this_is_r_chunk & is_r_ed),
echo=(this_is_python_chunk & is_py_ed) | (this_is_r_chunk & is_r_ed)
)
```
```{python}
# This chunk gets dropped in R edition, kept in Python edition.
```
```{r}
# This chunk gets dropped in Python edition, kept in R edition.
```
You can do this using an option hook and get the current language engine used by knitr to eval and execute the code of the current code chunk using options$engine
(where options
is a list of chunk options passed to the hook functions).
---
title: "Chunk language"
format: html
---
# My document
```{r, setup, include=FALSE}
is_py_ed <- TRUE # Worked out elsewhere.
is_r_ed <- FALSE # Worked out elsewhere.
knitr::opts_chunk$set(echo = "", eval = "")
knitr::opts_hooks$set(
echo = function(options) {
if(!is.logical(options$echo)) {
options$echo <- (options$engine == "python" & is_py_ed) | (options$engine == "R" & is_r_ed)
}
return(options)
},
eval = function(options) {
if(!is.logical(options$eval)) {
options$eval <- (options$engine == "python" & is_py_ed) | (options$engine == "R" & is_r_ed)
}
return(options)
}
)
```
```{python}
print("Hello from python")
```
```{r}
print("Hello from R")
```
```{r, echo=TRUE, eval=TRUE}
print("Hello from R (evaluated in python edition)")
```
Note: As a workaround to enable overriding the chunk option echo
and eval
locally, I have set them to empty strings globally. Then the option hooks will change the values accordingly if they are not set in the chunk header.