roxygen2 provides several ways to avoid repeating yourself in code documentation, while assembling information from multiple places in one documentation file:
Combine documentation for closely related functions into a single
file with @describe
in or @rdname
.
Inherit components from another topic with
@inheritParams
, @inheritSection
, or
@inherit
.
Use functions to generate repeated text with inline R code.
Share text between documentation and vignettes with child documents.
The chapter concludes by showing you how to update superseded reuse
mechanisms that we no longer recommend: @includeRmd
,
@eval
/@evalRd
, and @template
.
You can document multiple functions in the same file by using either
@rdname
or @describeIn
tag. It’s a technique
best used with care: documenting too many functions in one place leads
to confusion. Use it when all functions have the same (or very similar)
arguments.
@describeIn
Use @describeIn <destination> <description>
to document mutiple functions together. It generates a new section named
“Related functions and methods”, further divided into
subsections by the type of relationship between the source and the
destination documentation. Each subsection contains a bulleted list
describing the function with the specified
<description>
.
You can document several functions which perform slight variations of a task or which use different defaults in one documentation file:
#' Power
#' @param x base
#' @param exp exponent
<- function(x, exp) x ^ exp
power
#' @describeIn power Square a number
<- function(x) power(x, 2)
square
#' @describeIn power Cube a number
<- function(x) power(x, 3) cube
In this case, both destination and source are “normal” functions, and
you can use <description>
to explain their
differences.
@describeIn
is also well suited to explain the
relationships between functions making up an object oriented (OO) scheme
using S3 or S4. In this case, roxygen will automatically detect whether
a source function is a method and document the relationship to the
relevant class or generic. Your new methods will be organised in one of
two ways:
If your new method extends a generic in the
<destination>
, it will be listed in a section titled
“Methods for generic <destination>
”.
The subsection will include all methods for your new generic, labelled
by the class they cover.
If your new method extends another generic, for a class
constructed in the destination, it will be listed in a subsection titled
“Methods for class <destination>
”.
It will be labelled by the generic which the method extends.
While you can mix and match (some) different types of functions with
@describeIn
, the output may quickly become disorienting for
users if the functions are not tightly related.
By default, roxygen blocks are processed in the order in which they
appear in the file. When you’re combining multiple files, this can
sometimes cause the function usage to appear in a suboptimal order. You
can override the default ordering with @order
. For example,
the following the block would place times
first in
arith.Rd
because 1 comes before 2.
#' @rdname arith
#' @order 2
<- function(x, y) x + y
add
#' @rdname arith
#' @order 1
<- function(x, y) x * y times
You can inherit documentation from other topics in a few ways:
@inheritParams source_function
inherits just the
parameter documentation from source_function()
.
@inherit source_function
will inherit all supported
components from source_function
.
Alternatively, you can use (e.g.)
@inherit source_function return details
to just inherit the
return value and details from source_function()
. Supported
components are params
, return
,
title
, description
, details
,
seealso
, sections
, references
,
examples
, author
, source
,
note
.
@inheritSection source_function Section title
will
inherit the single @section
called “Section title” from
source_function()
.
@inheritDotParams
automatically generates parameter
documentation for ...
for the common case where you pass
...
on to another function. Because you often override some
arguments, it comes with a flexible specification for argument
selection:
@inheritDotParams foo
takes all parameters from
foo()
@inheritDotParams foo a b e:h
takes parameters
a
, b
, and all parameters between
e
and h
@inheritDotParams foo -x -y
takes all parameters except
for x
and y
.All of these tags also work to inherit documentation from functions
in another package by using pkg::source_function
.
To insert code inline, enclose it in `r `
. Roxygen will
interpret the rest of the text within backticks as R code and evaluate
it, and replace the backtick expression with its value. Here’s a simple
example:
#' Title `r 1 + 1`
#'
#' Description `r 2 + 2`
<- function() NULL foo
This is equivalent to writing:
#' Title 2
#'
#' Description 4
<- function() NULL foo
The resulting text, together with the whole tag is interpreted as markdown, as usual. This means that you can use R to dynamically write markdown. For example if you defined this function in your package:
<- function(n) {
alphabet paste0("`", letters[1:n], "`", collapse = ", ")
}
You could then write:
#' Title
#'
#' @param x A string. Must be one of `r alphabet(5)`
<- function(x) NULL foo
The result is equivalent to writing the following by hand:
#' Title
#'
#' @param x A string. Must be one of `a`, `b`, `c`, `d`, `e`
<- function(x) NULL foo
This is a powerful technique for reducing duplication because you can flexibly parameterise the function however best meets your needs. Note that the evaluation environment is deliberately a child of the package that you’re documenting so you can call internal functions.
You can use the same .Rmd
or .md
document
in the documentation, README.Rmd
, and vignettes but using
child documents:
```{r child = "common.Rmd"}
```
The included Rmd file can have roxygen Markdown-style links to other
help topics. E.g. [roxygen2::roxygenize()]
will link to the
manual page of the roxygenize
function in roxygen2. See
vignette("rd-formatting")
for details.
If the Rmd file contains roxygen (Markdown-style) links to other help topics, then some care is needed, as those links will not work in Rmd files by default. A workaround is to specify external HTML links for them. These external locations will not be used for the manual which instead always links to the help topics in the manual. Example:
See also the [roxygen2::roxygenize()] function.
[roxygen2::roxygenize()]: https://roxygen2.r-lib.org/reference/roxygenize.html
This example will link to the supplied URLs in HTML / Markdown files
and it will link to the roxygenize
help topic in the
manual.
Note that if you add external link targets like these, then roxygen will emit a warning about these link references being defined multiple times (once externally, and once to the help topic). This warning originates in Pandoc, and it is harmless.
Over the years, we have experimented with a number of other ways to reduce duplication across documentation files. A number of these are now superseded and we recommend changing them to use the techniques described above:
Instead of @includeRmd man/rmd/example.Rmd
, use a
child document.
Instead of @eval
or @evalRd
, use inline
R code.
Instead of @template
and @templateVars
write your own function and call it from inline R code.
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.