Function: org-babel-comint-with-output

org-babel-comint-with-output is a macro defined in ob-comint.el.gz.

Signature

(org-babel-comint-with-output META &rest BODY)

Documentation

Evaluate BODY in BUFFER and return process output.

Will wait until EOE-INDICATOR appears in the output, then return all process output. If REMOVE-ECHO and FULL-BODY are present and non-nil, then strip echo'd body from the returned output. META should be a list containing the following where the last two elements are optional.

 (BUFFER EOE-INDICATOR REMOVE-ECHO FULL-BODY)

This macro ensures that the filter is removed in case of an error or user keyboard-quit during execution of body.

Source Code

;; Defined in /usr/src/emacs/lisp/org/ob-comint.el.gz
(defmacro org-babel-comint-with-output (meta &rest body)
  "Evaluate BODY in BUFFER and return process output.
Will wait until EOE-INDICATOR appears in the output, then return
all process output.  If REMOVE-ECHO and FULL-BODY are present and
non-nil, then strip echo'd body from the returned output.  META
should be a list containing the following where the last two
elements are optional.

 (BUFFER EOE-INDICATOR REMOVE-ECHO FULL-BODY)

This macro ensures that the filter is removed in case of an error
or user `keyboard-quit' during execution of body."
  (declare (indent 1) (debug (sexp body)))
  (let ((buffer (nth 0 meta))
	(eoe-indicator (nth 1 meta))
	(remove-echo (nth 2 meta))
	(full-body (nth 3 meta))
        (org-babel-comint-prompt-separator
         "org-babel-comint-prompt-separator"))
    `(org-babel-comint-in-buffer ,buffer
       (let* ((string-buffer "")
	      (comint-output-filter-functions
	       (cons (lambda (text)
                       (setq string-buffer (concat string-buffer text)))
		     comint-output-filter-functions))
	      dangling-text)
	 ;; got located, and save dangling text
	 (goto-char (process-mark (get-buffer-process (current-buffer))))
	 (let ((start (point))
	       (end (point-max)))
	   (setq dangling-text (buffer-substring start end))
	   (delete-region start end))
	 ;; pass FULL-BODY to process
	 ,@body
	 ;; wait for end-of-evaluation indicator
	 (while (progn
		  (goto-char comint-last-input-end)
		  (not (save-excursion
		       (and (re-search-forward
			     (regexp-quote ,eoe-indicator) nil t)
			    (re-search-forward
			     comint-prompt-regexp nil t)))))
	   (accept-process-output (get-buffer-process (current-buffer))))
	 ;; replace cut dangling text
	 (goto-char (process-mark (get-buffer-process (current-buffer))))
	 (insert dangling-text)

         ;; Filter out prompts.
         (setq string-buffer
               (replace-regexp-in-string
                ;; Sometimes, we get multiple agglomerated
                ;; prompts together in a single output:
                ;; "prompt prompt prompt output"
                ;; Remove them progressively, so that
                ;; possible "^" in the prompt regexp gets to
                ;; work as we remove the heading prompt
                ;; instance.
                (if (string-prefix-p "^" comint-prompt-regexp)
                    (format "^\\(%s\\)+" (substring comint-prompt-regexp 1))
                  comint-prompt-regexp)
                ,org-babel-comint-prompt-separator
                string-buffer))
	 ;; remove echo'd FULL-BODY from input
	 (when (and ,remove-echo ,full-body
		    (string-match
		     (replace-regexp-in-string
		      "\n" "[\r\n]+" (regexp-quote (or ,full-body "")))
		     string-buffer))
	   (setq string-buffer (substring string-buffer (match-end 0))))
         (delete "" (split-string
                     string-buffer
                     ,org-babel-comint-prompt-separator))))))