Browse Source

R is working with no session

Eric Schulte 16 years ago
parent
commit
82ecab19fb
2 changed files with 119 additions and 87 deletions
  1. 46 27
      lisp/langs/org-babel-R.el
  2. 73 60
      org-babel.org

+ 46 - 27
lisp/langs/org-babel-R.el

@@ -96,43 +96,62 @@ R process in `org-babel-R-buffer'."
 
 
 (defun org-babel-R-initiate-session (session)
 (defun org-babel-R-initiate-session (session)
   "If there is not a current R process then create one."
   "If there is not a current R process then create one."
-  (setq session (or session "*R*"))
-  (if (org-babel-comint-buffer-livep session)
-      session
-    (save-window-excursion (R) (rename-buffer (if (bufferp session) (buffer-name session)
-                                                (if (stringp session) session (buffer-name)))) (current-buffer))))
+  (unless (string= session "none")
+    (setq session (or session "*R*"))
+    (if (org-babel-comint-buffer-livep session)
+        session
+      (save-window-excursion (R) (rename-buffer (if (bufferp session) (buffer-name session)
+                                                  (if (stringp session) session (buffer-name)))) (current-buffer)))))
 
 
 (defvar org-babel-R-eoe-indicator "'org_babel_R_eoe'")
 (defvar org-babel-R-eoe-indicator "'org_babel_R_eoe'")
 (defvar org-babel-R-eoe-output "[1] \"org_babel_R_eoe\"")
 (defvar org-babel-R-eoe-output "[1] \"org_babel_R_eoe\"")
+(defvar org-babel-R-wrapper-method "main <- function ()\n{\n%s\n}
+write.table(main(), file=\"%s\", sep=\"\\t\", na=\"nil\",row.names=FALSE, col.names=FALSE, quote=FALSE)")
 
 
 (defun org-babel-R-evaluate (buffer body result-type)
 (defun org-babel-R-evaluate (buffer body result-type)
   "Pass BODY to the R process in BUFFER.  If RESULT-TYPE equals
   "Pass BODY to the R process in BUFFER.  If RESULT-TYPE equals
 'output then return a list of the outputs of the statements in
 'output then return a list of the outputs of the statements in
 BODY, if RESULT-TYPE equals 'value then return the value of the
 BODY, if RESULT-TYPE equals 'value then return the value of the
 last statement in BODY."
 last statement in BODY."
-  (org-babel-comint-in-buffer buffer
-    (let* ((tmp-file (make-temp-file "org-babel-R"))
-           (last-value-eval
-            (format "write.table(.Last.value, file=\"%s\", sep=\"\\t\", na=\"nil\",row.names=FALSE, col.names=FALSE, quote=FALSE)"
-                    tmp-file))
-           (full-body (mapconcat #'org-babel-chomp (list body last-value-eval org-babel-R-eoe-indicator) "\n"))
-           (raw (org-babel-comint-with-output buffer org-babel-R-eoe-output nil
-                  (insert full-body) (inferior-ess-send-input)))
-           (results (let ((broke nil))
-                      (delete nil (mapcar (lambda (el)
-                                            (if (or broke
-                                                    (and (string-match (regexp-quote org-babel-R-eoe-output) el) (setq broke t)))
-                                                nil
-                                              (if (= (length el) 0)
+  (if (not session)
+      ;; external process evaluation
+      (let ((in-tmp-file (make-temp-file "R-in-functional-results"))
+            (out-tmp-file (make-temp-file "R-out-functional-results")))
+        (case result-type
+          (output
+           (with-temp-file in-tmp-file (insert body))
+           (message "R --slave --no-save < '%s' > '%s'" in-tmp-file out-tmp-file)
+           (shell-command-to-string (format "R --slave --no-save < '%s' > '%s'" in-tmp-file out-tmp-file)))
+          (value
+           (with-temp-file in-tmp-file
+             (insert (format org-babel-R-wrapper-method body out-tmp-file)))
+           (message "R --no-save < '%s'" in-tmp-file)
+           (shell-command (format "R --no-save < '%s'" in-tmp-file))))
+        (with-temp-buffer (insert-file-contents out-tmp-file) (buffer-string)))
+    ;; comint session evaluation
+    (org-babel-comint-in-buffer buffer
+      (let* ((tmp-file (make-temp-file "org-babel-R"))
+             (last-value-eval
+              (format "write.table(.Last.value, file=\"%s\", sep=\"\\t\", na=\"nil\",row.names=FALSE, col.names=FALSE, quote=FALSE)"
+                      tmp-file))
+             (full-body (mapconcat #'org-babel-chomp (list body last-value-eval org-babel-R-eoe-indicator) "\n"))
+             (raw (org-babel-comint-with-output buffer org-babel-R-eoe-output nil
+                    (insert full-body) (inferior-ess-send-input)))
+             (results (let ((broke nil))
+                        (delete nil (mapcar (lambda (el)
+                                              (if (or broke
+                                                      (and (string-match (regexp-quote org-babel-R-eoe-output) el) (setq broke t)))
                                                   nil
                                                   nil
-                                                (if (string-match comint-prompt-regexp el)
-                                                    (substring el (match-end 0))
-                                                  el))))
-                                          (mapcar #'org-babel-trim raw))))))
-      (case result-type
-        (output (org-babel-trim (mapconcat #'identity results "\n")))
-        (value (org-babel-trim (with-temp-buffer (insert-file-contents tmp-file) (buffer-string))))
-        (t (reverse results))))))
+                                                (if (= (length el) 0)
+                                                    nil
+                                                  (if (string-match comint-prompt-regexp el)
+                                                      (substring el (match-end 0))
+                                                    el))))
+                                            (mapcar #'org-babel-trim raw))))))
+        (case result-type
+          (output (org-babel-trim (mapconcat #'identity results "\n")))
+          (value (org-babel-trim (with-temp-buffer (insert-file-contents tmp-file) (buffer-string))))
+          (t (reverse results)))))))
 
 
 (provide 'org-babel-R)
 (provide 'org-babel-R)
 ;;; org-babel-R.el ends here
 ;;; org-babel-R.el ends here

+ 73 - 60
org-babel.org

@@ -114,7 +114,7 @@ table, allowing the test suite to be run be evaluation of the table
 and the results to be collected in the same table.
 and the results to be collected in the same table.
 
 
 
 
-* Tasks [25/42]
+* Tasks [26/42]
 ** TODO add a function to jump to a source-block by name
 ** TODO add a function to jump to a source-block by name
    I've had an initial stab at that in org-babel-find-named-block
    I've had an initial stab at that in org-babel-find-named-block
    (library-of-babel branch).
    (library-of-babel branch).
@@ -497,65 +497,6 @@ tabel
 
 
 Another example is in the [[*operations%20in%20on%20tables][grades example]].
 Another example is in the [[*operations%20in%20on%20tables][grades example]].
 
 
-** PROPOSED add =:none= session argument (for purely functional execution) [3/4]
-This would allow source blocks to be run in their own new process
-
-- These blocks could then also be run in the background (since we can
-  detach and just wait for the process to signal that it has terminated)
-- We wouldn't be drowning in session buffers after running the tests
-- we can re-use much of the session code to run in a more /functional/
-  mode
-
-While session provide a lot of cool features, like persistent
-environments, [[* DONE function to bring up inferior-process buffer][pop-to-session]], and hints at exportation for
-org-babel-tangle, they also have some down sides and I'm thinking that
-session-based execution maybe shouldn't be the default behavior.
-
-Down-sides to sessions
-- *much* more complicated than functional evaluation
-  - maintaining the state of the session has weird issues
-  - waiting for evaluation to finish
-  - prompt issues like [[* TODO weird escaped characters in shell prompt break shell evaluation][shell-prompt-escapes-bug]]
-- can't run in background
-- litter emacs with session buffers
-
-*** DONE ruby
-
-#+srcname: ruby-task-no-session
-#+begin_src ruby :results replace output
-puts :eric
-puts :schulte
-[1, 2, 3]
-#+end_src
-
-#+resname: ruby-task-no-session
-| "eric"    |
-| "schulte" |
-*** DONE python
-
-#+srcname: task-python-none-session
-#+begin_src python :session none :results replace value
-print 'something'
-print 'output'
-[1, 2, 3]
-#+end_src
-
-#+resname: task-python-none-session
-| 1 | 2 | 3 |
-
-*** DONE sh
-
-#+srcname: task-session-none-sh
-#+begin_src sh :results replace
-echo "first"
-echo "second"
-#+end_src
-
-#+resname: task-session-none-sh
-| "first"  |
-| "second" |
-
-*** TODO R
 ** PROPOSED Are we happy with current behaviour regarding vector/scalar output?
 ** PROPOSED Are we happy with current behaviour regarding vector/scalar output?
 This simple example of multilingual chaining produces vector output if
 This simple example of multilingual chaining produces vector output if
 there are spaces in the message and scalar otherwise.
 there are spaces in the message and scalar otherwise.
@@ -806,6 +747,78 @@ $0
 
 
 waiting for guidance from those more familiar with yasnippets
 waiting for guidance from those more familiar with yasnippets
 
 
+** DONE add =:none= session argument (for purely functional execution) [4/4]
+This would allow source blocks to be run in their own new process
+
+- These blocks could then also be run in the background (since we can
+  detach and just wait for the process to signal that it has terminated)
+- We wouldn't be drowning in session buffers after running the tests
+- we can re-use much of the session code to run in a more /functional/
+  mode
+
+While session provide a lot of cool features, like persistent
+environments, [[* DONE function to bring up inferior-process buffer][pop-to-session]], and hints at exportation for
+org-babel-tangle, they also have some down sides and I'm thinking that
+session-based execution maybe shouldn't be the default behavior.
+
+Down-sides to sessions
+- *much* more complicated than functional evaluation
+  - maintaining the state of the session has weird issues
+  - waiting for evaluation to finish
+  - prompt issues like [[* TODO weird escaped characters in shell prompt break shell evaluation][shell-prompt-escapes-bug]]
+- can't run in background
+- litter emacs with session buffers
+
+*** DONE ruby
+
+#+srcname: ruby-task-no-session
+#+begin_src ruby :results replace output
+puts :eric
+puts :schulte
+[1, 2, 3]
+#+end_src
+
+#+resname: ruby-task-no-session
+| "eric"    |
+| "schulte" |
+*** DONE python
+
+#+srcname: task-python-none-session
+#+begin_src python :session none :results replace value
+print 'something'
+print 'output'
+[1, 2, 3]
+#+end_src
+
+#+resname: task-python-none-session
+| 1 | 2 | 3 |
+
+*** DONE sh
+
+#+srcname: task-session-none-sh
+#+begin_src sh :results replace
+echo "first"
+echo "second"
+#+end_src
+
+#+resname: task-session-none-sh
+| "first"  |
+| "second" |
+
+*** DONE R
+
+#+srcname: task-no-session-R
+#+begin_src R :results replace output
+a <- 8
+b <- 9
+a + b
+b - a
+#+end_src
+
+#+resname: task-no-session-R
+| "[1]" | 17 |
+| "[1]" |  1 |
+
 ** DONE fully purge org-babel-R of direct comint interaction
 ** DONE fully purge org-babel-R of direct comint interaction
 try to remove all code under the [[file:lisp/org-babel-R.el::functions%20for%20evaluation%20of%20R%20code][;; functions for evaluation of R code]] line
 try to remove all code under the [[file:lisp/org-babel-R.el::functions%20for%20evaluation%20of%20R%20code][;; functions for evaluation of R code]] line