Roxygen comments involve prefixing lines with #'.
When writing and testing examples for functions, it's nice to be able to toggle the comments on and off. I could copy and paste the code back and forward to vim and remove or add those comments, but that's not very elegant.
Is there any easy way to toggle roxygen comments in Rstudio?
Alternatively, is there another way to efficiently run example R code that is commented out by roxygen comment characters?
Update: Thinking laterally, I suppose using #example examples/foo.r is an alternative way of avoiding having to use Roxygen comments for the actual example code (i.e., by sourcing the example from a file, i.e., examples/foo.r).
With respect to your proposed alternative:
Alternatively, is there another way to efficiently run example R code that is commented out by roxygen comment characters?
If you press CTRL+[Enter] within a Roxygen2 #examples block, Rstudio will send the selected code (line or highlighted section) to the R console. To use just declare the #examples code block on a line preceding your roxygen commented code.
#' #examples
#' ... your original roxygen commented code ...
You can put an #examples block anywhere in your code. This becomes a drag if you are developing a package and you are using the block for its intended purpose.
If you are looking for a way to toggle code, I would use the approach proposed by #Roman in in the comments to your question.
You can write your own function that extract example code from your R file. This is analogous to purl in knit package or Stangle. Here an example of what you can do. The function is not efficient but I write it just to show the idea. It should be a good start point. It assumes also that you already source your R file or at least that the documented function already exist in the R session.
purl.examples <- function(fileName){
ll <- readLines(fileName)
ex.lines <- grep('#examples',ll) ## get the example's lines
## for each example loop till
## there is no comment (inefficient)
examples <- lapply(ex.lines , function(x){
i <- x+1
code <- list()
while(grepl("#'",ll[i])){
l <- c(code,gsub("#'","",ll[i],fixed=TRUE))
i <- i+1
}
code
})
}
Then you can call it like this for example:
lapply(purl.examples('code.R'),
function(ex) eval(parse(text=ex))) ## safer to use evaluate package here
Related
The standard way of writing documentation with code formatting is by using \code{}.
That is, #' #param foo value passed on to \code{bar()} becomes
Arguments
foo value passed on to bar()
However, I've seen some packages (i.e. dplyr) using backticks instead of \code{} to the same effect. This is much better, since it's less clunky and allows for very nice syntax highlighting.
However, if I try that on my own package, the backticks get interpreted as... just backticks, like any other character.
The documentation for dplyr::across(), for example, starts with:
#' #description
#' `across()` makes it easy to apply the same transformation to multiple [...]
which gets compiled and displayed in the man page as:
Description
across() makes it easy to apply the same transformation to multiple [...]
But if I try something similar on my package, I get:
Description
`across()` makes it easy to apply the same transformation to multiple [...]
Weirdly, I've forked the package glue (which also manages to use backticks for code formatting) for a simple PR, and if I build the package locally, the backticks work (I get code formatting). Can't for the life of me figure out why it works there but not for my package.
So, is there some setting I need to modify to get this to work? I checked the dplyr.Rproj but found nothing relevant. I also glanced at the Doxyfile, but didn't know what it did or what I'd even be looking for there.
All credit goes to #rawr's comment to the question, just formalizing it with an answer:
The secret is in the roxygen2 documentation: just add the following to the end of the package DESCRIPTION file:
# DESCRIPTION file
# [... rest of file ...]
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.1.2 # actually works since 6.0.0
As that code would imply, this sets roxygen2 to interpret the commands as good ol' Markdown like we're used to using here on SO and elsewhere. This also implies all the other standard Markdown commands such as **bold** and *italics*, as well as [text](http://www.url.com), code blocks defined by ```, itemized and enumerated lists, etc. It's a huge improvement across the board.
Though be careful and take a look at the documentation, since there are a few gotchas. For instance, an empty line isn't necessary to start lists, so don't start any lines with #' 1. [...] or #' * [...] or you'll accidentally create a list!). There's also a few things which don't work yet, but they're pretty minor.
Following your recommendations (or trying to do it, at least), I have tried some options, but the problem remains, so there must be something I am missing.
I have included a more complete code
setwd("C:/naapp")
#' #import utils
#' #import devtools
I have tried with and without using suppressForeignCheck
if(getRversion() >= "2.15.1"){
utils::globalVariables(c("eleven"))
utils::suppressForeignCheck(c("eleven"))
}
myFunctionSum <- function(X){print(X+eleven)}
myFunctionMul <- function(X){print(X*eleven)}
myFunction11 <- function(X){
assign("eleven",11,envir=environment(myFunctionMul))
}
maybe I should use a particular environment?
package.skeleton(name = "myPack11", list=ls(),
path = "C:/naapp", force = TRUE,
code_files = character())
I remove the "man" directory from the directory myPack11,
otherwise I would get an error because the help files are empty.
I add the imports utils, and devtools to the descrption
Then I run check
devtools::check("myPack11")
And I still get this note
#checking R code for possible problems ... NOTE
#myFunctionMul: no visible binding for global variable 'eleven'
#myFunctionSum: no visible binding for global variable 'eleven'
#Undefined global functions or variables:eleven
I have tried also to make an enviroment, combining Tomas Kalibera's suggetion and an example I found in the Internet.
myEnvir <- new.env()
myEnvir$eleven <- 11
etc
In this case, I get the same note, but with "myEnvir", instead of "eleven"
First version of the question
I trying to use "globalVariables" from the package utils. I am building an interface in R and I am planning to submit to CRAN. This is my first time, so, sorry if the question is very basic.I have read the help and I have tried to find examples, but I still don't know how to use it.
I have made a little silly example to ilustrate my question, which is:
Where do I have to place this line exactly?:
if(getRversion() >= "2.15.1"){utils::globalVariables("eleven")}
My example has three functions. myFunction11 creates the global variable "eleven" and the other two functions manipulate it. In my real code, I cannot use arguments in the functions that are called by means of a button. Consider that this is just a silly example to learn how to use globalVariables (to avoid binding notes).
myFunction11 <- function(){
assign("eleven",11,envir=environment(myFunctionSum))
}
myFunctionSum <- function(X){
print(X+eleven)
}
myFunctionMul <- function(X){
print(X*eleven)
}
Thank you in advance
I thought that the file globals.R would be automatically generated when using globalsVariables. The problem was that I needed to create the package skeleton, then create the file globals.R, add it to the R directory in the package and check the package.
So, I needed to place this in a different file:
#' #import utils
utils::globalVariables(c("eleven"))
and save it
The documentation clearly says:
## In the same source file (to remind you that you did it) add:
if(getRversion() >= "2.15.1") utils::globalVariables(c(".obj1", "obj2"))
so put it in the same source file as your functions. It can go in any of your R source files, but the comment above recommends you put it close to your code. Looking at a bunch of github packages reveals another common pattern is to have a globals.R function with it in, but this is probably a bad idea. If you later remove the global from your package but neglect to update globals.R you could mask a problem. Putting it right close to the functions that use it will hopefully remind you when you edit those functions.
Make sure you put it outside any function definitions in the file, or it won't get seen.
You cannot modify bindings in a package namespace once the package is loaded (and namespace sealed, and bindings locked). The check tool helps you to spot violations of this restriction, so you find out about the problem when checking the package rather than while running it. globalVariables is just a call to silence check when looking for these violations, which is undesirable in almost all cases. If you really need mutable state in a package, you can create a new environment (using new.env) and bind it to an (unexported) "global" variable in your namespace. This binding will be locked, but this is ok, because in R you can change an environment in place (add/remove elements, effectively modifying the elements).
The best situation is however when you can keep all mutable state in user objects (passed in as arguments into functions, and their modified versions returned as output values of functions).
I'm looking into R Markdown for documenting functions I regularly use. I will put them into an R Markdown file to document them and then be able to read my thinking behind the function if i come back to it months later
My question is, if i start a new R project, Is it possible to source the r markdown file and use the library of functions i have created just by calling them similarly to if i was sourcing a regular R file. I dont really wish to maintain two sets of function files
I appreciate this may be a beginners question but any help pointing to tutorials and the like would be greatly appreciated
Thanks
As was mentioned in the comments, you should probably create a package for this purpose. But if you insist on putting function definitions in scripts and document them using RMarkdown files, using read_chunk() from the knitr package might be the way to go.
Note that this approach differs slightly from what you requested. You wanted to have the function definition in the markdown file together with the documentation. And then you wanted to somehow source that file into your R script in order to use the function. I did not find a way to do this (even though it might be possible).
The alternative that I propose puts the function definition in its own R script, say fun.R. The Rmarkdown file then reads the function definition from fun.R and adds documentation. If you want to use the function in some other script, you can simply source fun.R (and not the markdown file). This still means that you have to maintain the code for the function definition only once.
So let me show this with an example. This is fun.R:
## ---- fun
fun <- function(x) x^2
The first line is an identifier that will be used later. The markdown file is as follows:
---
title: "Documentation of fun()"
output: html_document
---
This documents the function `fun()` defined in `fun.R`.
```{r,cache = FALSE}
knitr::read_chunk("fun.R")
```
This is the function definition
```{r fun}
```
This is an example of how to use `fun()`:
```{r use_fun}
fun(3)
```
The first chunk reads in fun.R using knitr::read_chunk. Later on, you can define an empty chunk that has the identifier that was used in fun.R as its name. This will act as if the contents of fun.R were written directly in this file. As you see, you can also use fun() in later chunks. This is a screenshot of the resulting html file:
In a script where you want to use fun() you simply add source("fun.R") to source the function definition.
You could also have several functions in a single R file and still document them separately. Simply put an identifier starting with ## ---- before each function definition and then create empty chunks referring to each one of the identifiers.
This is admittedly somewhat more complicated than what you asked for, because it involves two files instead of just one. But at least there is no redundancy
The klmr/modules package has been superseded by the box package by the same author. It is on CRAN. After the cat command below run these lines to display the roxygen2 help for add2.
box::use(./test)
box::help(test$add2)
Perhaps this is close enough -- you can use the github klmr/modules package (not the CRAN modules package) to combine roxygen2 documentation and code in a single file without creating a package. For example, after installing the modules package copy this to the clipboard and then paste it into the R console to create a single file module with embedded documentation. The subsequent code then imports it, runs a function from it and invokes help. See the documentation of the modules package for more info.
Note that this has the following advantages: (1) everything is in a single file, (2) if you later decide to move to using packages you can use the very same file in your package with roxygen2 -- no need to revise anything, (3) any learning of roxygen2 applies to packages too.
# create a file with our documentation and code
Lines <- "
#' Add two numbers.
#'
#' #param x the first number.
#' #param y the second number.
#' #return The sum.
#' #note This is just a simple example.
#'
#' This function is a simple example intended to show how to use the modules
#' package with roxygen2.
add2 <- function(x, y) x + y
"
cat(Lines, file = "test.R")
# now we can import it
# devtools::install_github("klmr/modules")
library(modules)
test <- import("test") # do not include the .R extension
test$add2(1, 2)
## [1] 3
# this will cause help page to appear
?test$add2
Is there some mechanism by which I can transform the comments that roxygen sees, preferably before it does the roxygen->rd conversion?
For example, suppose I have:
#' My function. Does stuff with numbers.
#'
#' This takes an input `x` and does something with it.
#' #param x a number.
myFunction <- function (x) {
}
Now, suppose I want to do some conversion of the comment before roxygen parses it, for example replacing all instances of things in backticks with \code{}. Ie:
preprocess <- function (txt) {
gsub('`([^ ]+)`', '\\\\code{\\1}', txt)
}
# cat(preprocess('Takes an input `x` and does something with it'.))
# Takes an input \code{x} and does something with it.
Can I feed preprocess into roxygen somehow so that it will run it on the doclets before (or after would work in this case) roxygen does its document generation?
I don't want to do a permanent find-replace in my .r files. As you might guess from my example, I'm aiming towards some rudimentary markdown support in my roxygen comments, and hence wish to keep my .r files as-is to preserve readability (and insert the \code{..} stuff programmatically).
Should I just write my own version of roxygenise that runs preprocess on all detected roxygen-style comments in my files, saves them temporarily somewhere, and then runs the actual roxygenise on those?
Revisiting this a couple of years later, it looks like Roxygen has a function register.preref.parsers that one can use to inject their own parsers into roxygen.
One such use of this is the promising maxygen package (markdown + roxygen = maxygen), which a very neat implementation of markdown processing of roxygen comments (albeit only to the CommonMark spec), and you can see how it is used in that package's macument function. I eagerly await "pandoc + roxygen = pandoxygen"... :)
I am running R version 2.15.3 with RStudio version 0.97.312. I have one script that reads my data from various sources and creates several data.tables. I then have another r script which uses the data.tables created in the first script. I wanted to turn the second script into a R markdown script so that the results of analysis can be outputted as a report.
I do not know the purpose of read_chunk, as opposed to source. My read_chunk is not working, but source is working. With either instance I do not get to see the objects in my workspace panel of RStudio.
Please explain the difference between read_chunk and source? Why would I use one or the other? Why will my .Rmd script not work
Here is ridiculously simplified sample
It does not work. I get the following message
Error: object 'z' not found
Two simple files...
test of source to rmd.R
x <- 1:10
y <- 3:4
z <- x*y
testing source.Rmd
Can I run another script from Rmd
========================================================
Testing if I can run "test of source to rmd.R"
```{r first part}
require(knitr)
read_chunk("test of source to rmd.R")
a <- z-1000
a
```
The above worked only if I replaced "read_chunk" with "source". I
can use the vectors outside of the code chunk as in inline usage.
So here I will tell you that the first number is `r a[1]`. The most
interesting thing is that I cannot see the variables in RStudio
workspace but it must be there somewhere.
read_chunk() only reads the source code (for future references); it does not evaluate code like source(). The purpose of read_chunk() was explained in this page as well as the manual.
There isn't an option to run a chunk interactively from within knitr AFAIK. However, this can be done easily enough with something like:
#' Run a previously loaded chunk interactively
#'
#' Takes labeled code loaded with load_chunk and runs it in the /global/ envir (unless otherwise specified)
#'
#' #param chunkName The name of the chunk as a character string
#' #param envir The environment in which the chunk is to be evaluated
run_chunk <- function(chunkName,envir=.GlobalEnv) {
chunkName <- unlist(lapply(as.list(substitute(.(chunkName)))[-1], as.character))
eval(parse(text=knitr:::knit_code$get(chunkName)),envir=envir)
}
NULL
In case it helps anyone else, I've found using read_chunk() to read a script without evaluating can be useful in two ways. First, you might have a script with many chunks and want control over which ones run where (e.g., a plot or a table in a specific place). I use source when I want to run everything in a script (for example, at the start of a document to load a standard set of packages or custom functions). I've started using read_chunk early in the document to load scripts and then selectively run the chunks I want where I need them.
Second, if you are working with an R script directly or interactively, you might want a long preamble of code that loads packages, data, etc. Such a preamble, however, could be unnecessary and slow if, for example, prior code chunks in the main document already loaded data.