Haskell needs more work on the differences between interactive and non-interactive...
[org-mode.git] / lisp / org-babel-comint.el
blobd65f0549432be380a36ad614e47ec47f11a50002
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
8 ;; Version: 0.01
10 ;;; License:
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)
15 ;; any later version.
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.
27 ;;; Commentary:
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.
35 ;;; Code:
36 (require 'org-babel)
37 (require 'comint)
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
46 `save-match-data'."
47 (declare (indent 1))
48 `(save-window-excursion
49 (save-match-data
50 (unless (org-babel-comint-buffer-livep ,buffer)
51 (error (format "buffer %s doesn't exist or has no process" ,buffer)))
52 (set-buffer ,buffer)
53 ,@body)))
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."
60 (declare (indent 3))
61 `(org-babel-comint-in-buffer ,buffer
62 (let ((string-buffer ""))
63 (flet ((my-filt (text) (setq string-buffer (concat string-buffer text))))
64 ;; setup filter
65 (add-hook 'comint-output-filter-functions 'my-filt)
66 (unwind-protect
67 (progn
68 ;; pass FULL-BODY to process
69 (goto-char (process-mark (get-buffer-process (current-buffer))))
70 ,@body
71 ;; wait for end-of-evaluation indicator
72 (while (progn
73 (goto-char comint-last-input-end)
74 (not (save-excursion
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)))
81 ;; remove filter
82 (remove-hook 'comint-output-filter-functions 'my-filt)))
83 ;; remove echo'd FULL-BODY from input
84 (if (and ,remove-echo
85 (string-match
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)))
94 (insert cmd)
95 (comint-send-input)
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
101 code)."
102 (org-babel-comint-in-buffer buffer
103 (while (progn
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