-
Notifications
You must be signed in to change notification settings - Fork 142
RCloud Extensions
RCloud can be extended in three different ways:
- new user interface features on the client side
- new kinds of notebook content that integrate R and JavaScript functionality
- new cell languages on the server side
The basic mechanism for each of these kinds of extensions is the same: the R package. An RCloud extension, therefore, is just an R package which expects to be run in the RCloud environment, and the RCloud environment spans a process running on a server and a web browser running on a client.
Here is a basic introduction to the features of R packages which you will need for creating an RCloud extension. General (and comprehensive) information on creating R packages can be found on CRAN.
An R package is directory of files in a particular structure. They can include source files of any number of languages, which makes them great for RCloud packages.
Files at the root level:
-
DESCRIPTION- contains metadata about the package. Details below -
NAMESPACE- lists any names that to be available to the R session. (The NAMESPACE file has other name operations which don't concern us here - this document is one place to learn more.)
Optional directories:
-
R/- contains R sources -
inst/javascript- contains javascript sources to be loaded dynamically by the package. See the next section for details. -
inst/python,inst/...- contains python sources -
inst/www- contains static resources to be served by HTTP, such as HTML, javascript, or images. If packagexcontains fileinst/www/y.html, andrcloud.orgis an RCloud server (it's not), theny.htmlwill be available athttp://rcloud.org/shared.R/x/y.html
By convention, packages that install JavaScript to the RCloud client have a file R/zzz.R with a function .onLoad. (The reason for this filename is just to put it last so that it loads after any other R sources.)
Here is a typical zzz.R, from the rcloud.enviewer package that displays the Workspace panel:
rcloud.enviewer.caps <- NULL
.onLoad <- function(libname, pkgname)
{
f <- function(module.name, module.path) {
path <- system.file("javascript", module.path, package="rcloud.enviewer")
caps <- rcloud.install.js.module(module.name,
paste(readLines(path), collapse='\n'))
caps
}
rcloud.enviewer.caps <<- f("rcloud.enviewer", "rcloud.enviewer.js")
if(!is.null(rcloud.enviewer.caps)) {
ocaps <- list(refresh = rcloud.support:::make.oc(rcloud.enviewer.refresh),
view_dataframe = rcloud.support:::make.oc(rcloud.enviewer.view.dataframe))
rcloud.enviewer.caps$init(ocaps)
}
}
The internal function f finds a javascript source within the package and installs it on the client dynamically.
The next line calls this function in order to install rcloud.enviewer.js, which contains GUI code for the extension.
Finally, if the function returns non-null, it means the package was loaded in an RCloud session and it is safe to call the JavaScript functions that were returned. So this function uses rcloud.support:::make.oc to wrap a couple of R functions from the same package that the client code will need, rcloud.enviewer.refresh and rcloud.enviewer.view.dataframe, and passes them to the client initialization function which was returned.
See [R-JavaScript binding](R-JavaScript binding) for more details on how to call R functions from JavaScript, and JavaScript functions from R.
The DESCRIPTION file in the root of an R package contains metadata about the package, as key-value pairs separated by :. Where there is more than one value, the values are separated by commas.
The fields we need for an RCloud package are:
-
Package- the name of the package -
Title- longer title of the package -
Version- the version of the package -
Author- name and email of the original author(s) of the package -
Maintainer- name and email of the package's maintainer -
Description- a human-readable description of the package -
Imports- packages this depends on, which will be loaded but not attached (this package uses names from these packages, but won't add them to the global environment) -
License- if the package is open-source, names the open source license