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
                 "\\([ \t]+\\([^\n]+\\)\\)?\n" ;; match header arguments
                 "\\([^\000]+?\\)#\\+end_src")))
                 "\\([^\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 '()
 (defcustom litorgy-interpreters '()
   "Interpreters allows for evaluation tags.
   "Interpreters allows for evaluation tags.
 This is a list of program names (as strings) that can evaluate code and
 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
 sh         Pass command to the shell and display the result
 perl       The perl interpreter
 perl       The perl interpreter
 python     The python 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
   :group 'litorgy
   :set 'litorgy-set-interpreters
   :set 'litorgy-set-interpreters
   :type '(set :greedy t
   :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
      AIUI The following can all be viewed as implementations of
      org-eval-buffer for R code:
      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
 ***** org-eval-light
       This is the beginnings of a general evaluation mechanism, that
       This is the beginnings of a general evaluation mechanism, that
@@ -591,6 +593,15 @@ print "Hello world!"
 #+end_src
 #+end_src
 
 
 
 
+** litorgy-R
+
+#+begin_src R :replace t
+a <- 9
+b <- 18
+a + b
+#+end_src
+
+
 ** free variables
 ** free variables
 
 
 First assign the variable with some sort of interpreted line
 First assign the variable with some sort of interpreted line