From mboxrd@z Thu Jan 1 00:00:00 1970 From: Aaron Ecay Subject: Re: R code block produces only partial output Date: Sat, 16 Aug 2014 01:05:00 -0400 Message-ID: <87wqa9owhv.fsf@gmail.com> References: <87iom8zd24.fsf@gmail.com> <877g2oz9gv.fsf@gmail.com> <87lhr27oap.fsf@gmail.com> <87r40uwavs.fsf@gmail.com> <8761i5kg8f.fsf@gmail.com> <87ppgcrg8n.fsf@gmail.com> <87lhr0qimr.fsf@gmail.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Return-path: Received: from eggs.gnu.org ([2001:4830:134:3::10]:53994) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XIWAv-0004mk-QK for emacs-orgmode@gnu.org; Sat, 16 Aug 2014 01:05:15 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1XIWAq-0002hf-Aa for emacs-orgmode@gnu.org; Sat, 16 Aug 2014 01:05:09 -0400 Received: from mail-qa0-x236.google.com ([2607:f8b0:400d:c00::236]:57340) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XIWAq-0002g3-3U for emacs-orgmode@gnu.org; Sat, 16 Aug 2014 01:05:04 -0400 Received: by mail-qa0-f54.google.com with SMTP id k15so2810817qaq.27 for ; Fri, 15 Aug 2014 22:05:03 -0700 (PDT) In-Reply-To: <87lhr0qimr.fsf@gmail.com> List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org Sender: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org To: "Charles C. Berry" Cc: emacs-orgmode@gnu.org --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable 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 =E2=80=9Cevaluate=E2=80=9D R package, originally created for th= e 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=E2=80=99s first issue of remote sessions, just because I haven=E2=80=99t had time to look at it in detail (but I still thi= nk it should be easy, based on the code sample/hint that Chuck gave). What do you think of the approach broadly? --=-=-= Content-Type: text/x-diff; charset=utf-8 Content-Disposition: inline; filename=0001-ob-R-overhaul-handling-of-output-results-type-in-a-s.patch Content-Transfer-Encoding: quoted-printable >From ea99c10d148f71e5384144728a5714ecc5ae47ca 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 sessi= on MIME-Version: 1.0 Content-Type: text/plain; charset=3DUTF-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 =E2=80=9Cevaluate=E2=80=9D 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] --- 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-bloc= k'." ((stringp value) (format "%s <- %S" name (org-no-properties value))) (t (format "%s <- %S" name (prin1-to-string value)))))) =20 +(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.")))))) =20 (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) =20 (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 =3D FALSE, stop_on_er= ror =3D 0L), + finally =3D { + capture.output( + withCallingHandlers( + replay(Filter(function (x) !inherits(x, \"source\"), + .org.eval.result)), + message =3D function (x) { + cat(x$message); + invokeRestart(\"muffleMessage\") + }), + file=3D%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)))))) =20 (defun org-babel-R-process-value-result (result column-names-p) "R-specific processing of return value. --=20 2.0.4 --=-=-= Content-Type: text/plain Thanks, -- Aaron Ecay --=-=-=--