RPlugins Development

An overview of R Plugins can be found at  R Plugins & R Output window. This document provides a guideline to the development of new R plugins to bring custom functionality to Fluent Editor.  The first time you attemp to use a plugin, FluentEditor will try to download and install the ROntorion R-package if it is not already installed; ROntorion is the component that provides R with Fluent Editor reasoning capabilitites. All this implies that the ROntorion package is also accesible from a standard R console, including its help contents.

  1. Plugins inteface
  2. Plugins format
  3. Considerations and exception handling
  4. Plugin development's walk-through

Plugins interface

Every plugin developed must implement the following interface:



required RUN( R Environment ),

optional EDIT( R Environment ),

optional PLOT( R Environment )


The implementation in R looks as follows:

ontorion.plugin.{PLUGIN_NAME}.run  <- function(env) {}
ontorion.plugin.{PLUGIN_NAME}.plot <- function(env) {}
ontorion.plugin.{PLUGIN_NAME}.edit <- function(env) {}

Any of the above methods  can contain a call to the R print() function; Fluent Editor has an specific console device installed for the R engine and its content will be rendered either into the R Output console (run and plot)  or the Editor (edit) once all computing has been performed.   Additionally, any returned value from run() and plot() methods will be displayed respectively on the plot window or on the R output box).

The R plugin layout is as follows:



Where the parameter passed to each method (env) is an R Environment. To learn more about R environments type in an R console:

> ?new.env

In this first release of the functionality, the only symbol this environment is initialized with, is the contents of the editor in text format. This symbol is called content and can be accessed in env as:

editor_contents <- env['content']

Considerations and exception handling

Care must be taken when attempting to access the "content" symbol in the environment as it may be an empty string. To avoid issues, we recommend always check whether the symbols is empty or not through the following R-snipplet:

if (env[["content"]] == "") {stop("The CNL content is empty. No description will be performed.")}

The order of method calls is RUN > EDIT > PLOT. Each method will need to get the symbols already initialized in the enviroment (env) to perform its operation. The only required function is RUN which can be empty. Each function should call return() whenever no returned value is desired.

IMPORTS need to be done carefully. Each import must call the stop(_MESSAGE_) function in case of failure in either loading or downloading, we recommend the following schema:

if(!is.element('SOME_PACKAGE_NAME', installed.packages()[, 1])) {
        stop("Download the the package manually and install it in your local R environment") 

If there exist separate scripts then none of them should directly source  (through source(_FILENAME_)) any other, as this is handled automatically by the host in Fluent Editor.

Plugins format

Plugins are in .zip format  and all its contents are under the root folder. Inside there must be three files:

The schema of plugin.xml is:

    Name = "{PLUGIN_NAME}"
    Description = "A brief description of the functionality provided by the plugin"
    Author = "AUTHOR(s)"
    Date = "YYYY-MM-DD"
    RSources = "{COMMA_SEPARATED_R_SOURCES}.R"></RPlugin>

Once all contents are in the folder, zip it and change the extension of the resulting compressed file from .zip to .rplugin. To start deploying, drop the rplugin in the RPlugins folder under the FluentEditor installation path. The next time FluentEditor is started, the plugin will be listed under the Tools -> R Plugins:

Plugins development's walk-through

We will now provide a simple plugin implementation to print "Hello, world!" both to the R console  (as text) and to the Editor (as a comment).  The contents of the R source is as follows:

ontorion.plugin.helloWorld.run <- function(env){
  print("Hello, world!")
ontorion.plugin.helloWorld.edit <- function(env){
  if (env[["content"]] == "") {stop("The CNL content is empty. No description will be performed.")}
  onto<-ontorion.load.cnl.string( env[["content"]], FALSE)
  print("Comment: Hello, world!.")
  # Let's have some fun! Give me all instances in the universe as an or-collapsed string
  allInstances <- paste(sub("The-\"(.+)\"", "\\1", ontorion.instances.of(onto, "thing")), collapse = ' or ')
  # nothing outside this boundaries exists
  print(paste("Every-single-thing is either ", allInstances, ".", collapse=''))
which we will name "helloWorld.R". We have now a fully functional plugin. The plugin.xml file looks as follows:
    Name = "Hello World"
    Description = "A 'Hello, world!' program is a trivial program which outputs a static string of text, often the first written in a new esoteric programming language. --esolangs.org"
    Author = "Cognitum"
    Date = "2014-11-25"
    RSources = "helloWorld.R"></RPlugin>
The contents of our folder are:

We the zip the file and change the format from .zip to .rplugin ignoring any warning for the file extension change. We can provide any name to our plugin, in our case it will be helloWorld.rplugin. We now proceed to drop our rplugin to the RPlugins folder under the system-wide Fluent Editor installation path. The next time you start Fluent Editor, the new plugin will be available. Open an empty file and fill it with the following OCNL sentence:
Every-single-thing that is False is not True.

After clicking the new plugin you should see the following results:

You will notice that the R Output window contains two times the String "Hello, world!". This happens because we print both the results of the function and the string in the internal device console and as R is a functional language, the last computed value in a function is always the result of the function. To see try the following in an R console:
h <- function(){print("a")}
a <- h()
As you will notice a contains the string "a". To avoid this behavior, always call  return() on each method whenever you do not want to return any value.