babel: Provide notification of errors during code execution
This deals with external process :results value mode for R, ruby, python, perl and clojure: if the shell process has a non-zero exit code, a buffer containing stderr is displayed.
This commit is contained in:
parent
4e9a2d4efd
commit
ba4d698fa1
|
@ -142,18 +142,22 @@ BODY, if RESULT-TYPE equals 'value then return the value of the
|
|||
last statement in BODY, as elisp."
|
||||
(if (not session)
|
||||
;; external process evaluation
|
||||
(let ((tmp-file (make-temp-file "R-out-functional-results")))
|
||||
(case result-type
|
||||
(output
|
||||
(with-temp-buffer
|
||||
(insert body)
|
||||
(org-babel-shell-command-on-region (point-min) (point-max) "R --slave --no-save" 'current-buffer 'replace)
|
||||
(buffer-string)))
|
||||
(value
|
||||
(with-temp-buffer
|
||||
(insert (format org-babel-R-wrapper-method
|
||||
body tmp-file (if column-names-p "TRUE" "FALSE")))
|
||||
(org-babel-shell-command-on-region (point-min) (point-max) "R --no-save"))
|
||||
(case result-type
|
||||
(output
|
||||
(with-temp-buffer
|
||||
(insert body)
|
||||
(org-babel-shell-command-on-region (point-min) (point-max) "R --slave --no-save" 'current-buffer 'replace)
|
||||
(buffer-string)))
|
||||
(value
|
||||
(let* ((tmp-file (make-temp-file "R-out-functional-results")) exit-code
|
||||
(stderr
|
||||
(with-temp-buffer
|
||||
(insert (format org-babel-R-wrapper-method
|
||||
body tmp-file (if column-names-p "TRUE" "FALSE")))
|
||||
(setq exit-code (org-babel-shell-command-on-region
|
||||
(point-min) (point-max) "R --no-save" nil 'replace (current-buffer)))
|
||||
(buffer-string))))
|
||||
(if (> exit-code 0) (org-babel-error-notify exit-code stderr))
|
||||
(org-babel-R-process-value-result
|
||||
(org-babel-import-elisp-from-file (org-babel-maybe-remote-file tmp-file))
|
||||
column-names-p))))
|
||||
|
|
|
@ -219,25 +219,27 @@ or nil if \"none\" is specified"
|
|||
|
||||
(defun org-babel-clojure-evaluate-external-process (buffer body &optional result-type)
|
||||
"Evaluate the body in an external process."
|
||||
(save-window-excursion
|
||||
(case result-type
|
||||
(output
|
||||
(with-temp-buffer
|
||||
(insert body)
|
||||
(org-babel-shell-command-on-region
|
||||
(point-min) (point-max)
|
||||
(format "%s - " (mapconcat #'identity (org-babel-clojure-babel-clojure-cmd) " "))
|
||||
'current-buffer 'replace)
|
||||
(buffer-string)))
|
||||
(value
|
||||
(let ((tmp-results-file (make-temp-file "clojure_babel_results_")))
|
||||
(with-temp-buffer
|
||||
(insert (format org-babel-clojure-wrapper-method body tmp-results-file tmp-results-file))
|
||||
(org-babel-shell-command-on-region
|
||||
(point-min) (point-max)
|
||||
(format "%s - " (mapconcat #'identity (org-babel-clojure-babel-clojure-cmd) " "))))
|
||||
(org-babel-clojure-table-or-string
|
||||
(with-temp-buffer (insert-file-contents (org-babel-maybe-remote-file tmp-results-file)) (buffer-string))))))))
|
||||
(save-excursion
|
||||
(let ((cmd (format "%s -" (mapconcat #'identity (org-babel-clojure-babel-clojure-cmd) " "))))
|
||||
(case result-type
|
||||
(output
|
||||
(with-temp-buffer
|
||||
(insert body)
|
||||
(org-babel-shell-command-on-region cmd (point-min) (point-max) 'current-buffer 'replace)
|
||||
(buffer-string)))
|
||||
(value
|
||||
(let* ((tmp-file (make-temp-file "org-babel-clojure-results-")) exit-code
|
||||
(stderr
|
||||
(with-temp-buffer
|
||||
(insert
|
||||
(format org-babel-clojure-wrapper-method body tmp-file tmp-file))
|
||||
(setq exit-code
|
||||
(org-babel-shell-command-on-region (point-min) (point-max) cmd nil 'replace (current-buffer)))
|
||||
(buffer-string))))
|
||||
(if (> exit-code 0) (org-babel-error-notify exit-code stderr))
|
||||
(org-babel-clojure-table-or-string
|
||||
(with-temp-buffer
|
||||
(insert-file-contents (org-babel-maybe-remote-file tmp-file)) (buffer-string)))))))))
|
||||
|
||||
(defun org-babel-clojure-evaluate-session (buffer body &optional result-type)
|
||||
"Evaluate the body in the context of a clojure session"
|
||||
|
|
|
@ -92,7 +92,7 @@ BODY, if RESULT-TYPE equals 'value then return the value of the
|
|||
last statement in BODY, as elisp."
|
||||
(if (not session)
|
||||
;; external process evaluation
|
||||
(save-window-excursion
|
||||
(save-excursion
|
||||
(case result-type
|
||||
(output
|
||||
(with-temp-buffer
|
||||
|
@ -101,20 +101,25 @@ last statement in BODY, as elisp."
|
|||
(org-babel-shell-command-on-region (point-min) (point-max) "perl" 'current-buffer 'replace)
|
||||
(buffer-string)))
|
||||
(value
|
||||
(let ((tmp-file (make-temp-file "perl-functional-results")))
|
||||
(with-temp-buffer
|
||||
(insert
|
||||
(format
|
||||
(if (member "pp" result-params)
|
||||
(error "Pretty-printing not implemented for perl")
|
||||
org-babel-perl-wrapper-method)
|
||||
(mapconcat
|
||||
(lambda (line) (format "\t%s" line))
|
||||
(split-string
|
||||
(org-remove-indentation (org-babel-trim body)) "[\r\n]") "\n")
|
||||
tmp-file))
|
||||
;; (message "buffer=%s" (buffer-string)) ;; debugging
|
||||
(org-babel-shell-command-on-region (point-min) (point-max) "perl"))
|
||||
(let* ((tmp-file (make-temp-file "perl-functional-results")) exit-code
|
||||
(stderr
|
||||
(with-temp-buffer
|
||||
(insert
|
||||
(format
|
||||
(if (member "pp" result-params)
|
||||
(error "Pretty-printing not implemented for perl")
|
||||
org-babel-perl-wrapper-method)
|
||||
(mapconcat
|
||||
(lambda (line) (format "\t%s" line))
|
||||
(split-string
|
||||
(org-remove-indentation (org-babel-trim body)) "[\r\n]") "\n")
|
||||
tmp-file))
|
||||
;; (message "buffer=%s" (buffer-string)) ;; debugging
|
||||
(setq exit-code
|
||||
(org-babel-shell-command-on-region
|
||||
(point-min) (point-max) "perl" nil 'replace (current-buffer)))
|
||||
(buffer-string))))
|
||||
(if (> exit-code 0) (org-babel-error-notify exit-code stderr))
|
||||
(org-babel-import-elisp-from-file (org-babel-maybe-remote-file tmp-file))))))
|
||||
;; comint session evaluation
|
||||
(error "Sessions are not supported for Perl.")))
|
||||
|
|
|
@ -155,7 +155,7 @@ BODY, if RESULT-TYPE equals 'value then return the value of the
|
|||
last statement in BODY, as elisp."
|
||||
(if (not session)
|
||||
;; external process evaluation
|
||||
(save-window-excursion
|
||||
(save-excursion
|
||||
(case result-type
|
||||
(output
|
||||
(with-temp-buffer
|
||||
|
@ -164,20 +164,24 @@ last statement in BODY, as elisp."
|
|||
(org-babel-shell-command-on-region (point-min) (point-max) "python" 'current-buffer 'replace)
|
||||
(buffer-string)))
|
||||
(value
|
||||
(let ((tmp-file (make-temp-file "python-functional-results")))
|
||||
(with-temp-buffer
|
||||
(insert
|
||||
(format
|
||||
(if (member "pp" result-params)
|
||||
org-babel-python-pp-wrapper-method
|
||||
org-babel-python-wrapper-method)
|
||||
(mapconcat
|
||||
(lambda (line) (format "\t%s" line))
|
||||
(split-string
|
||||
(org-remove-indentation (org-babel-trim body)) "[\r\n]") "\n")
|
||||
tmp-file))
|
||||
;; (message "buffer=%s" (buffer-string)) ;; debugging
|
||||
(org-babel-shell-command-on-region (point-min) (point-max) "python"))
|
||||
(let* ((tmp-file (make-temp-file "org-babel-python-results-")) exit-code
|
||||
(stderr
|
||||
(with-temp-buffer
|
||||
(insert
|
||||
(format
|
||||
(if (member "pp" result-params)
|
||||
org-babel-python-pp-wrapper-method
|
||||
org-babel-python-wrapper-method)
|
||||
(mapconcat
|
||||
(lambda (line) (format "\t%s" line))
|
||||
(split-string
|
||||
(org-remove-indentation (org-babel-trim body)) "[\r\n]") "\n")
|
||||
tmp-file))
|
||||
;; (message "buffer=%s" (buffer-string)) ;; debugging
|
||||
(setq exit-code (org-babel-shell-command-on-region
|
||||
(point-min) (point-max) "python" nil 'replace (current-buffer)))
|
||||
(buffer-string))))
|
||||
(if (> exit-code 0) (org-babel-error-notify exit-code stderr))
|
||||
(let ((raw (with-temp-buffer
|
||||
(insert-file-contents (org-babel-maybe-remote-file tmp-file))
|
||||
(buffer-string))))
|
||||
|
|
|
@ -159,7 +159,7 @@ BODY, if RESULT-TYPE equals 'value then return the value of the
|
|||
last statement in BODY, as elisp."
|
||||
(if (not session)
|
||||
;; external process evaluation
|
||||
(save-window-excursion
|
||||
(save-excursion
|
||||
(case result-type
|
||||
(output
|
||||
(with-temp-buffer
|
||||
|
@ -168,13 +168,17 @@ last statement in BODY, as elisp."
|
|||
(org-babel-shell-command-on-region (point-min) (point-max) "ruby" 'current-buffer 'replace)
|
||||
(buffer-string)))
|
||||
(value
|
||||
(let ((tmp-file (make-temp-file "ruby-functional-results")))
|
||||
(with-temp-buffer
|
||||
(insert (format (if (member "pp" result-params)
|
||||
org-babel-ruby-pp-wrapper-method
|
||||
org-babel-ruby-wrapper-method) body tmp-file))
|
||||
;; (message "buffer=%s" (buffer-string)) ;; debugging
|
||||
(org-babel-shell-command-on-region (point-min) (point-max) "ruby"))
|
||||
(let* ((tmp-file (make-temp-file "ruby-functional-results")) exit-code
|
||||
(stderr
|
||||
(with-temp-buffer
|
||||
(insert (format (if (member "pp" result-params)
|
||||
org-babel-ruby-pp-wrapper-method
|
||||
org-babel-ruby-wrapper-method) body tmp-file))
|
||||
;; (message "buffer=%s" (buffer-string)) ;; debugging
|
||||
(setq exit-code
|
||||
(org-babel-shell-command-on-region (point-min) (point-max) "ruby" nil 'replace (current-buffer)))
|
||||
(buffer-string))))
|
||||
(if (> exit-code 0) (org-babel-error-notify exit-code stderr))
|
||||
(let ((raw (with-temp-buffer
|
||||
(insert-file-contents (org-babel-maybe-remote-file tmp-file))
|
||||
(buffer-string))))
|
||||
|
|
|
@ -1022,6 +1022,14 @@ block but are passed literally to the \"example-block\"."
|
|||
(nb-add (buffer-substring index (point-max)))))
|
||||
new-body))
|
||||
|
||||
(defun org-babel-error-notify (exit-code stderr)
|
||||
(message (format "Shell command exited with code %d" exit-code))
|
||||
(let ((buf (get-buffer-create "*Org-Babel Error Output*")))
|
||||
(with-current-buffer buf
|
||||
(goto-char (point-max))
|
||||
(save-excursion (insert stderr)))
|
||||
(display-buffer buf)))
|
||||
|
||||
(defun org-babel-clean-text-properties (text)
|
||||
"Strip all properties from text return."
|
||||
(set-text-properties 0 (length text) nil text) text)
|
||||
|
@ -1055,22 +1063,23 @@ This is taken almost directly from `org-read-prop'."
|
|||
"Read the results located at FILE-NAME into an elisp table. If
|
||||
the table is trivial, then return it as a scalar."
|
||||
(let (result)
|
||||
(with-temp-buffer
|
||||
(condition-case nil
|
||||
(progn
|
||||
(org-table-import file-name nil)
|
||||
(delete-file file-name)
|
||||
(setq result (mapcar (lambda (row)
|
||||
(mapcar #'org-babel-string-read row))
|
||||
(org-table-to-lisp))))
|
||||
(error nil)))
|
||||
(if (null (cdr result)) ;; if result is trivial vector, then scalarize it
|
||||
(if (consp (car result))
|
||||
(if (null (cdr (car result)))
|
||||
(caar result)
|
||||
result)
|
||||
(car result))
|
||||
result)))
|
||||
(save-window-excursion
|
||||
(with-temp-buffer
|
||||
(condition-case nil
|
||||
(progn
|
||||
(org-table-import file-name nil)
|
||||
(delete-file file-name)
|
||||
(setq result (mapcar (lambda (row)
|
||||
(mapcar #'org-babel-string-read row))
|
||||
(org-table-to-lisp))))
|
||||
(error nil)))
|
||||
(if (null (cdr result)) ;; if result is trivial vector, then scalarize it
|
||||
(if (consp (car result))
|
||||
(if (null (cdr (car result)))
|
||||
(caar result)
|
||||
result)
|
||||
(car result))
|
||||
result))))
|
||||
|
||||
(defun org-babel-string-read (cell)
|
||||
"Strip nested \"s from around strings in exported R values."
|
||||
|
|
Loading…
Reference in New Issue