Skip to content
Gordon Woodhull edited this page Mar 1, 2015 · 6 revisions

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.

R Packages

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:

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 package x contains file inst/www/y.html, and rcloud.org is an RCloud server (it's not), then y.html will be available at http://rcloud.org/shared.R/x/y.html

Loading JavaScript into the client

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.

DESCRIPTION

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