R functions as knitr chunks
— languageIn writing an R Markdown document to describe a within-host malaria model that I'm working on, I discovered that knitr::read_chunk()
only accepts fixed line numbers and # ---- some-label
marker comments.
So I've implemented read_function_chunks()
, below, which extracts each top-level function as a separate chunk, and supports including roxygen documentation comments.
Note that it identifies top-level functions with simple regular expressions, but as long as the code is well-formatted this works fine.
You can use this to display the code for each function in an R file:
In this example, ./R/utils.R
should define the functions function_name_1()
and function_name_2()
.
Note that underscores are replaced by dashes in the chunk names, so that they will work properly when exporting to PDF via LaTeX.
#' Read top-level functions as chunks into the current knitr session.
#'
#' @param path Path to the R script.
#' @param lines Character vector of lines of code.
#' @param names The function names to read as chunks.
#' By default, all functions are read.
#' @param prefix A prefix for chunk labels.
#' @param roxygen Whether to include roxygen2 comments (if present).
#'
#' @details
#'
#' You can use this in an R Markdown document to display the code for each
#' function in separate code blocks.
#'
#' For example, if the file "my_example.R" contains two functions called
#' "do_one_thing" and "do_another_thing", and you run the following code in
#' your R Markdown document:
#'
#' ```
#' read_function_chunks("my_example.R")
#' ```
#'
#' this will define two chunks called "my-example-do-one-thing" and
#' "my-example-do-another-thing".
#'
#' Note that underscores are replaced by dashes, to avoid issues when
#' exporting to PDF via LaTeX.
{
if () {
# Look for functions defined at the start of a line.
func_rexp <- "^([a-zA-Z0-9_\\.]+) <- function\\("
# Find all matching function definitions.
matches <-
# Extract the name of each function.
names <-
}
if ( != ) {
}
# Identify the start and end line of each function chunk.
chunks <-
# Pass these details on to knitr.
knitr::
}
{
# Find the line on which each function starts.
start_rexps <-
starts <-
if ( != ) {
}
starts <-
# Optionally include roxygen comments above each function.
if (roxygen) {
{
ix <- fn_line - 1
while (ix > 0 && ) {
ix <- ix - 1
}
ix + 1
}
starts <-
}
# Find the line on which each function ends.
end_rexp <- "^}$"
all_ends <-
ends <-
if ( != ) {
}
if () {
}
# Create a label for each function chunk.
if () {
prefix <-
}
labels <-
}