emacs-orgmode
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [O] R code block produces only partial output


From: Aaron Ecay
Subject: Re: [O] R code block produces only partial output
Date: Sat, 16 Aug 2014 01:05:00 -0400
User-agent: Notmuch/0.18.1+51~gbbbdf04 (http://notmuchmail.org) Emacs/24.4.50.2 (x86_64-unknown-linux-gnu)

Hi Chuck, hi all,

Attached to this message is a draft patch to complete this idea.  It
should address the issue of including warnings, errors, and messages in
output.

It uses the “evaluate” R package, originally created for the knitr
literate programming system, to do most of the heavy lifting, and
includes a new mechanism to load this package into babel sessions (and
to prompt the user to install it from CRAN, if not already installed).

It does not yet address Chuck’s first issue of remote sessions, just
because I haven’t had time to look at it in detail (but I still think it
should be easy, based on the code sample/hint that Chuck gave).

What do you think of the approach broadly?
>From ea99c10d148f71e5384144728a5714ecc5ae47ca Mon Sep 17 00:00:00 2001
From: Aaron Ecay <address@hidden>
Date: Sat, 16 Aug 2014 00:49:05 -0400
Subject: [PATCH] ob-R: overhaul handling of :output results type in a session
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* lisp/ob-R.el (org-babel-R-check-evaluate-package): New function.
(org-babel-R-initiate-session): Use it.
(org-babel-R-evaluate-session): Use the evaluate package to capture
session output.

This uses the “evaluate” R package[1] to capture the
output (incl. warnings, errors, and messages) from a babel R session.
This avoids the output showing up in the session buffer, and dodges
some previous issues with removing R prompts (>) when scraping the
output from the session buffer.

[1] <http://cran.r-project.org/web/packages/evaluate/index.html>
---
 lisp/ob-R.el | 68 +++++++++++++++++++++++++++++++++++++++++++-----------------
 1 file changed, 49 insertions(+), 19 deletions(-)

diff --git a/lisp/ob-R.el b/lisp/ob-R.el
index 41b943c..08ef9c2 100644
--- a/lisp/ob-R.el
+++ b/lisp/ob-R.el
@@ -245,6 +245,22 @@ This function is called by `org-babel-execute-src-block'."
          ((stringp  value) (format "%s <- %S" name (org-no-properties value)))
          (t                (format "%s <- %S" name (prin1-to-string value))))))
 
+(defvar ess-execute-in-process-buffer)
+(defun org-babel-R-check-evaluate-package (&optional recursive)
+  (save-window-excursion
+    (let ((ess-execute-in-process-buffer nil)
+         (r-buff (current-buffer)))
+      (ess-execute "library(evaluate)" nil "org-babel-R-auto")
+      (when (with-current-buffer "*org-babel-R-auto*"
+             (goto-char (point-min))
+             (search-forward "Error" nil t))
+       (if (and (not recursive)
+                (y-or-n-p "Cannot load the evaluate package required for babel 
session support, would you like to install it from CRAN?"))
+           (progn
+             (message "Downloading and installing package (may take some 
time)")
+             (ess-execute "install.packages(\"evaluate\")" nil 
"org-babel-R-auto")
+             (org-babel-R-check-evaluate-package t))
+         (user-error "R package evaluate is required, but not available."))))))
 
 (defvar ess-ask-for-ess-directory) ; dynamically scoped
 (defun org-babel-R-initiate-session (session params)
@@ -261,7 +277,9 @@ This function is called by `org-babel-execute-src-block'."
          (when (get-buffer session)
            ;; Session buffer exists, but with dead process
            (set-buffer session))
-         (require 'ess) (R)
+         (require 'ess)
+         (R)
+         (org-babel-R-check-evaluate-package)
          (rename-buffer
           (if (bufferp session)
               (buffer-name session)
@@ -366,7 +384,7 @@ last statement in BODY, as elisp."
 (defvar ess-eval-visibly-p)
 
 (defun org-babel-R-evaluate-session
-  (session body result-type result-params column-names-p row-names-p)
+    (session body result-type result-params column-names-p row-names-p)
   "Evaluate BODY in SESSION.
 If RESULT-TYPE equals 'output then return standard output as a
 string.  If RESULT-TYPE equals 'value then return the value of the
@@ -396,23 +414,35 @@ last statement in BODY, as elisp."
          (org-babel-import-elisp-from-file tmp-file '(16)))
        column-names-p)))
     (output
-     (mapconcat
-      'org-babel-chomp
-      (butlast
-       (delq nil
-            (mapcar
-             (lambda (line) (when (> (length line) 0) line))
-             (mapcar
-              (lambda (line) ;; cleanup extra prompts left in output
-                (if (string-match
-                     "^\\([ ]*[>+\\.][ ]?\\)+\\([[0-9]+\\|[ ]\\)" line)
-                    (substring line (match-end 1))
-                  line))
-              (org-babel-comint-with-output (session org-babel-R-eoe-output)
-                (insert (mapconcat 'org-babel-chomp
-                                   (list body org-babel-R-eoe-indicator)
-                                   "\n"))
-                (inferior-ess-send-input)))))) "\n"))))
+     (let* ((output-file (org-babel-temp-file "R-"))
+           (sentinel-file (concat output-file "-sentinel")))
+       (org-babel-comint-eval-invisibly-and-wait-for-file
+       session sentinel-file
+       (format
+"
+tryCatch(.org.eval.result <- evaluate(%S, new_device = FALSE, stop_on_error = 
0L),
+         finally = {
+             capture.output(
+                 withCallingHandlers(
+                     replay(Filter(function (x) !inherits(x, \"source\"),
+                                   .org.eval.result)),
+                     message = function (x) {
+                         cat(x$message);
+                         invokeRestart(\"muffleMessage\")
+                     }),
+                 file=%S)
+             file.create(%S)
+         })
+"
+               (org-babel-chomp body)
+               output-file
+               sentinel-file))
+       (with-temp-buffer
+        (insert-file-contents output-file)
+        (goto-char (point-min))
+        (flush-lines "^$")
+        (delete-trailing-whitespace)
+        (buffer-string))))))
 
 (defun org-babel-R-process-value-result (result column-names-p)
   "R-specific processing of return value.
-- 
2.0.4

Thanks,

-- 
Aaron Ecay

reply via email to

[Prev in Thread] Current Thread [Next in Thread]