(Info-on-current-buffer): Default arg to "Top".
[bpt/emacs.git] / lisp / emacs-lisp / tq.el
CommitLineData
abeffda9
ER
1;;; tq.el --- utility to maintain a transaction queue
2
58142744
ER
3;; Copyright (C) 1985, 1986, 1987, 1992 Free Software Foundation, Inc.
4
83023647
ER
5;; Author: Scott Draves <spot@cs.cmu.edu>
6;; Adapted-By: ESR
d7b4d18f 7;; Keywords: extensions
83023647 8
58142744
ER
9;; This file is part of GNU Emacs.
10
11;; GNU Emacs is free software; you can redistribute it and/or modify
12;; it under the terms of the GNU General Public License as published by
13;; the Free Software Foundation; either version 2, or (at your option)
14;; any later version.
15
16;; GNU Emacs is distributed in the hope that it will be useful,
17;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19;; GNU General Public License for more details.
20
21;; You should have received a copy of the GNU General Public License
b578f267
EN
22;; along with GNU Emacs; see the file COPYING. If not, write to the
23;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24;; Boston, MA 02111-1307, USA.
58142744
ER
25
26;;; Commentary:
83023647 27
abeffda9
ER
28;;; manages receiving a stream asynchronously,
29;;; parsing it into transactions, and then calling
30;;; handler functions
31
abeffda9
ER
32;;; Our basic structure is the queue/process/buffer triple. Each entry
33;;; of the queue is a regexp/closure/function triple. We buffer
34;;; bytes from the process until we see the regexp at the head of the
35;;; queue. Then we call the function with the closure and the
36;;; collected bytes.
37
83023647 38;;; Code:
abeffda9 39
09f11993 40;;;###autoload
abeffda9 41(defun tq-create (process)
09f11993
RS
42 "Create and return a transaction queue communicating with PROCESS.
43PROCESS should be a subprocess capable of sending and receiving
44streams of bytes. It may be a local process, or it may be connected
45to a tcp server on another machine."
abeffda9
ER
46 (let ((tq (cons nil (cons process
47 (generate-new-buffer
48 (concat " tq-temp-"
49 (process-name process)))))))
50 (set-process-filter process
51 (`(lambda (proc string)
52 (tq-filter '(, tq) string))))
53 tq))
54
55;;; accessors
56(defun tq-queue (tq) (car tq))
57(defun tq-process (tq) (car (cdr tq)))
58(defun tq-buffer (tq) (cdr (cdr tq)))
59
60(defun tq-queue-add (tq re closure fn)
61 (setcar tq (nconc (tq-queue tq)
62 (cons (cons re (cons closure fn)) nil)))
63 'ok)
64
65(defun tq-queue-head-regexp (tq) (car (car (tq-queue tq))))
66(defun tq-queue-head-fn (tq) (cdr (cdr (car (tq-queue tq)))))
67(defun tq-queue-head-closure (tq) (car (cdr (car (tq-queue tq)))))
68(defun tq-queue-empty (tq) (not (tq-queue tq)))
69(defun tq-queue-pop (tq) (setcar tq (cdr (car tq))) (null (car tq)))
70
71
72;;; must add to queue before sending!
73(defun tq-enqueue (tq question regexp closure fn)
09f11993
RS
74 "Add a transaction to transaction queue TQ.
75This sends the string QUESTION to the process that TQ communicates with.
76When the corresponding answer comes back, we call FN
77with two arguments: CLOSURE, and the answer to the question.
78REGEXP is a regular expression to match the entire answer;
79that's how we tell where the answer ends."
abeffda9
ER
80 (tq-queue-add tq regexp closure fn)
81 (process-send-string (tq-process tq) question))
82
83(defun tq-close (tq)
09f11993 84 "Shut down transaction queue TQ, terminating the process."
abeffda9
ER
85 (delete-process (tq-process tq))
86 (kill-buffer (tq-buffer tq)))
87
88(defun tq-filter (tq string)
89 "Append STRING to the TQ's buffer; then process the new data."
09841f8d
RS
90 (with-current-buffer (tq-buffer tq)
91 (goto-char (point-max))
92 (insert string)
93 (tq-process-buffer tq)))
abeffda9
ER
94
95(defun tq-process-buffer (tq)
96 "Check TQ's buffer for the regexp at the head of the queue."
97 (set-buffer (tq-buffer tq))
98 (if (= 0 (buffer-size)) ()
99 (if (tq-queue-empty tq)
100 (let ((buf (generate-new-buffer "*spurious*")))
101 (copy-to-buffer buf (point-min) (point-max))
102 (delete-region (point-min) (point))
103 (pop-to-buffer buf nil)
e8a74167
KH
104 (error "Spurious communication from process %s, see buffer %s"
105 (process-name (tq-process tq))
106 (buffer-name buf)))
abeffda9
ER
107 (goto-char (point-min))
108 (if (re-search-forward (tq-queue-head-regexp tq) nil t)
109 (let ((answer (buffer-substring (point-min) (point))))
110 (delete-region (point-min) (point))
941e78a7
RS
111 (unwind-protect
112 (condition-case nil
113 (funcall (tq-queue-head-fn tq)
114 (tq-queue-head-closure tq)
115 answer)
116 (error nil))
117 (tq-queue-pop tq))
abeffda9
ER
118 (tq-process-buffer tq))))))
119
58142744
ER
120(provide 'tq)
121
abeffda9 122;;; tq.el ends here