I have numerous similar functions where only one or two words need to change in the documentation. To limit duplication, I'm using functions inside the documentation.
This works in roxygen2 for @description
and @param
, but I cannot get it to work for @examples
. The inline code is not evaluated.
useless_description <- function(name) {
paste0('This useless function prints the word "', name , '" n times.')
}
useless_example <- function(name) {
paste("# Print ", name, " 1 time",
name, "(1)",
"",
"# Print ", name, " 3 times",
name, "(3)",
sep = "\n"
)
}
#' @title Hello
#' @description `r useless_description("hello")`
#' @examples `r useless_example("hello")`
hello <- function(n) {
print(rep("hello", n))
}
#' @title Goodbye
#' @description `r useless_description("goodbye")`
#' @examples `r useless_example("hello")`
goodbye <- function(n) {
print(rep("goodbye", n))
}
When running devtools::document()
, this is the help page that is created for the function hello()
:
@eval
I have found a way around this, but it uses the superseded keyword @eval
.
useless_example2 <- function(name) {
c("@examples ",
paste0("# Print ", name, " 1 time"),
paste0(name, "(1)"),
"",
paste0("# Print ", name, " 3 time"),
paste0(name, "(3)")
)
}
#' @title Hello
#' @description `r useless_description("hello")`
#' @eval useless_example2("hello")
hello <- function(n) {
print(rep("hello", n))
}
Resulting help page:
Is there a way to evaluate inline code in roxygen2 @examples
without using superseded functions?
First note that the use of inline code with {Roxygen2} only works if markdown support is turned on. That is accomplished either:
Roxygen: list(markdown = TRUE)
into the package DESCRIPTION file (e.g., usethis::use_roxygen_md()
) or@md
in the present roxygen blockAs you noted, the use of @eval
has been superseded in favor of inline R code.
On that same page, the authors go on to say:
Inline R markdown can only generate markdown text within a tag so in principle it is less flexible than @eval/@evalRd/@template. However, our experience has revealed that generating multiple tags at once tends to be rather inflexible, and you often end up refactoring into smaller pieces so we don’t believe this reflects a real loss of functionality.
I see two points worth repeating:
Then on this page the authors note that:
Some of the roxygen tags are not parsed as markdown. Most of these are unlikely to contain text that needs markup, so this is not an important restriction. Tags without markdown support: @aliases, @backref, @docType, @encoding, @evalRd, @example, @examples, @family, @inheritParams, @keywords, @method @name, @md, @noMd, @noRd, @rdname, @rawRd, @usage.
This is why your inline code works for the @description
, but does not work for @examples
as the package authors have explicitly decided not to support inline code for @examples
.
If you wish to follow along with the package authors' intent and not use deprecated functionality, I suggest you extend {roxygen2} with your own custom tag. You can even make it so that your tag simply adds to the already existing examples section.
While there would be kinks to work out, adding your own custom tag can be as simple as defining two functions like this:
roxy_tag_parse.roxy_tag_examples2 <- function(x) {
roxygen2::tag_markdown(x)
}
roxy_tag_rd.roxy_tag_examples2 <- function(x, base_path, env) {
roxygen2::rd_section("examples", x$val)
}
Then load these functions into memory before documenting your package.
Here is an example R package file:
roxygen_generate_description <- function(x) {
sprintf('This function prints the word "%s" n times.', x)
}
# a kink to workout:
# - use \u0023 for # to avoid an attempt at a level 1 header
roxygen_generate_examples <- function(x) {
paste(
sprintf("\u0023 Print %s 1 time", x),
sprintf("%s(1)", x),
"",
sprintf("\u0023 Print %s 3 times", x),
sprintf("%s(3)", x),
sep = "\n"
)
}
#' @title Hello
#' @description `r roxygen_generate_description("hello")`
#' @examples2 `r roxygen_generate_examples("hello")`
hello <- function(n) {
print(rep("hello", n))
}
And then doing:
devtools::document()
?hello
We get this: