1 ;;; org-babel-comint.el --- org-babel functions for interaction with comint buffers
3 ;; Copyright (C) 2009 Eric Schulte
5 ;; Author: Eric Schulte
6 ;; Keywords: literate programming, reproducible research, comint
7 ;; Homepage: http://orgmode.org
12 ;; This program is free software; you can redistribute it and/or modify
13 ;; it under the terms of the GNU General Public License as published by
14 ;; the Free Software Foundation; either version 3, or (at your option)
17 ;; This program is distributed in the hope that it will be useful,
18 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 ;; GNU General Public License for more details.
22 ;; You should have received a copy of the GNU General Public License
23 ;; along with GNU Emacs; see the file COPYING. If not, write to the
24 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
25 ;; Boston, MA 02110-1301, USA.
29 ;; These functions build on comint to ease the sending and receiving
30 ;; of commands and results from comint buffers.
32 ;; Note that the buffers in this file are analogous to sessions in
33 ;; org-babel at large.
39 (defun org-babel-comint-buffer-livep (buffer)
40 (let ((buffer (if buffer
(get-buffer buffer
))))
41 (and buffer
(buffer-live-p buffer
) (get-buffer-process buffer
) buffer
)))
43 (defmacro org-babel-comint-in-buffer
(buffer &rest body
)
44 "Check BUFFER with `org-babel-comint-buffer-livep' then execute
45 body inside the protection of `save-window-excursion' and
48 `(save-window-excursion
50 (unless (org-babel-comint-buffer-livep ,buffer
)
51 (error (format "buffer %s doesn't exist or has no process" ,buffer
)))
55 (defmacro org-babel-comint-with-output
(buffer eoe-indicator remove-echo
&rest body
)
56 "Evaluate BODY in BUFFER, wait until EOE-INDICATOR appears in
57 output, then return all process output. This ensures that the
58 filter is removed in case of an error or user `keyboard-quit'
59 during execution of body."
61 `(org-babel-comint-in-buffer ,buffer
62 (let ((string-buffer ""))
63 (flet ((my-filt (text) (setq string-buffer
(concat string-buffer text
))))
65 (add-hook 'comint-output-filter-functions
'my-filt
)
68 ;; pass FULL-BODY to process
69 (goto-char (process-mark (get-buffer-process (current-buffer))))
71 ;; wait for end-of-evaluation indicator
73 (goto-char comint-last-input-end
)
75 (and (re-search-forward comint-prompt-regexp nil t
)
76 (re-search-forward (regexp-quote ,eoe-indicator
) nil t
)))))
77 (accept-process-output (get-buffer-process (current-buffer)))
78 ;; ;; thought this would allow async background running, but I was wrong...
79 ;; (run-with-timer .5 .5 'accept-process-output (get-buffer-process (current-buffer)))
82 (remove-hook 'comint-output-filter-functions
'my-filt
)))
83 ;; remove echo'd FULL-BODY from input
86 (replace-regexp-in-string "\n" "\r\n" (regexp-quote ,full-body
)) string-buffer
))
87 (setq raw
(substring string-buffer
(match-end 0))))
88 (split-string string-buffer comint-prompt-regexp
))))
90 (defun org-babel-comint-input-command (buffer cmd
)
91 "Pass CMD to BUFFER The input will not be echoed."
92 (org-babel-comint-in-buffer buffer
93 (goto-char (process-mark (get-buffer-process buffer
)))
96 (org-babel-comint-wait-for-output buffer
)))
98 (defun org-babel-comint-wait-for-output (buffer)
99 "Wait until output arrives. Note: this is only safe when
100 waiting for the result of a single statement (not large blocks of
102 (org-babel-comint-in-buffer buffer
104 (goto-char comint-last-input-end
)
105 (not (and (re-search-forward comint-prompt-regexp nil t
)
106 (goto-char (match-beginning 0))
107 (string= (face-name (face-at-point))
108 "comint-highlight-prompt"))))
109 (accept-process-output (get-buffer-process buffer
)))))
111 (provide 'org-babel-comint
)
112 ;;; org-babel-comint.el ends here