Introduction
Code documentation is extremely important if you want to share the code with anyone else, future you included. In this second post in the RStudio:addins series we will pay a part of our technical debt from the previous article and document our R functions conveniently using a new addin we will build for this purpose.
The addin we will create in this article will let us create well formatted roxygen documentation easily by using keyboard shortcuts to add useful tags such as
\code{}
or\link{}
around selected text in RStudio.
Contents
Quick intro to documentation with roxygen2
1. Documenting your first function
To help us generate documentation easily we will be using the roxygen2 package. You can install it using install.packages("roxygen2")
. Roxygen2 works with in-code tags and will generate R’s documentation format .Rd
files, create a NAMESPACE
, and manage the Collate
field in DESCRIPTION
(not relevant to us at this point) automatically for our package.
Documenting a function works in 2 simple steps:
- Inserting a skeleton - Do this by placing your cursor anywhere in the function you want to document and click
Code Tools -> Insert Roxygen Skeleton
(default keyboard shortcutCtrl+Shift+Alt+R
). - Populating the skeleton with relevant information. A few important tags are:
#' @params
- describing the arguments of the function#' @return
- describing what the function returns#' @importFrom package function
- in case your function uses a function from a different package Roxygen will automatically add it to theNAMESPACE
#' @export
- if case you want the function to be exported (mainly for use by other packages)#' @examples
- showing how to use the function in practice
2. Generating and viewing the documentation
- We generate the documentation files using
roxygen2::roxygenise()
ordevtools::document()
(default keyboard shortcutCtrl+Shift+D
) - Re-installing the package (default keyboard shortcut
Ctrl+Shift+B
) - Viewing the documentation for a function using
?functioname
e.g.?mean
, or placing cursor on a function name and pressingF1
in RStudio - this will open theViewer
pane with the help for that function
3. A real-life example
Let us now document runCurrentRscript
a little bit:
#' runCurrentRscript
#' @description Wrapper around executeCmd with default arguments for easy use as an RStudio addin
#' @param path character(1) string, specifying the path of the file to be used as Rscript argument (ideally a path to an R script)
#' @param outputFile character(1) string, specifying the name of the file, into which the output produced by running the Rscript will be written
#' @param suffix character(1) string, specifying additional suffix to pass to the command
#' @importFrom rstudioapi getActiveDocumentContext
#' @importFrom rstudioapi navigateToFile
#' @seealso executeCmd
#' @return side-effects
runCurrentRscript <- function(
path = replaceTilde(rstudioapi::getActiveDocumentContext()[["path"]])
, outputFile = "output.txt"
, suffix = "2>&1") {
cmd <- makeCmd(path, outputFile = outputFile, suffix = suffix)
executeCmd(cmd)
if (!is.null(outputFile) && file.exists(outputFile)) {
rstudioapi::navigateToFile(outputFile)
}
}
As we can see by looking at ?runCurrentRscript
versus ?mean
, our documentation does not quite look up to par with documentation for other functions:
What is missing if we abstract from the richness of the content is the usage of markup commands (tags) for formatting and linking our documentation. Some of the very useful such tags are for example:
\code{}
,\strong{}
,\emph{}
for font style\link{}
,\href{}
,\url{}
for linking to other parts of the documentation or external resources\enumerate{}
,\itemize{}
,\tabular{}
for using lists and tables\eqn{}
,\deqn{}
for mathematical expressions such as equations etc.
For the full list of options regarding text formatting, linking and more see Writing R Extensions’ Rd format chapter
Our addins to make documenting a breeze
As you can imagine, typing the markup commands in full all the time is quite tedious. The goal of our new addin will therefore be to make this process efficient using keyboard shortcuts - just select a text and our addin will place the desired tags around it. For this time, we will be satisfied with simple 1 line tags.
1. Add a selected tag around a character string
roxyfy <- function(str, tag = NULL, splitLines = TRUE) {
if (is.null(tag)) {
return(str)
}
if (!isTRUE(splitLines)) {
return(paste0("\\", tag, "{", str, "}"))
}
str <- unlist(strsplit(str, "\n"))
str <- paste0("\\", tag, "{", str, "}")
paste(str, collapse = "\n")
}
2. Apply the tag on a selection in an active document in RStudio
We will make the functionality available for multi-selections as well by lapply-ing
over the selection
elements retrieved from the active document in RStudio.
addRoxytag <- function(tag = NULL) {
context <- rstudioapi::getActiveDocumentContext()
lapply(X = context[["selection"]]
, FUN = function(thisSel, contextid) {
rstudioapi::modifyRange(location = thisSel[["range"]]
, roxyfy(thisSel[["text"]], tag)
, id = contextid)
}
, contextid = context[["id"]]
)
return(invisible(NULL))
}
4. Add the addin bindings into addins.dcf
and assign keyboard shortcuts
As the final step, we need to add the bindings for our new addins to the inst/rstudio/addins.dcf
file and re-install the package.
Name: addRoxytagCode
Description: Adds roxgen tag code to current selections in the active RStudio document
Binding: addRoxytagCode
Interactive: false
Name: addRoxytagLink
Description: Adds roxgen tag link to current selections in the active RStudio document
Binding: addRoxytagLink
Interactive: false
Name: addRoxytagEqn
Description: Adds roxgen tag eqn to current selections in the active RStudio document
Binding: addRoxytagEqn
Interactive: false
The addins in action
And now, let’s just select the text we want to format and watch our addins do the work for us! Then document the package, re-install it and view the improved help for our functions:
What is next - even more automated documentation
Next time we will try to enrich our addins for generating documentation by adding the following functionalities
- automatic generation of
@importFrom
tags by inspecting the function code - allowing for more complex tags such as
itemize
TL;DR - Just give me the package
- Get the status of the package after this article
- or use
git clone
fromhttps://gitlab.com/jozefhajnala/jhaddins.git