From afa24835f2a170c59a044dcf3bcf0ee765e8b568 Mon Sep 17 00:00:00 2001 From: Aaron Ecay 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 | 69 ++++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 51 insertions(+), 18 deletions(-) diff --git a/lisp/ob-R.el b/lisp/ob-R.el index 41b943c..fbd4af4 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,55 @@ 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) + (temp-buffer-show-function #'ignore)) + (ess-execute (format + " +.org.old.opts <- options(prompt = \"# Org babel prompt\\n\", continue = \"# Org babel prompt\\n\") +cat(\"# Org babel begin output\n\") +{ +%s +#ORG-BABEL-OOPS\"#' +} +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)) + (when (search-forward "ORG-BABEL-OOPS") + (user-error "Mismatched quotation marks in babel code; could not parse output.")) + (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