From noreply at r-forge.r-project.org Thu Jan 2 16:39:43 2014 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Thu, 2 Jan 2014 16:39:43 +0100 (CET) Subject: [Rpad-commits] r3 - in pkg/Rpad: . R inst inst/basehtml inst/basehtml/server man Message-ID: <20140102153943.D4521183CC5@r-forge.r-project.org> Author: jedick Date: 2014-01-02 16:39:42 +0100 (Thu, 02 Jan 2014) New Revision: 3 Added: pkg/Rpad/inst/basehtml/index.html pkg/Rpad/inst/basehtml/server/ pkg/Rpad/inst/basehtml/server/R_process.pl pkg/Rpad/inst/basehtml/server/Rpad_process.pl pkg/Rpad/man/Rpad-package.Rd Removed: pkg/Rpad/inst/basehtml/LocalDefault.Rpad Modified: pkg/Rpad/DESCRIPTION pkg/Rpad/R/LocalVersion.R pkg/Rpad/inst/NEWS pkg/Rpad/inst/README pkg/Rpad/inst/basehtml/DojoTest.html pkg/Rpad/inst/basehtml/Example1.Rpad pkg/Rpad/inst/basehtml/Rpad.css pkg/Rpad/inst/basehtml/Rpad_body.js pkg/Rpad/inst/basehtml/ServerNotes.html pkg/Rpad/man/RpadLocalServer.Rd Log: restore some functionality to the server version Modified: pkg/Rpad/DESCRIPTION =================================================================== --- pkg/Rpad/DESCRIPTION 2013-12-31 05:19:15 UTC (rev 2) +++ pkg/Rpad/DESCRIPTION 2014-01-02 15:39:42 UTC (rev 3) @@ -1,6 +1,6 @@ Package: Rpad Title: Workbook-style, web-based interface to R -Version: 1.3.99.0 +Version: 1.3.99.1 Author: Tom Short (EPRI), Philippe Grosjean (UMH EcoNum), Jeffrey Dick Description: A workbook-style user interface to R through a web browser. Provides convenient interaction with an R process Modified: pkg/Rpad/R/LocalVersion.R =================================================================== --- pkg/Rpad/R/LocalVersion.R 2013-12-31 05:19:15 UTC (rev 2) +++ pkg/Rpad/R/LocalVersion.R 2014-01-02 15:39:42 UTC (rev 3) @@ -36,13 +36,13 @@ "Rpad" <- -function(file = "", defaultfile = "LocalDefault.Rpad", port = 8079) { +function(file = "", defaultfile = "index.html", port = 8079) { startRpadServer(defaultfile, port) browseURL(paste("http://127.0.0.1:", port, "/", file, sep = "")) } "startRpadServer" <- -function(defaultfile = "LocalDefault.Rpad", port = 8079) { +function(defaultfile = "index.html", port = 8079) { require("tcltk") # This is the main function that starts the server # This function implements a basic http server on 'port' Modified: pkg/Rpad/inst/NEWS =================================================================== --- pkg/Rpad/inst/NEWS 2013-12-31 05:19:15 UTC (rev 2) +++ pkg/Rpad/inst/NEWS 2014-01-02 15:39:42 UTC (rev 3) @@ -1,3 +1,20 @@ +CHANGES IN Rpad 1.3.99.1 (2014-01-02) +------------------------------------- + +- Restore Perl files related to server version of Rpad + (Rpad_process.pl, R_process.pl). + +- Rename LocalDefault.Rpad to index.html (used in both the local and + server versions). + +- Remove outdated Debian and Windows sections in ServerNotes.html, but + move some of the notes to "Additional Notes". + +- Major revision of R_process.pl. Now uses a recent Statistics::R + (tested with version 0.32), forks a background Perl process, + uses Linux:Inotify to become aware of R commands and Time:Out + to self-destruct. + CHANGES IN Rpad 1.3.99.0 (2013-12-31) ------------------------------------- Modified: pkg/Rpad/inst/README =================================================================== --- pkg/Rpad/inst/README 2013-12-31 05:19:15 UTC (rev 2) +++ pkg/Rpad/inst/README 2014-01-02 15:39:42 UTC (rev 3) @@ -1,13 +1,14 @@ This is the Rpad "inst" directory -README this file -ChangeLog old ChangeLog, from Rpad 1.3.0 (April 2007) -NEWS current NEWS -tcl/ HTTP server written in TCL -server/ Perl files for the server version of Rpad -basehtml/ The Javascript, CSS and example HTML files for Rpad -app.profile.js Application build profile for Dojo customization -LICENSE.dojo License for the Dojo toolkit (http://dojotoolkit.org/) +README This file +ChangeLog Old ChangeLog, from Rpad 1.3.0 (April 2007) +NEWS Current NEWS +tcl/ Local HTTP server in TCL +basehtml/ The Javascript, CSS and example HTML files for Rpad +basehtml/server/ Perl files for the server version of Rpad +perl_interface/ Statistics::Rpad Perl module, based on Statistics::R +app.profile.js Application build profile for Dojo customization +LICENSE.dojo License for the Dojo toolkit (http://dojotoolkit.org/) -------- Parts of app.profile.js were adapted from the Dojo boilerplate: Modified: pkg/Rpad/inst/basehtml/DojoTest.html =================================================================== --- pkg/Rpad/inst/basehtml/DojoTest.html 2013-12-31 05:19:15 UTC (rev 2) +++ pkg/Rpad/inst/basehtml/DojoTest.html 2014-01-02 15:39:42 UTC (rev 3) @@ -29,7 +29,7 @@

Hello

-

The heading immediately above should say "Hello Dojo!" then change to "Hello" a few seconds later. This confirms that Dojo is loaded and can locate modules programmatically (in JavaScript).

+

The heading immediately above should say "Hello Dojo!" then change to "Hello" a few seconds later. This confirms that Dojo is loaded and can locate modules programmatically (in JavaScript). It may not work on the server version of Rpad (if myModule.js is not in the webserver root directory).

A simple Dojo widget

There should be a button below with a counter that increments when clicked. This confirms that Dojo widgets can be instantiated declaratively (in markup).

Modified: pkg/Rpad/inst/basehtml/Example1.Rpad =================================================================== --- pkg/Rpad/inst/basehtml/Example1.Rpad 2013-12-31 05:19:15 UTC (rev 2) +++ pkg/Rpad/inst/basehtml/Example1.Rpad 2014-01-02 15:39:42 UTC (rev 3) @@ -22,8 +22,6 @@ --> - - Rpad Example @@ -64,12 +62,22 @@ The Calculate button also refreshes this plot.

+ +

-

+
Standard deviation

+
+
+print(sdlog)
+
+

Deleted: pkg/Rpad/inst/basehtml/LocalDefault.Rpad
===================================================================
--- pkg/Rpad/inst/basehtml/LocalDefault.Rpad	2013-12-31 05:19:15 UTC (rev 2)
+++ pkg/Rpad/inst/basehtml/LocalDefault.Rpad	2014-01-02 15:39:42 UTC (rev 3)
@@ -1,167 +0,0 @@
-
-
-
-
-
-
-
-
-  Rpad Base Page
-  
-  
-  
-  
-
-
-
-
-  
-
-
-
-
-
-

Rpad/HTML pages in working directory (click on the link to load the file):

- - - -
-
-.threecolumns = function(lst) {
-    n = length(lst)
-    if (n <= 3) return(as.matrix(lst))
-    ncol = 3
-    nrow = ceiling(n / ncol)
-    lst = as.matrix(append(lst, rep("", ncol * nrow - n)))
-    dim(lst) = c(nrow, ncol)
-    lst
-}
-.rpadfiles = grep('\\.html$|\\.rpad$', dir(), ignore.case = TRUE, value = TRUE)
-.rpadfiles = H("a", href = .rpadfiles, collapseContents = FALSE,
-               .rpadfiles)
-.rpadfiles = .threecolumns(.rpadfiles)
-HTMLon()
-Html(.rpadfiles)
-
-
- - - - - -

Objects in user's workspace:

-
-
-# print(ls.str(), wid = 40, nchar.max = 20, vec.len=2)
-ls()
-
-
- -

Enter R code here and press - -or F9 to run it: -

-
- -
- - -
      -

Help

- - -Rpad documentation
-Server notes
-
- -

Rpad Demos

- - -General Example
-Input Examples
-Dojo Test Page
-Rpad Test Page
-
- -

Links

- - -Tom Short's R refcard
-Matt Baggot's R refcard v2
-Liu's R refcard
-Rpad homepage
-R homepage
-
- - - -
- -


-The original author of Rpad is: -
-Tom Short, tshort at epri.com, Copyright 2005. EPRI, license: GNU GPL v2 or greater -
-To contact the current maintainer, see the DESCRIPTION file - - - Modified: pkg/Rpad/inst/basehtml/Rpad.css =================================================================== --- pkg/Rpad/inst/basehtml/Rpad.css 2013-12-31 05:19:15 UTC (rev 2) +++ pkg/Rpad/inst/basehtml/Rpad.css 2014-01-02 15:39:42 UTC (rev 3) @@ -79,11 +79,3 @@ text-align:right; padding:2px 2px 2px 2px; border: thin solid #CCC; } -.RpadTableHolder .tableheaderrow { -/* - cursor: pointer ; - behavior:url(js/tablesort.htc); - -moz-binding: url(../js/moz-behaviors.xml#tablesort.htc); -*/ -} - Modified: pkg/Rpad/inst/basehtml/Rpad_body.js =================================================================== --- pkg/Rpad/inst/basehtml/Rpad_body.js 2013-12-31 05:19:15 UTC (rev 2) +++ pkg/Rpad/inst/basehtml/Rpad_body.js 2014-01-02 15:39:42 UTC (rev 3) @@ -204,6 +204,7 @@ // Send "commands" for processing. // Put results received in the DOM node "rpadResults". // Send along the originating DOM node "rpadInput" in case it's needed. +//alert("in rpad.send, commands = "+commands); require(["dojo/request"], function(request){ // The target URL on your webserver: request.get("server/R_process.pl", { @@ -220,7 +221,7 @@ rpad.receive(rpadResults, response, rpadInput); }, function(err){ // Event handler on errors: - alert("error in rpad.send"); + alert("Error in rpad.send. Did R stop running?\n"+err); }); }); } @@ -325,18 +326,24 @@ command = name + " = '" + node.value + "'"; } else if (node.nodeName.toLowerCase() == "select" && node.selectedIndex >= 0) command = name + " = '" + node[node.selectedIndex].text.replace(/'/g,"\\\'") + "'" - else if (node.type == "text" || node.type == "hidden") + else if (node.type == "text" || node.type == "hidden") { if (node.getAttribute("rpadType") == "Rvariable" && node.value != "") { command = name + " = " + node.value; } else if (node.getAttribute("rpadType") == "Rstring" && node.value != "") { command = name + " = '" + node.value.replace(/'/g,"\\\'") + "'"; } + } commands = commands + command + "\n"; + } //alert("processRForm node.type="+node.type+" commands="+commands); - } - if (commands != "") { + if (commands != "" && commands != "\n") { rpad.send(commands, null, nodes[0]); + } else if (commands == "\n") { + // the \n by itself, caused by an input field in an Rpad widget (not Rvariable or Rstring) + // results in a spurious R command that breaks R communication in the CGI implementation, + // but we do need to keep going to calculate the next nodes + rpad.calculateNextNode(nodes[0]); } } @@ -447,9 +454,10 @@ rpad.processRForm(node.elements); return true; } - // process standalone input fields individually + // process standalone input fields (but not buttons) individually if ((node.nodeName == "INPUT" || node.nodeName == "SELECT") && node.getAttribute("name") != "" && + node.type != "button" && rpad._hasNoFormParent(node)) { rpad.processRForm(node); return true; @@ -507,27 +515,30 @@ require(["dojo/request"], function(request){ // The target URL on your webserver: + // initialize Rpad request.get("server/Rpad_process.pl?command=login", { // The used data format. handleAs: "text" }).then(function(response){ - // Event handler on successful call: - // The target URL on your webserver: + // Save the location of the rpad temporary directory and start an R process + rpad.dir = response; request.get("server/R_process.pl?ID="+response+"&command=login", { handleAs: "text" }).then(function(response){ // this is where we want to be! let's calculate the page if(rpad._runState == "init") rpad.calculatePage(); }, function(err){ - alert("error in rpad.login step 2/2"); + // (The missingness of Statistics::R might cause this error on the server version of Rpad, not the local version) + alert("Error in rpad.login step 2/2. Is the Statistics::R Perl module installed? Error:\n"+err); }); }, function(err){ // Event handler on errors: - alert("error in rpad.login step 1/2"); + // (The missingness of Rpad_process.pl will cause this error on the server version of Rpad, not the local version) + alert("Error in rpad.login step 1/2. Is the Rpad/server/Rpad_process.pl file present on the HTTP server?"); }); }); Modified: pkg/Rpad/inst/basehtml/ServerNotes.html =================================================================== --- pkg/Rpad/inst/basehtml/ServerNotes.html 2013-12-31 05:19:15 UTC (rev 2) +++ pkg/Rpad/inst/basehtml/ServerNotes.html 2014-01-02 15:39:42 UTC (rev 3) @@ -30,15 +30,8 @@

Installation of the Server Version

-

Rpad has been setup with Linux using the Apache server, with - either Apache 1.3 or Apache 2.0. It may - well work on others, but this was the easiest option. Under - windows, it has also been tested with Apache - (although it doesn't seem as responsive as apache under linux). I have - also had good experiences using Rpad with coLinux (www.colinux.org) under - win2k with R, Apache, and mod_perl. Rpad can be installed using - CGI for the perl portion or with mod_perl. These directions - describe installation with mod_perl:

+

This document outlines the setup of the server version of Rpad on Linux using Apache 2.4. + The Perl portion of the Rpad interface can be installed using CGI or mod_perl.

The main steps to installing Rpad on a server are:

@@ -47,49 +40,54 @@
  • Install the R2HTML package from CRAN.
  • -
  • Install the Rpad package from CRAN.
  • +
  • Install the Rpad package from CRAN. + Note: for server version, Rpad and all other referenced R packages must be + installed at the system level.
  • Install Apache.
  • -
  • Install mod_perl. This is optional. Rpad can also be run - with CGI.
  • +
  • Install mod_perl (optional, but faster than CGI).
  • Copy the directory basehtml in Rpad's package directory to - /www/var (or wherever your server root is). Rename as + /var/www (or wherever your server root is). Rename as appropriate. For example:
  •  cp -r /usr/lib/R/library/Rpad/basehtml /var/www/Rpad
     
    -
  • Enable write access to the Rpad directory as well as the - Rpad/server directory.
  • +
  • Ensure the webserver user (e.g. apache) has write access to the /tmp directory.
  • Enable execution of all of the Rpad/server/*.pl files (chmod a+x).
  • -
  • Install the Statistics-R_perl_interface that comes with Rpad - in the serverversion directory. This version has slight - modifications to Graciliano's R-Statistics - version 0.02).
  • + +
  • Install the required Perl modules (all available on CPAN):
  • + +
      +
    • Statistics::R (tested with version 0.32; don't use the old 0.02!) (and dependencies IPC::Run, Regexp::Common, Text::Balanced). + Used to control an R process through Perl.
    • -
    • Change the server configuration as appropriate to enable - CGI and/or mod_perl. Tell the browser not - to cache some files which might change during a - session, using the mod_expires module. Here is the portion of the httpd.conf for Apache 1.3 - to do this for Rpad files in /var/www/Rpad:
    • +
    • Linux::Inotify2 (and its dependency, common:sense). Used to monitor file changes + so that incoming R commands can be executed by a backgrounded Perl/R bridge.
    • +
    • Time::Out. Used to time out waiting for R results (10 seconds), and to destroy the background + Perl/R bridge (10 minutes, after which the temporary directory is cleared and the R and Perl processes exit).
    • +
    + + + + +
  • Update the HTTP server configuration file to enable execution of the Perl scripts. + Also, add a mime type to tell the server to serve .Rpad files as text/html, and + use mod_expires to tell the browser not to cache some files which might change + during a session. Here is the portion of the httpd.conf for Apache 2.4 + to do this using CGI:
  • +
    +LoadModule cgi_module modules/mod_cgi.so
     <Directory /var/www/Rpad/server*>  
    -  <IfModule mod_perl.c>
    -    <Files *.pl> # requires mod_perl
    -      SetHandler perl-script
    -      PerlHandler Apache::Registry
    -      Options +ExecCGI
    -      PerlSendHeader ON
    -    </Files>
    -  </IfModule>
       Options +ExecCGI
       AddHandler cgi-script .pl
       <IfModule mod_expires.c>
    @@ -97,66 +95,35 @@
         ExpiresDefault "now plus 0 seconds"
       </IfModule>
     </Directory>
    -AddType text/x-component .htc
     AddType text/html .Rpad
     
      -
    • Here's a portion of the httpd.conf to configure Rpad for - Apache2 for files in /var/www/Rpad:
    • +
    • This is what it might look like when using mod_perl:
    +LoadModule perl_module modules/mod_perl.so
     <Directory /var/www/Rpad/server*>  
       <IfModule mod_perl.c>
         <Files *.pl> # requires mod_perl
           SetHandler perl-script
    -      PerlResponseHandler ModPerl::PerlRun
    +      PerlResponseHandler ModPerl::Registry
           PerlOptions +ParseHeaders
    -      Options -Indexes +ExecCGI
    +      Options +ExecCGI
         </Files>
       </IfModule>
    -  Options +ExecCGI
    -  AddHandler cgi-script .pl
       <IfModule mod_expires.c>
         ExpiresActive on
         ExpiresDefault "now plus 0 seconds"
       </IfModule>
     </Directory>
    -AddType text/x-component .htc
     AddType text/html .Rpad
     
    -
      -
    • Add a mime type to tell the server to serve .Rpad files as - text/html (done in the httpd.conf files above).
    • -
    • To get the help menu item to work, create a symlink R to /usr/lib/R - in the /www/var/Rpad directory (ln -s /usr/lib/R /var/www/Rpad/R).
    • -
    • To update the javascript database for the R keyword search - page (SearchRKeywords.html), source makeHelpTemplate.R from - within R in the main Rpad directory.
    • -
    -

    Notes on Debian

    +

    Additional Notes

    -

    This is the main platform that Debian's been tested on, and -www.Rpad.org is a Debian -server. Debian packages for Rpad are available at www.Rpad.org. Installing the Rpad -package does all of the installation steps described above. Under -Debian, Rpad will work with apache or apache2, and it will work with -or without mod_perl on either version of apache.

    - -

    There's also a script that will install the Rpad html files. It is located in the -serverversion directory within the Rpad package directory. It's called -installRpadWWW.sh. This creates another Rpad directory. In -addition to copying the base html files, it sets permissions and configures -apache properly for that directory. Here's an example: -

    -
    -/usr/local/lib/R/site-library/Rpad/installRpadWWW.sh /var/www/RpadTesting
    -
    -

    I normally add a cron job to restart the Apache server once a day. This clears out any R processes that didn't get killed for whatever reason. I create the following as the file /etc/cron.daily/Rpad-cleanup:

    @@ -166,49 +133,10 @@ rm -rf /var/www/Rpad/server/dd*
    +

    Some considerations for Windows:

    -

    Notes on Apache 1.3 under Windows

    - -
    -# Installing apache_1.3.33-win32-x86-no_src.msi downloaded from
    -# www.apache.org using CGI
    -# Windows 2000
    -# Perl 5.8.4 installed at C:/apps/perl
    -# Installed Apache at C:/Program Files/Apache Group/Apache
    -# WWW root is at C:/Program Files/Apache Group/Apache/htdocs
    -
    -# Copied the directory basehtml directory to htdocs\Rpad
    -xcopy/I/S "C:\Program Files\R\rw2001\library\Rpad\basehtml" "C:\Program Files\Apache Group\Apache\htdocs\Rpad"
    -
    -# Added a mime type for .Rpad files in conf\mime.types as follows:
    -text/html			Rpad
    -
    -#Installed Statistics-R_perl_interface:
    -cd C:\Program Files\R\rw2001\library\Rpad\serverversion\Statistics-R_perl_interface
    -perl Makefile.pl
    -nmake
    -nmake install
    -# you can also just copy the directory
    -# C:\Program Files\R\rw2001\library\Rpad\serverversion\Statistics-R_perl_interface\lib\Statistics
    -# to C:\apps\perl\site\lib (or wherever your perl lib's are)
    -
    -# Add the following to the conf\httpd.conf file to read .pl files as CGI:
    -AddHandler cgi-script .pl
    -
    -# Changed the following in the conf\httpd.conf file to enable CGI:
    -    Options Indexes FollowSymLinks MultiViews
    -# to 
    -    Options Indexes FollowSymLinks MultiViews ExecCGI
    -
    -# Added the following line as the first line to the 3 perl files in
    -# htdocs\Rpad\server to point to perl 
    -#!c:/apps/perl/bin/perl.exe 
    -
    -# I also futzed with the permissions on these files, but I don't know
    -# that it was necessary.
    -
    -# Used R's png driver rather than ghostscript: in .RpadStartup.R,
    +# Used R's png driver rather than ghostscript: in RpadStartup.R,
     # uncommented the following line: 
     # 
     graphoptions(type="Rpng")
    @@ -230,78 +158,10 @@
     You need to change the user for the apache service and 
     set permissions for that user to prevent access to unwanted
     parts of your hard drive. Google for "apache localsystem ntfs permissions".
    -
     
    -

    Notes on Apache 2.0 under Windows

    -

    Installing Rpad on an apache2 installation (cgi mode) on Windows 2000 -worked exactly the same as the Apache 1.3 installation.

    - -

    I briefly tried Rpad with apache2/modperl under windows. In very limited -testing, it worked okay. Modperl under windows can make Apache very slow, at least to start -and stop. A server restart can take over 10 seconds on my win2k -laptop.

    - -

    Notes on the Windows IIS server

    - -

    WARNING: Users (including me) have reported problems installing -Rpad on IIS. I've got a Windows 2000 machine with IIS running fine. In -another installation on XP (also using IIS v5.1), it refuses to start -R (the perl part works, it just won't spawn another process).

    - -

    Installing Rpad on the IIS server that came with Windows 2000 -worked mainly the same as the Apache 1.3 installation. Here are some -further notes:

    - -
     
    -# Copied the directory basehtml directory to wwwroot\Rpad
    -xcopy/I/S "C:\Program Files\R\rw2001\library\Rpad\basehtml" "C:\Inetpub\wwwroot\Rpad"
    -
    -#Installed the Statistics-R_perl_interface as outlined above.
    -
    -## NOTE: This step shouldn't be needed anymore! It should figure it out right,
    -## but I left it in so you can try it if things don't work right.
    -# In C:\Inetpub\wwwroot\Rpad\server\R_process.pl, change the following
    -# lines from:
    -my $R = Statistics::Rpad->new(
    -#                           log_dir => '/var/www/Rpad/server/' . $Rpad_ID
    -                           log_dir => $dir . $Rpad_ID
    -                           ) ;
    -# to:
    -my $R = Statistics::Rpad->new(
    -                           log_dir => 'c:/Inetpub/wwwroot/Rpad/server/' . $Rpad_ID
    -#                           log_dir => $dir . $Rpad_ID
    -                           ) ;
    -
    -# In the IIS "properties" tab, change the following:
    -# Under Http Headers|File Types...|New Type..., entered a Content type
    -# of text/html for an Associated Extension of Rpad
    -# Under Home Directory|Configuration...|App Mappings,
    -# added a Extension for pl with an Executable of 
    -# C:\apps\Perl\bin\perl5.8.4.exe %s %s
    -
    -# Used R's png driver rather than ghostscript: 
    -# in c:/Inetpub/wwwroot/Rpad/.RpadStartup.R,
    -# uncommented the following line: 
    -# 
    -graphoptions(type="Rpng")
    -
    -# In c:/Inetpub/wwwroot/Rpad/.RpadStartup.R, uncommented 
    -# the following lines to properly specify the location for graphs.
    -#
    -## NOTE: This step shouldn't be needed anymore! It should figure it out right,
    -## but I left it in so you can try it if things don't work right.
    -assign("RpadDir", envir = Rpad:::.RpadEnv,
    -       gsub("c:/Inetpub/wwwroot","", getwd(), ignore.case = TRUE) )
    -
    -I didn't know how to disable caching on the pages served from Rpad/server*.
    -
    -As with apache, you need to lock down the file permissions. Google
    -for IIS and IUSR. Also look for "IIS Lockdown Tool". 
    -
    -

    Troubleshouting server installations

    Look for directories named /var/www/Rpad/server/dd??????????/ @@ -355,13 +215,17 @@

    If graphics appear locally but not on remote machines, it indicates a problem with finding the URL for the graphics files. You may have to -modify the Rpad/.RpadStartup.R to explicitly tell R where to find +modify the Rpad/RpadStartup.R to explicitly tell R where to find the graphics files, like:

    assign("RpadDir", envir = Rpad:::.RpadEnv, gsub("c:/Inetpub/wwwroot","", getwd(), ignore.case = TRUE) ) -


    by Tom Short, tshort at epri.com, Copyright 2005. EPRI, license: GNU GPL v2 or greater +


    +Original author: +by Tom Short, tshort at epri.com, Copyright 2005. EPRI, license: GNU GPL v2 or greater +Last updated 2014-01-01 by Jeffrey Dick. + Added: pkg/Rpad/inst/basehtml/index.html =================================================================== --- pkg/Rpad/inst/basehtml/index.html (rev 0) +++ pkg/Rpad/inst/basehtml/index.html 2014-01-02 15:39:42 UTC (rev 3) @@ -0,0 +1,174 @@ + + + + + + + + + Rpad Base Page + + + + + + + + + + + + + +
    +

    Rpad/HTML pages in working directory (click on the link to load the file):

    + + + +
    +
    +.threecolumns = function(lst) {
    +    n = length(lst)
    +    if (n <= 3) return(as.matrix(lst))
    +    ncol = 3
    +    nrow = ceiling(n / ncol)
    +    lst = as.matrix(append(lst, rep("", ncol * nrow - n)))
    +    dim(lst) = c(nrow, ncol)
    +    lst
    +}
    +.rpadfiles = grep('\\.html$|\\.rpad$', dir(), ignore.case = TRUE, value = TRUE)
    +.rpadfiles = H("a", href = .rpadfiles, collapseContents = FALSE,
    +               .rpadfiles)
    +.rpadfiles = .threecolumns(.rpadfiles)
    +HTMLon()
    +Html(.rpadfiles)
    +
    +
    + + + + + +

    Objects in user's workspace:

    +
    +
    +# print(ls.str(), wid = 40, nchar.max = 20, vec.len=2)
    +ls()
    +
    +
    + +

    Enter R code here and press + +or F9 to run it: +

    +
    + +
    + +

    The date and time:

    +
    +
    +date()
    +
    +
    + + +
          +

    Help

    + + +Rpad documentation
    +Server notes
    +
    + +

    Rpad Demos

    + + +General Example
    +Input Examples
    +Dojo Test Page
    +Rpad Test Page
    +
    + +

    Links

    + + +Tom Short's R refcard
    +Matt Baggot's R refcard v2
    +Liu's R refcard
    +Rpad homepage
    +R homepage
    +
    + + + +
    + +


    +The original author of Rpad is: +
    +Tom Short, tshort at epri.com, Copyright 2005. EPRI, license: GNU GPL v2 or greater +
    +To contact the current maintainer, see the DESCRIPTION file + + + Added: pkg/Rpad/inst/basehtml/server/R_process.pl =================================================================== --- pkg/Rpad/inst/basehtml/server/R_process.pl (rev 0) +++ pkg/Rpad/inst/basehtml/server/R_process.pl 2014-01-02 15:39:42 UTC (rev 3) @@ -0,0 +1,176 @@ +#!/usr/bin/perl -w +#!c:/apps/perl/bin/perl.exe + +# The following line is a test script to see if it works. +# http://localhost/Rpad/server/R_process.pl?&ID=/tmp/ddNTlmHSvWZF&command=R_commands&R_commands=print('hello') + +use strict; +use warnings; + +use Statistics::R; +use Linux::Inotify2; +use File::Path qw(remove_tree); [TRUNCATED] To get the complete diff run: svnlook diff /svnroot/rpad -r 3 From noreply at r-forge.r-project.org Sat Jan 4 11:15:39 2014 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Sat, 4 Jan 2014 11:15:39 +0100 (CET) Subject: [Rpad-commits] r4 - in pkg/Rpad: . inst inst/basehtml inst/basehtml/server man Message-ID: <20140104101539.CE6B81865F7@r-forge.r-project.org> Author: jedick Date: 2014-01-04 11:15:39 +0100 (Sat, 04 Jan 2014) New Revision: 4 Modified: pkg/Rpad/DESCRIPTION pkg/Rpad/inst/NEWS pkg/Rpad/inst/basehtml/ServerNotes.html pkg/Rpad/inst/basehtml/index.html pkg/Rpad/inst/basehtml/server/R_process.pl pkg/Rpad/man/Rpad-package.Rd Log: improve timeout in R_process.pl Modified: pkg/Rpad/DESCRIPTION =================================================================== --- pkg/Rpad/DESCRIPTION 2014-01-02 15:39:42 UTC (rev 3) +++ pkg/Rpad/DESCRIPTION 2014-01-04 10:15:39 UTC (rev 4) @@ -1,6 +1,6 @@ Package: Rpad Title: Workbook-style, web-based interface to R -Version: 1.3.99.1 +Version: 1.3.99.2 Author: Tom Short (EPRI), Philippe Grosjean (UMH EcoNum), Jeffrey Dick Description: A workbook-style user interface to R through a web browser. Provides convenient interaction with an R process Modified: pkg/Rpad/inst/NEWS =================================================================== --- pkg/Rpad/inst/NEWS 2014-01-02 15:39:42 UTC (rev 3) +++ pkg/Rpad/inst/NEWS 2014-01-04 10:15:39 UTC (rev 4) @@ -1,4 +1,4 @@ -CHANGES IN Rpad 1.3.99.1 (2014-01-02) +CHANGES IN Rpad 1.3.99.2 (2014-01-04) ------------------------------------- - Restore Perl files related to server version of Rpad @@ -12,8 +12,8 @@ - Major revision of R_process.pl. Now uses a recent Statistics::R (tested with version 0.32), forks a background Perl process, - uses Linux:Inotify to become aware of R commands and Time:Out - to self-destruct. + uses Linux:Inotify to become aware of R commands, and attempts to + to self-destruct after 10 minutes. CHANGES IN Rpad 1.3.99.0 (2013-12-31) ------------------------------------- Modified: pkg/Rpad/inst/basehtml/ServerNotes.html =================================================================== --- pkg/Rpad/inst/basehtml/ServerNotes.html 2014-01-02 15:39:42 UTC (rev 3) +++ pkg/Rpad/inst/basehtml/ServerNotes.html 2014-01-04 10:15:39 UTC (rev 4) @@ -70,8 +70,6 @@
  • Linux::Inotify2 (and its dependency, common:sense). Used to monitor file changes so that incoming R commands can be executed by a backgrounded Perl/R bridge.
  • -
  • Time::Out. Used to time out waiting for R results (10 seconds), and to destroy the background - Perl/R bridge (10 minutes, after which the temporary directory is cleared and the R and Perl processes exit).
  • Modified: pkg/Rpad/inst/basehtml/index.html =================================================================== --- pkg/Rpad/inst/basehtml/index.html 2014-01-02 15:39:42 UTC (rev 3) +++ pkg/Rpad/inst/basehtml/index.html 2014-01-04 10:15:39 UTC (rev 4) @@ -124,14 +124,7 @@
    -

    The date and time:

    -
    -
    -date()
    -
    -
    -      

    Help

    Modified: pkg/Rpad/inst/basehtml/server/R_process.pl =================================================================== --- pkg/Rpad/inst/basehtml/server/R_process.pl 2014-01-02 15:39:42 UTC (rev 3) +++ pkg/Rpad/inst/basehtml/server/R_process.pl 2014-01-04 10:15:39 UTC (rev 4) @@ -1,176 +1,198 @@ -#!/usr/bin/perl -w -#!c:/apps/perl/bin/perl.exe - -# The following line is a test script to see if it works. -# http://localhost/Rpad/server/R_process.pl?&ID=/tmp/ddNTlmHSvWZF&command=R_commands&R_commands=print('hello') - -use strict; -use warnings; - -use Statistics::R; -use Linux::Inotify2; -use File::Path qw(remove_tree); -use Time::Out qw(timeout); -use CGI qw/:standard send_http_header/; - -# chdir to temporary directory -#my $Rpad_ID = '/home/jedick/tmp/rtmp'; ## testing -my $Rpad_ID = param('ID'); -chomp($Rpad_ID); -chdir $Rpad_ID; - -#my $p_command = 'login'; ## testing -#my $p_command = 'R_commands'; ## testing -my $p_command = param('command'); -chomp $p_command ; - -my @output_value = ""; - -if ($p_command eq 'login') { - - # fork this process - my $pid = fork(); - die "Fork failed: $!" if !defined $pid; - - if ($pid == 0) { - - # do this in the child - open STDOUT, ">/dev/null"; - open STDERR, ">/dev/null"; - - # start R and load Rpad - my $R = ""; - sub startR{ - $R = Statistics::R->new( shared => 1 ); - $R->start(); - $R->run(q`require(Rpad)`); - # from ?stop: "don't stop on stop(.)" - # this way the R process behaves more like the interactive session - it isn't halted when an error occurs - # but errors still hang up the perl so we can't use it... - #$R->run(q`options(error = expression(NULL))`); - } - &startR(); - - # subroutine to clean up temporary directory - sub cleanup{ - chdir ".." or die "Failed to go to parent directory: $!"; - remove_tree($Rpad_ID); - } - - # set up inotify watch on temporary directory - my $inotify = new Linux::Inotify2 - or die "Unable to create new inotify object: $!"; - $inotify->watch("$Rpad_ID", IN_CLOSE_WRITE, sub { - my $event = shift; - my $name = $event->name; - # run the input.R when it appears - if ( $name eq "input.R" ) { - # read R command from the input file - # $R->run_from_file would be cleaner, but it's a source(), so doesn't echo like the interactive session - #my $output_value = eval { $R->run_from_file($name); }; - open(my $fh, '<', $name) or die "Could not open file '$name' $!"; - # Slurp into a scalar - my $R_commands; - { local $/ = undef; $R_commands = <$fh>; } - close $fh; - my $output_value = eval { $R->run($R_commands); }; - - # convert any errors from R into the output text - if ( $@ ) { - $output_value = "$@"; - # remove first 3 lines for a cleaner error message - $output_value =~ s/^(?:.*\n){1,3}//; - # restart R (probably should test if really did stop) - &startR(); - } - # save output to file - my $filename = "output"; - open($fh, '>', $filename) or die "Could not open file '$filename' $!"; - print $fh "$output_value\n"; - close $fh; - } - elsif ( $name eq "theend" ) { - &cleanup(); - die "watch process terminated by request"; - } - }) or die "watch creation failed: $!"; - - # put a limit of 10 minutes on our process - timeout 600 => sub { - 1 while $inotify->poll; - } ; - if ($@){ - &cleanup(); - # operation timed-out - die "watch process reached timeout limit"; - } - } - - # wait a second for R to start and to begin watch of - # input file before any R commands are sent - sleep 1; - -} - -elsif ($p_command eq 'logout') { - - # this creates a file signalling the end of Perl child process - my $filename = "theend"; - open(my $fh, '>', $filename) or die "Could not open file '$filename' $!"; - print $fh "\n"; - close $fh; - -} - -elsif ($p_command eq 'R_commands') { - - # process R commands - #my $R_commands = "print('abcxyz') \n\ndate()\n\n \n Sys.sleep(10)"; ## testing - my $R_commands = param('R_commands'); - # replace non-breaking spaces with regular spaces - $R_commands =~ s/\xA0/ /g; - - # save commands to the input file that is being watched by the child process - my $filename = "input.R"; - open(my $fh, '>', $filename) or die "Could not open file '$filename' $!"; - # split the string of commands on newlines - my @lines = split /\n/, $R_commands; - foreach my $line (@lines) { - # remove the trailing space(s), which seem to cause problems - $line =~ s/\ *$//g; - # blank lines also cause problems; remove them too - if ( $line ne "" ) { - print $fh "$line\n"; - } - } - close $fh; - - # set up inotify watch to grab output file - my $inotify = new Linux::Inotify2 - or die "Unable to create new inotify object: $!"; - $inotify->watch("$Rpad_ID", IN_CLOSE_WRITE, sub { - my $event = shift; - my $name = $event->name; - if ( $name eq "output" ) { - # read contents of output file into output_value - my $filename = "output"; - open(my $fh, '<', $filename) or die "Could not open file '$filename' $!"; - @output_value=<$fh>; - close $fh; - } - }) or die "watch creation failed: $!"; - - # interrupt the watch if it runs for more than 10 seconds. - timeout 10 => sub { - $inotify->poll; - } ; - if ($@){ - # operation timed-out - @output_value = "10 seconds passed with no output from R ... back to you!\n"; - } - -} - -CGI::initialize_globals(); -print header; -print @output_value; +#!/usr/bin/perl +#!c:/apps/perl/bin/perl.exe + +# The following line is a test script to see if it works. +# http://localhost/Rpad/server/R_process.pl?&ID=/tmp/ddNTlmHSvWZF&command=R_commands&R_commands=print('hello') + +use strict; +use warnings; + +use Statistics::R; +use Linux::Inotify2; +use File::Path qw(remove_tree); +use CGI qw/:standard send_http_header/; +use Time::HiRes qw(time sleep); + +CGI::initialize_globals(); + +# get name of temporary directory +#my $Rpad_ID = '/home/jedick/tmp/rtmp'; ## testing +my $Rpad_ID = param('ID'); +chomp($Rpad_ID); + +#my $p_command = 'login'; ## testing +#my $p_command = 'R_commands'; ## testing +my $p_command = param('command'); +chomp $p_command ; + +my @output_value = ""; + +if ($p_command eq 'login') { + + # fork this process + my $pid = fork(); + die "Fork failed: $!" if !defined $pid; + + if ($pid == 0) { + + # do this in the child + open STDOUT, ">/dev/null"; + open STDERR, ">/dev/null"; + + # start R and load Rpad + my $R = ""; + sub startR{ + chdir $Rpad_ID; + $R = Statistics::R->new( shared => 1 ); + $R->start(); + $R->run(q`require(Rpad)`); + # from ?stop: "don't stop on stop(.)" + # this way the R process behaves more like the interactive session - it isn't halted when an error occurs + # but errors still hang up the perl so we can't use it... + #$R->run(q`options(error = expression(NULL))`); + chdir ".." or die "Failed to go to parent directory: $!"; + } + &startR(); + + # subroutine to clean up temporary directory + sub cleanup{ + remove_tree($Rpad_ID); + } + + # set up inotify watch on temporary directory + my $inotify = new Linux::Inotify2 + or die "Unable to create new inotify object: $!"; + $inotify->watch($Rpad_ID, IN_CLOSE_WRITE, sub { + my $event = shift; + my $name = $event->name; + my $fullname = $event->fullname; + # run the input.R when it appears + if ( $name eq "input.R" ) { + # read R command from the input file + # $R->run_from_file would be cleaner, but it's a source(), so doesn't echo like the interactive session + #my $output_value = eval { $R->run_from_file($name); }; + open(my $fh, '<', $fullname) or die "Could not open file '$fullname' $!"; + # Slurp into a scalar + my $R_commands; + { local $/ = undef; $R_commands = <$fh>; } + close $fh; + my $output_value = eval { $R->run($R_commands); }; + + # convert any errors from R into the output text + if ( $@ ) { + $output_value = "$@"; + # remove first 3 lines for a cleaner error message + $output_value =~ s/^(?:.*\n){1,3}//; + # restart R (probably should test if really did stop) + &startR(); + } + # save output to file + my $filename = $Rpad_ID . "/output"; + open($fh, '>', $filename) or die "Could not open file '$filename' $!"; + print $fh "$output_value\n"; + close $fh; + } + elsif ( $name eq "theend" ) { + &cleanup(); + die "watch process terminated by request"; + } + }) or die "watch creation failed: $!"; + + # time out after 5 minutes + # Sys::SigAction or Time::Out work when script is run from commandline, but don't timeout under CGI + # instead, turn off blocking on inotify and use Time::HiRes + # http://www.perlmonks.org/?node_id=859287 + $inotify->blocking(0); + my $timelimit = 20; + my $end = time() + $timelimit; + while( time() < $end ) { + $inotify->poll; + sleep 0.1; + } + &cleanup(); + die "watch process reached timeout limit"; + + } + + # wait a second for R to start and to begin watch of + # input file before any R commands are sent + sleep 1; + +} + +elsif ($p_command eq 'logout') { + + # this creates a file signalling the end of Perl child process + my $filename = "theend"; + open(my $fh, '>', $filename) or die "Could not open file '$filename' $!"; + print $fh "\n"; + close $fh; + +} + +elsif ($p_command eq 'R_commands') { + + # process R commands + #my $R_commands = "print('abcxyz') \n\ndate()\n\n \n Sys.sleep(10)"; ## testing + my $R_commands = param('R_commands'); + # replace non-breaking spaces with regular spaces + $R_commands =~ s/\xA0/ /g; + + # save commands to the input file that is being watched by the child process + my $filename = $Rpad_ID . "/input.R"; + sub not_writable{ + @output_value="Input file not writable; timeout may have occurred.\nTry starting a new session by reloading the page.\n"; + print header; + print @output_value; + exit 1; + } + open(my $fh, '>', $filename) or ¬_writable(); + # split the string of commands on newlines + my @lines = split /\n/, $R_commands; + foreach my $line (@lines) { + # remove the trailing space(s), which seem to cause problems + $line =~ s/\ *$//g; + # blank lines also cause problems; remove them too + if ( $line ne "" ) { + print $fh "$line\n"; + } + } + close $fh; + + # set up inotify watch to grab output file or create message if tmpdir (Rpad_ID) was deleted while running R command + my $inotify = new Linux::Inotify2 + or die "Unable to create new inotify object: $!"; + # set up a watcher on an output file + $inotify->watch($Rpad_ID, IN_DELETE_SELF | IN_CLOSE_WRITE, sub { + my $event = shift; + my $name = $event->name; + my $fullname = $event->fullname; + if ( $event->IN_DELETE_SELF ) { + # TODO: test this, do we ever get here? + @output_value="Temporary directory was deleted while running R command; timeout may have occurred.\nTry starting a new session by reloading the page.\n"; + } + elsif ( $name eq "output" ) { + # read contents of output file into output_value + open(my $fh, '<', $fullname) or die "Could not open file '$fullname' $!"; + @output_value=<$fh>; + close $fh; + } + }) or die "watch creation failed: $!"; + + $inotify->poll; + +# this slows down response time considerably, so for now running of R commands is blocking +# # return a default message if the R process doesn't finish within 10 seconds +# @output_value = "10 seconds passed with no output from R ... back to you!\n"; +# $inotify->blocking(0); +# my $timelimit = 10; +# my $end = time() + $timelimit; +# while( time() < $end ) { +# $inotify->poll; +# sleep 0.01; +# } + +} + +print header; +print @output_value; Modified: pkg/Rpad/man/Rpad-package.Rd =================================================================== --- pkg/Rpad/man/Rpad-package.Rd 2014-01-02 15:39:42 UTC (rev 3) +++ pkg/Rpad/man/Rpad-package.Rd 2014-01-04 10:15:39 UTC (rev 4) @@ -1,6 +1,5 @@ \docType{package} \name{Rpad-package} -\alias{Rpad} \alias{Rpad-package} \title{Rpad} \description{ @@ -9,8 +8,8 @@ \details{ This manual describes the R functions that support the web interface. Other documentation is in the \dQuote{basehtml} directory. -The example below will launch a local web browser where you can read the documentation and view the demos. -You can continue to interact with the R console when the local HTTP server starts. +The example below will launch a browser where you can read that documentation and view the demos. +You can continue to use the R console after the local HTTP server starts. } \examples{ \dontrun{ From noreply at r-forge.r-project.org Sun Jan 5 15:58:57 2014 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Sun, 5 Jan 2014 15:58:57 +0100 (CET) Subject: [Rpad-commits] r5 - in pkg/Rpad: . R inst inst/basehtml inst/basehtml/server man Message-ID: <20140105145857.EE124186B07@r-forge.r-project.org> Author: jedick Date: 2014-01-05 15:58:57 +0100 (Sun, 05 Jan 2014) New Revision: 5 Added: pkg/Rpad/inst/basehtml/DojoEvents.Rpad pkg/Rpad/inst/basehtml/RpadWidgets.Rpad Removed: pkg/Rpad/inst/basehtml/RpadTest.Rpad Modified: pkg/Rpad/DESCRIPTION pkg/Rpad/NAMESPACE pkg/Rpad/R/Graphing.R pkg/Rpad/R/HtmlTree.R pkg/Rpad/R/LocalVersion.R pkg/Rpad/R/Rpad-internal.R pkg/Rpad/R/Util.R pkg/Rpad/inst/NEWS pkg/Rpad/inst/basehtml/BasicDocumentation.html pkg/Rpad/inst/basehtml/DojoTest.html pkg/Rpad/inst/basehtml/Example1.Rpad pkg/Rpad/inst/basehtml/InputExamples.Rpad pkg/Rpad/inst/basehtml/Rpad_body.js pkg/Rpad/inst/basehtml/index.html pkg/Rpad/inst/basehtml/server/R_process.pl pkg/Rpad/man/Rpad-internal.Rd pkg/Rpad/man/RpadGraphing.Rd pkg/Rpad/man/RpadHTML.Rd pkg/Rpad/man/RpadLocalServer.Rd pkg/Rpad/man/RpadUtil.Rd Log: consolidate graphing functions; add Dojo events demo Modified: pkg/Rpad/DESCRIPTION =================================================================== --- pkg/Rpad/DESCRIPTION 2014-01-04 10:15:39 UTC (rev 4) +++ pkg/Rpad/DESCRIPTION 2014-01-05 14:58:57 UTC (rev 5) @@ -1,6 +1,6 @@ Package: Rpad Title: Workbook-style, web-based interface to R -Version: 1.3.99.2 +Version: 1.3.99.3 Author: Tom Short (EPRI), Philippe Grosjean (UMH EcoNum), Jeffrey Dick Description: A workbook-style user interface to R through a web browser. Provides convenient interaction with an R process Modified: pkg/Rpad/NAMESPACE =================================================================== --- pkg/Rpad/NAMESPACE 2014-01-04 10:15:39 UTC (rev 4) +++ pkg/Rpad/NAMESPACE 2014-01-05 14:58:57 UTC (rev 5) @@ -5,7 +5,6 @@ Rpad, startRpadServer, stopRpadServer, - ROutputFormat, Html, H, HtmlTree, @@ -13,11 +12,6 @@ BR, HTMLon, HTMLoff, - HTMLh1, - HTMLh2, - HTMLh3, - HTMLh4, - HTMLh5, HTMLargs, HTMLtag, HTMLetag, @@ -31,12 +25,12 @@ graphoptions, newgraph, showgraph, - RpadPlotName, RpadURL, RpadBaseURL, RpadBaseFile, RpadIsLocal, - json + json, + RpadEnv ) S3method(json, default) Modified: pkg/Rpad/R/Graphing.R =================================================================== --- pkg/Rpad/R/Graphing.R 2014-01-04 10:15:39 UTC (rev 4) +++ pkg/Rpad/R/Graphing.R 2014-01-05 14:58:57 UTC (rev 5) @@ -1,198 +1,121 @@ # Rpad graphing functions -"graphoptions" <- function (..., reset = FALSE, override.check = TRUE) { - # set various Rpad graph options - # modified based on code from ps.options - l... <- length(new <- list(...)) - old <- check.options(new = new, envir = .RpadEnv, name.opt = ".RpadGraphOptions", - reset = as.logical(reset), assign.opt = l... > 0, override.check = override.check) - if (reset || l... > 0) - invisible(old) - else old -} +###################### +# internal functions # +###################### "newRpadPlotName" <- function(name = "") { # Create a new Rpad plot name # Updates the plot counter and name if (name == "") { - Counter <- get("Rpad.plot.counter", envir = .RpadEnv) - assign("Rpad.plot.counter", Counter + 1, envir = .RpadEnv) - name <- paste("Rpad_plot", Counter, sep="") + Counter <- get("plot.counter", envir = .RpadEnv) + assign("plot.counter", Counter + 1, envir = .RpadEnv) + name <- sprintf("Rpad_plot%03d", Counter) } - assign("Rpad.plot.name", name, envir = .RpadEnv) + assign("plot.name", name, envir = .RpadEnv) name } -"RpadPlotName" <- function() - get("Rpad.plot.name", envir = .RpadEnv) +GScmd <- function(name, invisible=FALSE, infile=paste(name, ".eps", sep = "")) { + # generate a ghostscript command + # set invisible=TRUE for windows + # set infile="" for output piped to command (see ?postscript) + GO <- graphoptions() + gsexe <- Sys.getenv("R_GSCMD") + if (is.null(gsexe) || nchar(gsexe) == 0) + gsexe <- ifelse(.Platform$OS.type == "windows", "gswin32c.exe", "gs") + if(invisible) gshelp <- system(paste(gsexe, "-help"), intern = TRUE, invisible = TRUE) + else gshelp <- system(paste(gsexe, "-help"), intern = TRUE) + st <- grep("^Available", gshelp) + en <- grep("^Search", gshelp) + gsdevs <- gshelp[(st + 1):(en - 1)] + devs <- c(strsplit(gsdevs, " "), recursive = TRUE) + if (match(GO$type, devs, 0) == 0) + stop(paste(paste("Device ", GO$type, "is not available"), + "Available devices are", paste(gsdevs, collapse = "\n"), + sep = "\n")) + cmd <- paste(gsexe, " -dNOPAUSE -dBATCH -q -sDEVICE=", GO$type, + " -r", GO$res, " -g", ceiling(GO$res * GO$width), "x", + ceiling(GO$res * GO$height), " -sOutputFile=", name, + ".", GO$extension, " ", infile, sep = "") +} - +"newDevice" <- function(name) { + # Open a new device. + # If it's an R graphics device, initiate it. + # If it's a ghostscript-based device, set up the ghostscript handling. + name <- newRpadPlotName(name) + GO <- graphoptions() + if (GO$type == "Rpng") { + # for builtin png support + png(filename = paste(name, ".png", sep=""), width = GO$width*GO$res, height = GO$height*GO$res) + } else if (GO$type == "pngalpha") { + # for a ghostscript device using bitmap + if (.Platform$OS.type == "windows") { + cmd <- NULL + } else { + cmd <- GScmd(name, infile="") + } + postscript(file = paste(name, ".eps", sep=""), width = GO$width, height = GO$height, + pointsize = GO$pointsize, + paper = "special", horizontal = FALSE, print.it = !is.null(cmd), + command = cmd) + } +} "closeCurrentDevice" <- function() { # Closes the current device and if the current device is postscript, # process the output with ghostscript to generate the desired output. - if (exists("RpadPlotParams", envir = .RpadEnv)) - p <- get("RpadPlotParams", envir = .RpadEnv) - else - return() - dev.set(p$dev) if (.Device == "postscript") { dev.off() if (.Platform$OS.type == "windows") { - gsexe <- Sys.getenv("R_GSCMD") - if (is.null(gsexe) || nchar(gsexe) == 0) - gsexe <- ifelse(.Platform$OS.type == "windows", "gswin32c.exe", "gs") - - gshelp <- system(paste(gsexe, "-help"), intern = TRUE, invisible = TRUE) - st <- grep("^Available", gshelp) - en <- grep("^Search", gshelp) - gsdevs <- gshelp[(st + 1):(en - 1)] - devs <- c(strsplit(gsdevs, " "), recursive = TRUE) - if (match(p$type, devs, 0) == 0) - stop(paste(paste("Device ", p$type, "is not available"), - "Available devices are", paste(gsdevs, collapse = "\n"), - sep = "\n")) - cmd <- paste(gsexe, " -dNOPAUSE -dBATCH -q -sDEVICE=", p$type, - " -r", p$res, " -g", ceiling(p$res * p$width), "x", - ceiling(p$res * p$height), " -sOutputFile=", p$name, - "-%03d.", p$extension, " ", p$name, ".eps", sep = "") + cmd <- GScmd(get("plot.name", envir = .RpadEnv), invisible=TRUE) system(cmd, intern = TRUE, invisible = TRUE) } - for (fun in getHook("closeRpadDevice")) try(fun()) } else if (.Device != "null device") { dev.off() - for (fun in getHook("closeRpadDevice")) try(fun()) } - assign("RpadPlotParams", NULL, envir = .RpadEnv) } -"newDevice" <- function(name, extension, type, res, width, height, deviceUsesPixels, pointsize, ...) { - # Open a new device. If it's a ghostscript-based device, set up the - # ghostscript handling. - # If it's an R graphics device, initiate it. - name <- newRpadPlotName(name) - assign("Rpad.plot.type", type, envir = .RpadEnv) - if (is.character(type) && type == "Rpng") { # for builtin png support - unlink(grep(paste(name,".*\\.png",sep=""), dir(), value=T)) - png(filename = paste(name,"-%03d.png",sep=""), width = width*res, height = height*res) - assign("RpadPlotParams", list(dev=dev.cur(), extension="png"), envir = .RpadEnv) - } else if (is.function(type)) { - # for an arbitrary R graphics device - unlink(grep(paste(name,".*\\.", extension, sep=""), dir(), value=T)) - funargs <- formals(type) - callargs <- list(file = paste(name, "-%03d.", extension, sep="")) - if (deviceUsesPixels) { - height <- height * res - width <- width * res - } - extraargs <- c(list(res = res, width = width, height = height, pointsize = pointsize), - list(...)) - if ("..." %in% names(funargs)) { - # the device function has a ..., so we (probably) can pass everything - callargs <- c(callargs, extraargs) - } else { - # remove arguments not used by this device function - callargs <- c(callargs, extraargs[intersect(names(extraargs), names(funargs))]) - } - do.call("type", callargs) - assign("RpadPlotParams", list(dev=dev.cur(), extension=extension), envir = .RpadEnv) - } else { - # for a ghostscript device using bitmap - unlink(grep(paste(name,".*\\.", extension,sep=""), dir(), value=T)) - if (.Platform$OS.type == "windows") { - cmd <- NULL - } else { - gsexe <- Sys.getenv("R_GSCMD") - if (is.null(gsexe) || nchar(gsexe) == 0) - gsexe <- ifelse(.Platform$OS.type == "windows", "gswin32c.exe", "gs") - gshelp <- system(paste(gsexe, "-help"), intern = TRUE) - st <- grep("^Available", gshelp) - en <- grep("^Search", gshelp) - gsdevs <- gshelp[(st + 1):(en - 1)] - devs <- c(strsplit(gsdevs, " "), recursive = TRUE) - if (match(type, devs, 0) == 0) - stop(paste(paste("Device ", type, "is not available"), - "Available devices are", paste(gsdevs, collapse = "\n"), - sep = "\n")) - cmd <- paste(gsexe, " -dNOPAUSE -dBATCH -q -sDEVICE=", type, - " -r", res, " -g", ceiling(res * width), "x", ceiling(res * - height), " -sOutputFile=", name, "-%03d.", extension, " ", sep = "") - } - postscript(file = paste(name,".eps",sep=""), width = width, height = height, - pointsize = pointsize, - paper = "special", horizontal = FALSE, print.it = !is.null(cmd), - command = cmd, ...) - assign("RpadPlotParams", - list(dev=dev.cur(), name=name, type=type, width=width, - height=height, res=res, extension=extension), envir = .RpadEnv) - } -} -"newgraph" <- function(name = "", extension = graphoptions()$extension, - type = graphoptions()$type, res = graphoptions()$res, - width = graphoptions()$width, height = graphoptions()$height, - deviceUsesPixels = graphoptions()$deviceUsesPixels, - pointsize = graphoptions()$pointsize, sublines = graphoptions()$sublines, - toplines = graphoptions()$toplines, ratio = graphoptions()$ratio, - leftlines = graphoptions()$leftlines, lwd = graphoptions()$lwd, ...) { -# Start a new Rpad graph. -# uses code from bitmap and from Frank Harrell's Hmisc routine setps - - if (width == 0 & height == 0) - width <- 3.5 - if (width > 0 & height == 0) - height <- width/ratio - if (width == 0 & height > 0) - width <- height * ratio - closeCurrentDevice() - newDevice(name, extension, type, res, width, height, deviceUsesPixels, pointsize, ...) +########################## +# user-visible functions # +########################## - par(lwd = lwd, mgp = c(2.5, 0.6, 0), - mar = c(3 + sublines + 0.25 * (sublines > 0) + - 0.5, 3 + leftlines + 0.5, toplines+.4, 1) + 0.1, - cex.main=1,font.main=1,las=1) - #require(lattice) +"graphoptions" <- function (..., reset = FALSE, override.check = TRUE) { + # set various Rpad graph options + # modified based on code from ps.options + l... <- length(new <- list(...)) + old <- check.options(new = new, envir = .RpadEnv, name.opt = "GraphOptions", + reset = as.logical(reset), assign.opt = l... > 0, override.check = override.check) + if (reset || l... > 0) + invisible(old) + else old +} -# lattice::lset(lattice::canonical.theme("postscript", color = TRUE)) - -# if (exists('xyplot')) { -# trellis.device(col=T) -# lset(list(axis.line=list(col="gray50"),axis.text=list(col="black"), -# strip.background=list(col="white"),strip.shingle=list(col="gray70"))) -# } - for (fun in getHook("newgraph")) try(fun()) +"newgraph" <- function(name = "") { + # Start a new Rpad graph. + closeCurrentDevice() + newDevice(name) + GO <- graphoptions() + par(lwd = GO$lwd, mgp = c(2.5, 0.6, 0), + mar = c(3 + GO$sublines + 0.25 * (GO$sublines > 0) + + 0.5, 3 + GO$leftlines + 0.5, GO$toplines+.4, 1) + 0.1, + cex.main=1, font.main=1, las=1) invisible() } # Start a new Rpad graph, and show the existing graph(s). -"showgraph" <- function(name = RpadPlotName(), link = FALSE, ...) { +"showgraph" <- function(name = get("plot.name", envir = .RpadEnv), link = FALSE, ...) { name newgraph() - for (n in dir(pattern = paste(name, ".*", get("RpadPlotParams", envir = .RpadEnv)$extension, sep=""))) + for (n in dir(pattern = paste(name, graphoptions()$extension, sep="."))) print(HTMLimg(n)) - if (link && # show a link to an EPS file if specified and if using the ghostscript graphics - get("Rpad.plot.type", envir = .RpadEnv) != "Rpng" && - !is.function(get("Rpad.plot.type", envir = .RpadEnv))) + # show a link to an EPS file if specified and if using the ghostscript graphics + if (link && graphoptions()$type == "pngalpha") cat("", "[EPS]", "\n", sep="") invisible() } - - -# Here's an example hook that you could use to add an EPS preview to eps files (requires epstool) - -#eps.add.preview <- function(fname) system(paste("epstool -n1 -b -t6p -zbmp256 -r200 -g\"gswin32c\" -o",fname,".eps ",fname,".eps",sep=""),show.output.on.console = TRUE) -# -#setHook("closeRpadDevice", function() { # add a tiff preview to an eps file -# name = RpadPlotName() -# if (length(dir(pattern=paste(name,".eps",sep=""))) == 1) -# eps.add.preview(name) -#}) - -### This will set the default graphics option to the GDD device: -# library(GDD) -# graphoptions(type = GDD) -### This is how you could change the pointsize on a GDD device: -# newgraph(ps = 10) # the default is 12 Modified: pkg/Rpad/R/HtmlTree.R =================================================================== --- pkg/Rpad/R/HtmlTree.R 2014-01-04 10:15:39 UTC (rev 4) +++ pkg/Rpad/R/HtmlTree.R 2014-01-05 14:58:57 UTC (rev 5) @@ -1,10 +1,3 @@ -# -# -# -# -# -# - "Html" <- function(x,...) { UseMethod("Html") } @@ -118,23 +111,6 @@ } -# broken: -#"HtmlTree.list" <- "Html.list" <- function (x, first = TRUE, ...) { -# res = rep(H("dum"), length = 2*length(x)) -# res[seq(1, 2*length(x), by = 2)] = H(NULL, names(x), collapseContents = FALSE) -# res[seq(2, 2*length(x), by = 2)] = sapply(x, FUN = function(x) -# H("ul", -# Html(x, first = FALSE))) -# if (first) # IE needs contenteditable off -# H("div", contentEditable='false', -# H("ul", -# H("li", -# H(NULL, res)))) -# else -# H("li", -# H(NULL, res)) -#} - "HTMLbutton" <- function(label = "Calculate", js = "rpad.calculatePage()", ...) # Other useful js parameters: # js = "rpad.calculateNext(this)" # calculate the next Rpad block @@ -193,7 +169,7 @@ H("a", href = url, ..., text)) -"HTMLimg" <- function(filename = RpadPlotName(), ...) +"HTMLimg" <- function(filename = get("plot.name", envir = .RpadEnv), ...) H("img", src = RpadURL(filename), ...) "HTMLembed" <- function(filename, width = 600, height = 600, ...) @@ -223,31 +199,12 @@ "BR" = function() H("br", standaloneTag = TRUE) #
    -"HTMLh1" <- function(text) { - H("h1", text) -} -"HTMLh2" <- function(text) { - H("h2", text) -} -"HTMLh3" <- function(text) { - H("h3", text) -} -"HTMLh4" <- function(text) { - H("h4", text) -} -"HTMLh5" <- function(text) { - H("h5", text) -} - "HTMLon" <- function() H("htmlon", standaloneTag = TRUE) "HTMLoff" <- function() H("htmloff", standaloneTag = TRUE) -"ROutputFormat" <- function(Format) - options(R.output.format = Format) - "HTMLtag" <- function(tagName, ...) { # outputs the given HTML tagName with arguments supplied in ... str <- paste("<", tagName, HTMLargs(list(...)), ">", sep = "", collapse = "") @@ -283,34 +240,3 @@ Html(x) } } - -"dojoTree" <- function(x, first = TRUE, ...) { - x <- as.list(x) - res <- sapply(seq(len = length(x)), - function(i) - H("div", dojoType="TreeNodeV3", ..., - title = names(x)[i], - if (is.list(x[[i]]) && !(any(class(x[[i]]) %in% gsub("^Html.","",methods(Html))))) - dojoTree(x[[i]], first = FALSE) - else - H("div", dojoType="TreeNodeV3", title = Html(x[[i]])))) - res <- paste(res, collapse="") # combine the list elements - if (first) { - H(NULL, - H("div", dojoType = "TreeBasicControllerV3", widgetId="controller"), - H("div", dojoType="TreeV3", listeners="controller", - res)) - } else { - res - } -} - -## ##tests for dojoTree -## x = list(a = 1:2, 44, b = list(a = 3:4, b = 6:5), c = data.frame(a=1:5, b = 11:15)) -## HTMLon() -## H("p", "A simple tree:") -## dojoTree(x) -## H("p", "An expanded version:") -## dojoTree(x, expandLevel = 2) -## H("p", "A bigger tree:") -## dojoTree(as.list(lm(1:10 ~ rnorm(10)))) Modified: pkg/Rpad/R/LocalVersion.R =================================================================== --- pkg/Rpad/R/LocalVersion.R 2014-01-04 10:15:39 UTC (rev 4) +++ pkg/Rpad/R/LocalVersion.R 2014-01-05 14:58:57 UTC (rev 5) @@ -1,19 +1,17 @@ # Rpad utility functions for running Rpad locally. # Here we use a local Tcl httpd server to receive Rpad commands. +# this is an internal function, but is exported to the package namespace +# so that it can be evaluated from within the Tcl scripts "processRpadCommands" <- function() { require("tcltk") commands <- tclvalue(.Tcl("set user(R_commands)")) textcommands <- textConnection(commands) - .dev.active <- dev.cur() - if (exists("RpadPlotParams", envir = .RpadEnv)) - dev.set( get("RpadPlotParams", envir = .RpadEnv)$dev ) - results <- tryCatch({ tc <- textConnection("textfromconnection",open="w") sink(file=tc) - guiSource(textcommands) + source(textcommands, print.eval=TRUE) sink() close(tc) # the result is R result text @@ -27,48 +25,38 @@ etext <- paste(paste(get("textfromconnection"), "\n", collapse=""), '\n', e) etext }, finally=close(textcommands)) - dev.set(.dev.active) formattedresults <- paste(results,"\n",sep="",collapse="") -# cat(formattedresults) escapeBrackets <- function(x) gsub("(\\{|\\})", "\\\\\\1", x) .Tcl(paste("set RpadTclResults {", escapeBrackets(formattedresults), "}", sep="")) } - "Rpad" <- -function(file = "", defaultfile = "index.html", port = 8079) { - startRpadServer(defaultfile, port) - browseURL(paste("http://127.0.0.1:", port, "/", file, sep = "")) +function(file = "", port = 8079, type="Rpng") { + # stop the local server if it's running + if(RpadIsLocal()) { + stopRpadServer() + WasRunning <- TRUE + } else WasRunning <- FALSE + # start the local server, set the graph type and browse to the default page + graphoptions(type=type) + startRpadServer(port=port) + if(!WasRunning) browseURL(paste("http://127.0.0.1:", port, "/", file, sep = "")) } "startRpadServer" <- -function(defaultfile = "index.html", port = 8079) { - require("tcltk") +function(file = "index.html", port = 8079) { # This is the main function that starts the server - # This function implements a basic http server on 'port' - # The server is written in Tcl. - # This way it is not blocking the R command-line! - if (!require("tcltk")) stop("package tcltk required for the local Rpad http server") assign("RpadLocal", TRUE, envir = .RpadEnv) assign("RpadDir", ".", envir = .RpadEnv) - assign("RpadPort", port, envir = .RpadEnv) - graphoptions(type = "Rpng") + # This implements a basic http server on 'port', written in Tcl. + # This way it is not blocking the R command-line! tclfile <- file.path(find.package(package = "Rpad"), "tcl", "mini1.1.tcl") htmlroot <- file.path(find.package(package = "Rpad"), "basehtml") tcl("source", tclfile) - tcl("Httpd_Server", htmlroot, port, defaultfile) - # delete the Rpad graphics files in the dir - unlink(dir(pattern="Rpad_plot.*\\.png")) - unlink(dir(pattern="Rpad_plot.*\\.eps")) - # turn on the interactive plotting device so as not to confuse the command-line user if they later plot - # ... but it's kind of distracting when Rpad starts so leave it off for now - #if(interactive() && .Device == "null device") x11() - #dev <- dev.cur() + tcl("Httpd_Server", htmlroot, port, file) # this initializes the png device for Rpad newgraph() - # switch back to the existing device to not confuse the user - #dev.set(dev) return(TRUE) } @@ -76,9 +64,6 @@ function() { require("tcltk") assign("RpadLocal", FALSE, envir = .RpadEnv) - # delete the Rpad graphics files in the dir - unlink(dir(pattern="Rpad_plot.*\\.png")) - unlink(dir(pattern="Rpad_plot.*\\.eps")) .Tcl("close $Httpd(listen)") .Tcl("unset Httpd") } Modified: pkg/Rpad/R/Rpad-internal.R =================================================================== --- pkg/Rpad/R/Rpad-internal.R 2014-01-04 10:15:39 UTC (rev 4) +++ pkg/Rpad/R/Rpad-internal.R 2014-01-05 14:58:57 UTC (rev 5) @@ -2,6 +2,9 @@ ".onLoad" <- function(lib, pkg) { + # create the RpadEnv environment + #attach(NULL, name=".RpadEnv") + # look for R2HTML package isR2HMTLAvailable <- length(find.package("R2HTML", quiet = TRUE)) != 0 if (isR2HMTLAvailable) { options(R2HTML.sortableDF = TRUE) @@ -13,39 +16,36 @@ .HTML.file <<- "" } # The following uses the environment variable DOCUMENT_ROOT with apache to find - # the directory of the R process. Change may be required for another server. - if (Sys.getenv("DOCUMENT_ROOT") != "") { # works for Apache 1.3 linux & win - RpadDir <- gsub(Sys.getenv("DOCUMENT_ROOT"), "", - getwd(), ignore.case = TRUE) # strip off the document root - } else if (Sys.getenv("SCRIPT_NAME") != "") { # for Apache 2.0 - RpadDir <- paste(gsub("R_process.pl", "", Sys.getenv("SCRIPT_NAME"), ignore.case = TRUE), - gsub(".*/", "", getwd()), - sep="") - } else if (Sys.getenv("PATH_INFO") != "") { # for microsoft IIS - RpadDir <- paste(gsub("R_process.pl", "", Sys.getenv("PATH_INFO"), ignore.case = TRUE), - gsub(".*/", "", getwd()), - sep="") - } else { - .rootdir = ifelse(.Platform$OS.type == "windows", "C:/www", "/var/www") - RpadDir <- gsub(.rootdir, "", getwd(), ignore.case = TRUE) - } + # the directory of the R process. Change may be required for another server. + if (Sys.getenv("DOCUMENT_ROOT") != "") { + # for Apache 1.3 linux & win + # strip off the document root + RpadDir <- gsub(Sys.getenv("DOCUMENT_ROOT"), "", getwd(), ignore.case = TRUE) + } else if (Sys.getenv("SCRIPT_NAME") != "") { + # for Apache 2.0 + RpadDir <- paste(gsub("R_process.pl", "", Sys.getenv("SCRIPT_NAME"), ignore.case = TRUE), + gsub(".*/", "", getwd()), sep="") + } else if (Sys.getenv("PATH_INFO") != "") { + # for microsoft IIS + RpadDir <- paste(gsub("R_process.pl", "", Sys.getenv("PATH_INFO"), ignore.case = TRUE), + gsub(".*/", "", getwd()), sep="") + } else { + .rootdir = ifelse(.Platform$OS.type == "windows", "C:/www", "/var/www") + RpadDir <- gsub(.rootdir, "", getwd(), ignore.case = TRUE) + } - options(R.output.format = "text") # do we need or want this anymore? If we do, why don't we put it in .RpadEnv? - - assign(".RpadGraphOptions", - list(type = "pngalpha", extension = "png", - res = 120, width = 0, height = 0, deviceUsesPixels = TRUE, pointsize = 10, - sublines = 0, toplines = .6, ratio = 4/3, leftlines = 0, lwd = 0.6), - envir = .RpadEnv) + assign("GraphOptions", + list(type = "pngalpha", extension = "png", + res = 120, width = 4, height = 3, deviceUsesPixels = TRUE, pointsize = 10, + sublines = 0, toplines = 0.6, leftlines = 0, lwd = 0.6), + envir = .RpadEnv) assign("RpadLocal", FALSE, envir = .RpadEnv) assign("RpadDir", RpadDir, envir = .RpadEnv) - assign("Rpad.plot.counter", 0, envir = .RpadEnv) + assign("plot.counter", 0, envir = .RpadEnv) } ".onUnload" <- function(libpath) { if (interactive()) stopRpadServer() } - -".packageName" <- "Rpad" Modified: pkg/Rpad/R/Util.R =================================================================== --- pkg/Rpad/R/Util.R 2014-01-04 10:15:39 UTC (rev 4) +++ pkg/Rpad/R/Util.R 2014-01-05 14:58:57 UTC (rev 5) @@ -1,94 +1,8 @@ # Rpad utility functions. -# this function is used to parse and evaluate the commands from an Rpad input block -"guiSource" <- -function (file, out.form = getOption("R.output.format"), local = FALSE, - echo = verbose, print.eval = TRUE, - verbose = getOption("verbose"), prompt.echo = getOption("prompt"), - max.deparse.length = 150, chdir = FALSE) -{ - eval.with.vis <- function(expr, envir = parent.frame(), enclos = if (is.list(envir) || - is.pairlist(envir)) - parent.frame()) withVisible(eval(expr, envir, - enclos)) - envir <- if (local) - parent.frame() - else .GlobalEnv - if (!missing(echo)) { - if (!is.logical(echo)) - stop("echo must be logical") - if (!echo && verbose) { - warning(paste("verbose is TRUE, echo not; ... coercing", - sQuote("echo <- TRUE"))) - echo <- TRUE - } - } - if (verbose) { - cat(sQuote("envir"), "chosen:") - print(envir) - } - Ne <- length(exprs <- parse(n = -1, file = file)) - if (verbose) - cat("--> parsed", Ne, "expressions; now eval(.)ing them:\n") - if (Ne == 0) - return(invisible()) - if (chdir && (path <- dirname(file)) != ".") { - owd <- getwd() - on.exit(setwd(owd)) - setwd(path) - } - if (echo) { - sd <- "\"" - nos <- "[^\"]*" - oddsd <- paste("^", nos, sd, "(", nos, sd, nos, sd, ")*", - nos, "$", sep = "") - } - for (i in 1:Ne) { - if (verbose) - cat("\n>>>> eval(expression_nr.", i, ")\n\t\t =================\n") - ei <- exprs[i] - if (echo) { - dep <- substr(paste(deparse(ei), collapse = "\n"), - 12, 1e+06) - nd <- nchar(dep) - 1 - do.trunc <- nd > max.deparse.length - dep <- substr(dep, 1, if (do.trunc) - max.deparse.length - else nd) - cat("\n", prompt.echo, dep, if (do.trunc) - paste(if (length(grep(sd, dep)) && length(grep(oddsd, - dep))) - " ...\" ..." - else " ....", "[TRUNCATED] "), "\n", sep = "") - } - yy <- eval.with.vis(ei, envir) - i.symbol <- mode(ei[[1]]) == "name" - if (!i.symbol) { - curr.fun <- ei[[1]][[1]] - if (verbose) { - cat("curr.fun:") - str(curr.fun) - } - } - if (verbose >= 2) { - cat(".... mode(ei[[1]])=", mode(ei[[1]]), "; paste(curr.fun)=") - str(paste(curr.fun)) - } - if ( yy$visible ) { - # always print, even if not shown for side effects - printoutput = capture.output(print(yy$value)) - if (out.form == "html" && exists("HTML")) - HTML(yy$value) - else if (out.form != "none") - cat(paste(printoutput,collapse="\n"),"\n") - } - if (verbose) - cat(" .. after ", sQuote(deparse(ei)), "\n", sep = "") - } - invisible(yy) -} +# for debugging, it's nice to have the .RpadEnv environment accessible +RpadEnv <- function() .RpadEnv - "RpadURL" <- function(filename = "") { # returns the URL for the given filename # "./filename" for the local version Modified: pkg/Rpad/inst/NEWS =================================================================== --- pkg/Rpad/inst/NEWS 2014-01-04 10:15:39 UTC (rev 4) +++ pkg/Rpad/inst/NEWS 2014-01-05 14:58:57 UTC (rev 5) @@ -1,4 +1,4 @@ -CHANGES IN Rpad 1.3.99.2 (2014-01-04) +CHANGES IN Rpad 1.3.99.3 (2014-01-05) ------------------------------------- - Restore Perl files related to server version of Rpad @@ -15,6 +15,9 @@ uses Linux:Inotify to become aware of R commands, and attempts to to self-destruct after 10 minutes. +- Remove guiSource() (used to parse and evaluate the commands from an + Rpad input block - R's source() suffices). + CHANGES IN Rpad 1.3.99.0 (2013-12-31) ------------------------------------- Modified: pkg/Rpad/inst/basehtml/BasicDocumentation.html =================================================================== --- pkg/Rpad/inst/basehtml/BasicDocumentation.html 2014-01-04 10:15:39 UTC (rev 4) +++ pkg/Rpad/inst/basehtml/BasicDocumentation.html 2014-01-05 14:58:57 UTC (rev 5) @@ -287,7 +287,15 @@
  • rpad.calculateNext(node) -- Calculates the first Rpad widget after or under the given DOM node
  • +

    Debugging hint: the dojo.js that is packaged with Rpad is an optimized (compressed) +version. To debug errors in the Javascript code using e.g. Firebug, it is easier +to use a non-compressed dojo.js. This can be built by setting layerOptimize: false +in app.profile.js and then building Dojo as outlined in the README (you will need +the complete Dojo source distribution). Then, place the un-optimized dojo.js +in your working directory and start Rpad; this new dojo.js will take precedence +over the one installed with the package.

    +

    Example

    Here is an example of a complete Rpad HTML file:

    Added: pkg/Rpad/inst/basehtml/DojoEvents.Rpad =================================================================== --- pkg/Rpad/inst/basehtml/DojoEvents.Rpad (rev 0) +++ pkg/Rpad/inst/basehtml/DojoEvents.Rpad 2014-01-05 14:58:57 UTC (rev 5) @@ -0,0 +1,115 @@ + + + + + + Dojo Events + + + + + + + + +

    Dojo Events

    + +

    (Modified from testDojoEvents.Rpad of Rpad 1.3.0)

    + +

    Normally, Rpad runs calculations on a page from top to bottom. With +Dojo's event system, you can change that and run things in different orders +or with different dependencies or to make interactions more dynamic. +The following example updates the top Rpad input block whenever you change the select +box created by the third Rpad input block.

    + + +
    +
    +# this block (id=rpad3) runs after the Rpad section below is finished
    +p = state.x77[sname, "Population"]
    +a = state.area[state.name==sname]
    +cat("population density of", sname, "is", 1000*p/a, "persons/sq.mile")
    +
    +
    +
    + +
    +
    +# this block (id=rpad2) runs when the select box is updated
    +HTMLon()
    +H("h3", sname)
    +Html(state.x77[sname, , drop=FALSE])
    +n <- n + 1
    +pop <- pop + state.x77[sname, "Population"]
    +BR()
    +cat("in the", n, "states selected so far, the total population is", pop, "thousand people")
    +
    +
    +
    + +
    +
    +# this block (id=rpad1) runs initially
    +pop <- n <- 0
    +data(state)
    +cat("Pick a state:")
    +HTMLon()
    +HTMLselect("sname", state.name, id="sNameSelect")
    +
    +
    +
    + + +
    + +

    Dojo Javascript code to tie the GUI together (normally, you'd hide this code):

    + + +
    +
    +require(["dojo/parser", "dojo/on", "dojo/dom", "dijit/registry", "dojo/aspect", "dojo/domReady!"],
    +function(parser, on, dom, registry, aspect){
    +
    +  // parsing the nodes is needed when using declarative syntax
    +  // http://dojotoolkit.org/documentation/tutorials/1.8/declarative/
    +  parser.parse();
    +
    +  // to make the select box automatically update the R variable
    +  // we watch for a change in the widget holding the select box
    +  var myWidget1 = registry.byId("rpad1");
    +  on(myWidget1, "change", function(evt){
    +
    +    var mySelect = dom.byId("sNameSelect");
    +    // here, set 'doit' (second argument) to true to force calculation of
    +    // a node with rpadRun="init" (which otherwise is calculated only on page load).
    +    rpad.calculateNode(mySelect, true)
    +
    +    // when the select is done updating (has a response from R), calculate "rpad2"
    +    var handle = aspect.after(mySelect, "onReceive", function(response){
    +      // to run just once, we remove this handle, otherwise the 'n' increments indefinitely
    +      handle.remove();
    +      //rpad.calculateNode("rpad2", true)
    +      var myWidget2 = registry.byId("rpad2");
    +      myWidget2.calculate();
    +    });
    +
    +    // when "rpad2" is done, calculate "rpad3"
    +    var myWidget2 = registry.byId("rpad2");
    +    on(myWidget2, "receive", function(evt) {
    +      var myWidget3 = registry.byId("rpad3");
    +      // set a 0.5s timeout to visually demonstrate the order of calculation
    +      setTimeout(function() { 
    +        myWidget3.calculate();
    +      }, 500);
    +    });
    +
    +  });
    +
    +});
    +
    +
    + + + + + Modified: pkg/Rpad/inst/basehtml/DojoTest.html =================================================================== --- pkg/Rpad/inst/basehtml/DojoTest.html 2014-01-04 10:15:39 UTC (rev 4) +++ pkg/Rpad/inst/basehtml/DojoTest.html 2014-01-05 14:58:57 UTC (rev 5) @@ -60,6 +60,7 @@ [TRUNCATED] To get the complete diff run: svnlook diff /svnroot/rpad -r 5