Browse Source

adding R support for litorgy

Eric Schulte 16 years ago
parent
commit
715998c107
3 changed files with 142 additions and 1 deletions
  1. 118 0
      litorgy/litorgy-R.el
  2. 13 1
      litorgy/litorgy.el
  3. 11 0
      rorg.org

+ 118 - 0
litorgy/litorgy-R.el

@@ -0,0 +1,118 @@
+;;; litorgy-R.el --- litorgy functions for R code evaluation
+
+;; Copyright (C) 2009 Eric Schulte, Dan Davison, Austin F. Frank
+
+;; Author: Eric Schulte, Dan Davison, Austin F. Frank
+;; Keywords: literate programming, reproducible research
+;; Homepage: http://orgmode.org
+;; Version: 0.01
+
+;;; License:
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+;;
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; Litorgy support for evaluating R code
+
+;;; Code:
+(require 'litorgy)
+
+(litorgy-add-interpreter "R")
+
+(defun litorgy-execute:R (body params)
+  "Execute a block of R code with litorgy.  This function is
+called by `litorgy-execute-src-block'."
+  (let (results)
+    (message "executing R code block...")
+    (litorgy-initiate-R-buffer)
+    (mapc (lambda (line) (litorgy-R-input-command line)) (butlast (split-string body "[\r\n]")))
+    (litorgy-R-last-output)
+    ;; ;; using litorgy-R-region-to-string
+    ;; (with-temp-buffer
+    ;;   (insert body)
+    ;;   (setq results (litorgy-R-region-to-string (point-min) (point-max)))
+    ;;   (message "finished executing R code block")
+    ;;   results)
+    ))
+
+;; Maybe the following be replaced with a method using `ess-execute',
+;; I went with the following functions because I wrote them and they
+;; are what I know
+;;
+;; (not the best reasons for making design decisions)
+
+(defvar litorgy-R-buffer nil
+  "Holds the buffer for the current R process")
+
+(defun litorgy-initiate-R-buffer ()
+  "If there is not a current R process then create one."
+  (unless (and (buffer-live-p litorgy-R-buffer) (get-buffer litorgy-R-buffer))
+    (save-excursion
+      (R)
+      (setf litorgy-R-buffer (current-buffer))
+      (litorgy-R-wait-for-output)
+      (litorgy-R-input-command ""))))
+
+(defun litorgy-R-command-to-string (command)
+  "Send a command to R, and return the results as a string."
+  (litorgy-R-input-command command)
+  (litorgy-R-last-output))
+
+(defun litorgy-R-input-command (command)
+  "Pass COMMAND to the R process running in `litorgy-R-buffer'."
+  (save-excursion
+    (save-match-data
+      (set-buffer litorgy-R-buffer)
+      (goto-char (process-mark (get-buffer-process (current-buffer))))
+      (insert command)
+      (comint-send-input)
+      (litorgy-R-wait-for-output))))
+
+(defun litorgy-R-region-to-string (start end)
+  "Send a region to R, and return the results as a string."
+  (interactive "r")
+  (comint-send-region (get-buffer-process litorgy-R-buffer) start end)
+  (litorgy-R-wait-for-output)
+  (litorgy-R-last-output))
+
+(defun litorgy-R-wait-for-output ()
+  "Wait until output arrives"
+  (save-excursion
+    (save-match-data
+      (set-buffer litorgy-R-buffer)
+      (while (progn
+	       (goto-char comint-last-input-end)
+	       (not (re-search-forward comint-prompt-regexp nil t)))
+	(accept-process-output (get-buffer-process (current-buffer)))))))
+
+(defun litorgy-R-last-output ()
+  "Return the last R output as a string"
+  (save-excursion
+    (save-match-data
+      (set-buffer litorgy-R-buffer)
+      (goto-char (process-mark (get-buffer-process (current-buffer))))
+      (forward-line 0)
+      (let ((raw (buffer-substring comint-last-input-end (- (point) 1))))
+	(if (string-match "\n" raw)
+	    raw
+	  (and (string-match "\\[[[:digit:]+]\\] *\\(.*\\)$" raw)
+	       (message raw)
+	       (message (match-string 1 raw))
+	       (match-string 1 raw)))))))
+
+(provide 'litorgy-R)
+;;; litorgy-R.el ends here

+ 13 - 1
litorgy/litorgy.el

@@ -56,6 +56,13 @@ so then run `litorgy-execute-src-block'."
                 "\\([ \t]+\\([^\n]+\\)\\)?\n" ;; match header arguments
                 "\\([^\000]+?\\)#\\+end_src")))
 
+(defun litorgy-add-interpreter (interpreter)
+  "Add INTERPRETER to `litorgy-interpreters' and update
+`litorgy-src-block-regexp' appropriately."
+  (unless (member interpreter litorgy-interpreters)
+    (setq litorgy-interpreters (cons interpreter litorgy-interpreters))
+    (litorgy-set-interpreters 'litorgy-interpreters litorgy-interpreters)))
+
 (defcustom litorgy-interpreters '()
   "Interpreters allows for evaluation tags.
 This is a list of program names (as strings) that can evaluate code and
@@ -66,7 +73,12 @@ emacs-lisp Evaluate Emacs Lisp code and display the result
 sh         Pass command to the shell and display the result
 perl       The perl interpreter
 python     The python interpreter
-ruby       The ruby interpreter"
+ruby       The ruby interpreter
+
+The source block regexp `litorgy-src-block-regexp' is updated
+when a new interpreter is added to this list through the
+customize interface.  To add interpreters to this variable from
+lisp code use the `litorgy-add-interpreter' function."
   :group 'litorgy
   :set 'litorgy-set-interpreters
   :type '(set :greedy t

+ 11 - 0
rorg.org

@@ -87,6 +87,8 @@ The main objectives of this project are...
     
      AIUI The following can all be viewed as implementations of
      org-eval-buffer for R code:
+
+     (see this question again posed in [[file:litorgy/litorgy-R.el::Maybe%20the%20following%20be%20replaced%20with%20a%20method%20using%20ess%20execute][litorgy-R.el]])
     
 ***** org-eval-light
       This is the beginnings of a general evaluation mechanism, that
@@ -591,6 +593,15 @@ print "Hello world!"
 #+end_src
 
 
+** litorgy-R
+
+#+begin_src R :replace t
+a <- 9
+b <- 18
+a + b
+#+end_src
+
+
 ** free variables
 
 First assign the variable with some sort of interpreted line