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, 23 Aug 2014 04:32:03 -0400
User-agent: Notmuch/0.18.1+51~gbbbdf04 (http://notmuchmail.org) Emacs/24.4.50.2 (x86_64-unknown-linux-gnu)

2014ko abuztuak 19an, Achim Gratz-ek idatzi zuen:
> 
> Aaron Ecay writes:
>> R is capable of installing packages to a user-specified directory,
>> without requiring root or any other special privileges.  So IT cannot
>> literally prevent R users from installing their own packages;
> 
> They can, all they have to do is to take away the ability to connect to
> the outside network and that's what is increasingly being done (for
> other reasons, mind you).
> 
>> the requirement must rather come as a statement of policy.
> 
> That is another common thing, if only to shift the responsibility if the
> other measures don't actually prevent that.
> 
>> I’d like to
>> understand more about how such regimes work and how org could work
>> with them, ideally from people who have direct experience with them.
> 
> Ideally, don't require the use of a non-core package.  The beef with
> things like CTAN, CRAN or CPAN is that they require extra maintenance
> beyond the pure installation of some software and some specific
> knowledge of the software in question and that's just not going to
> happen in some places.
> 
>> Otherwise, it would be disappointing if the fear that an unidentifiable
>> somebody somewhere might not be able to install R packages derailed the
>> improvement of babel’s R support.
> 
> The request was to keep a fallback to core.  I have no comment at this
> time if it would be possible or not.  Since ultimately it's the session
> support of Emacs that is clunky (and that affects most other languages
> as well), maybe an effort to improve that would be more generally
> helpful than working around it in different ways in each language.

Well, I think that it’s going to be difficult to make babel a better
literate programming solution for R if we restrict ourselves not to
use the state-of-the-art R package for low-level literate programming
support.  Org is full of features which one needs to install other
software to use, and I’m comfortable with the idea that babel’s R
support should require the evaluate package.  However, it’s difficult
to argue this point of view when no one has spoken up about their own
requirements, and a spirit of conservatism in the face of vague
imagined difficulties persists.

The attached patch fixes the problem that touched off this thread.
It’s only debatably nicer than the present approach, but it has the
independently desirable property of segregating babel-driven output
from the session buffer.  It incorporates what I think is a fix for
the tramp bug Charles pointed out.

It’s as yet only lightly tested, and as always comments are welcome.
>From 5f3b4ec203b8bc14c3da975368481c3767ab6f02 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

* (org-babel-R-evaluate-session): Capture output using ‘ess-execute’.

This function dumps the output from R into a buffer; we then use some
tricks to clean it of spurious text.
---
 lisp/ob-R.el | 63 +++++++++++++++++++++++++++++++++++++++++++-----------------
 1 file changed, 45 insertions(+), 18 deletions(-)

diff --git a/lisp/ob-R.el b/lisp/ob-R.el
index 41b943c..2d8220b 100644
--- a/lisp/ob-R.el
+++ b/lisp/ob-R.el
@@ -364,9 +364,10 @@ last statement in BODY, as elisp."
     (output (org-babel-eval org-babel-R-command body))))
 
 (defvar ess-eval-visibly-p)
+(defvar ess-execute-in-process-buffer)
 
 (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 +397,49 @@ 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* ((sentinel-file (org-babel-temp-file "R-")))
+       ;; This code borrowed from
+       ;; `org-babel-comint-eval-invisibly-and-wait-for-file'
+       (unless (org-babel-comint-buffer-livep session)
+        (error "Buffer %s does not exist or has no process" session))
+       (if (file-exists-p sentinel-file) (delete-file sentinel-file))
+       (with-current-buffer session
+        (let ((ess-execute-in-process-buffer nil))
+          (ess-execute (format
+                        "
+.org.old.opts <- options(prompt = \"# Org babel prompt\\n\", continue = \"# 
Org babel prompt\\n\")
+cat(\"# Org babel begin output\n\")
+%s
+cat(\"# Org babel end output\n\")
+options(.org.old.opts)
+rm(.org.old.opts)
+file.create(%S)
+"
+                        (org-babel-chomp body)
+                        (if (tramp-tramp-file-p sentinel-file)
+                            (tramp-file-name-localname
+                             (tramp-dissect-file-name sentinel-file))
+                          sentinel-file))
+                       nil "org-babel-R-output"))
+        ;; From Tramp 2.1.19 the following cache flush is not necessary
+        (if (file-remote-p default-directory)
+            (let (v)
+              (with-parsed-tramp-file-name default-directory nil
+                (tramp-flush-directory-property v "")))))
+       (while (not (file-exists-p sentinel-file)) (sit-for 0.25))
+       ;; End borrowed code.
+       (with-current-buffer "*org-babel-R-output*"
+        (goto-char (point-min))
+        (search-forward "# Org babel begin output")
+        (delete-region (point-min) (1+ (point)))
+        (goto-char (point-max))
+        (search-backward "# Org babel end output")
+        (delete-region (point) (point-max))
+        (goto-char (point-min))
+        (flush-lines "^$")
+        (flush-lines "^# Org babel prompt$")
+        (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

-- 
Aaron Ecay

reply via email to

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