aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiles Bader2006-04-16 02:17:00 +0000
committerMiles Bader2006-04-16 02:17:00 +0000
commit51fa34bc588ffe6b6d6d20791ffaa3a855873e13 (patch)
tree565fb7d3a99103c90d41ba3d37e9c5c24cb77139
parent21acd4c9d34373a2798a13fabe0e5f36313e6316 (diff)
downloademacs-51fa34bc588ffe6b6d6d20791ffaa3a855873e13.tar.gz
emacs-51fa34bc588ffe6b6d6d20791ffaa3a855873e13.zip
Revision: emacs@sv.gnu.org/emacs--devo--0--patch-220
Creator: Michael Olson <mwolson@gnu.org> Improve tq.el. * lispref/processes.texi (Transaction Queues): Mention the new optional `delay-question' argument for `tq-enqueue'. * lisp/emacs-lisp/tq.el: Improve comments. (tq-queue-head-question): New accessor function. (tq-queue-head-regexp, tq-queue-head-closure, tq-queue-head-fn): Update for modified queue structure. (tq-queue-add): Accept `question' argument. (tq-queue-pop): If a question is pending, send it. (tq-enqueue): Accept new optional argument `delay-question'. If this is non-nil, and at least one other question is pending a response, queue the question rather than sending it immediately.
-rw-r--r--lisp/ChangeLog12
-rw-r--r--lisp/emacs-lisp/tq.el96
-rw-r--r--lispref/ChangeLog5
-rw-r--r--lispref/processes.texi6
4 files changed, 91 insertions, 28 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 547e4663d51..dfc0c79b1f5 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,15 @@
12006-04-15 Michael Olson <mwolson@gnu.org>
2
3 * emacs-lisp/tq.el: Improve comments.
4 (tq-queue-head-question): New accessor function.
5 (tq-queue-head-regexp, tq-queue-head-closure, tq-queue-head-fn):
6 Update for modified queue structure.
7 (tq-queue-add): Accept `question' argument.
8 (tq-queue-pop): If a question is pending, send it.
9 (tq-enqueue): Accept new optional argument `delay-question'. If
10 this is non-nil, and at least one other question is pending a
11 response, queue the question rather than sending it immediately.
12
12006-04-15 Roland Winkler <Roland.Winkler@physik.uni-erlangen.de> 132006-04-15 Roland Winkler <Roland.Winkler@physik.uni-erlangen.de>
2 14
3 * calendar/appt.el (appt-add): Check whether an appointment is 15 * calendar/appt.el (appt-add): Check whether an appointment is
diff --git a/lisp/emacs-lisp/tq.el b/lisp/emacs-lisp/tq.el
index a4a22806d09..2126d7663fc 100644
--- a/lisp/emacs-lisp/tq.el
+++ b/lisp/emacs-lisp/tq.el
@@ -27,18 +27,56 @@
27 27
28;;; Commentary: 28;;; Commentary:
29 29
30;; manages receiving a stream asynchronously, 30;; This file manages receiving a stream asynchronously, parsing it
31;; parsing it into transactions, and then calling 31;; into transactions, and then calling the associated handler function
32;; handler functions 32;; upon the completion of each transaction.
33 33
34;; Our basic structure is the queue/process/buffer triple. Each entry 34;; Our basic structure is the queue/process/buffer triple. Each entry
35;; of the queue is a regexp/closure/function triple. We buffer 35;; of the queue part is a list of question, regexp, closure, and
36;; bytes from the process until we see the regexp at the head of the 36;; function that is consed to the last element.
37;; queue. Then we call the function with the closure and the 37
38;; collected bytes. 38;; A transaction queue may be created by calling `tq-create'.
39
40;; A request may be added to the queue by calling `tq-enqueue'. If
41;; the `delay-question' argument is non-nil, we will wait to send the
42;; question to the process until it has finished sending other input.
43;; Otherwise, once a request is enqueued, we send the given question
44;; immediately to the process.
45
46;; We then buffer bytes from the process until we see the regexp that
47;; was provided in the call to `tq-enqueue'. Then we call the
48;; provided function with the closure and the collected bytes. If we
49;; have indicated that the question from the next transaction was not
50;; sent immediately, send it at this point, awaiting the response.
39 51
40;;; Code: 52;;; Code:
41 53
54;;; Accessors
55
56;; This part looks like (queue . (process . buffer))
57(defun tq-queue (tq) (car tq))
58(defun tq-process (tq) (car (cdr tq)))
59(defun tq-buffer (tq) (cdr (cdr tq)))
60
61;; The structure of `queue' is as follows
62;; ((question regexp closure . fn)
63;; <other queue entries>)
64;; question: string to send to the process
65(defun tq-queue-head-question (tq) (car (car (tq-queue tq))))
66;; regexp: regular expression that matches the end of a response from
67;; the process
68(defun tq-queue-head-regexp (tq) (car (cdr (car (tq-queue tq)))))
69;; closure: additional data to pass to function
70(defun tq-queue-head-closure (tq) (car (cdr (cdr (car (tq-queue tq))))))
71;; fn: function to call upon receiving a complete response from the
72;; process
73(defun tq-queue-head-fn (tq) (cdr (cdr (cdr (car (tq-queue tq))))))
74
75;; Determine whether queue is empty
76(defun tq-queue-empty (tq) (not (tq-queue tq)))
77
78;;; Core functionality
79
42;;;###autoload 80;;;###autoload
43(defun tq-create (process) 81(defun tq-create (process)
44 "Create and return a transaction queue communicating with PROCESS. 82 "Create and return a transaction queue communicating with PROCESS.
@@ -54,33 +92,37 @@ to a tcp server on another machine."
54 (tq-filter ',tq string))) 92 (tq-filter ',tq string)))
55 tq)) 93 tq))
56 94
57;;; accessors 95(defun tq-queue-add (tq question re closure fn)
58(defun tq-queue (tq) (car tq))
59(defun tq-process (tq) (car (cdr tq)))
60(defun tq-buffer (tq) (cdr (cdr tq)))
61
62(defun tq-queue-add (tq re closure fn)
63 (setcar tq (nconc (tq-queue tq) 96 (setcar tq (nconc (tq-queue tq)
64 (cons (cons re (cons closure fn)) nil))) 97 (cons (cons question (cons re (cons closure fn))) nil)))
65 'ok) 98 'ok)
66 99
67(defun tq-queue-head-regexp (tq) (car (car (tq-queue tq)))) 100(defun tq-queue-pop (tq)
68(defun tq-queue-head-fn (tq) (cdr (cdr (car (tq-queue tq))))) 101 (setcar tq (cdr (car tq)))
69(defun tq-queue-head-closure (tq) (car (cdr (car (tq-queue tq))))) 102 (let ((question (tq-queue-head-question tq)))
70(defun tq-queue-empty (tq) (not (tq-queue tq))) 103 (when question
71(defun tq-queue-pop (tq) (setcar tq (cdr (car tq))) (null (car tq))) 104 (process-send-string (tq-process tq) question)))
105 (null (car tq)))
72 106
73 107(defun tq-enqueue (tq question regexp closure fn &optional delay-question)
74;;; must add to queue before sending!
75(defun tq-enqueue (tq question regexp closure fn)
76 "Add a transaction to transaction queue TQ. 108 "Add a transaction to transaction queue TQ.
77This sends the string QUESTION to the process that TQ communicates with. 109This sends the string QUESTION to the process that TQ communicates with.
78When the corresponding answer comes back, we call FN 110
79with two arguments: CLOSURE, and the answer to the question. 111When the corresponding answer comes back, we call FN with two
112arguments: CLOSURE, which may contain additional data that FN
113needs, and the answer to the question.
114
80REGEXP is a regular expression to match the entire answer; 115REGEXP is a regular expression to match the entire answer;
81that's how we tell where the answer ends." 116that's how we tell where the answer ends.
82 (tq-queue-add tq regexp closure fn) 117
83 (process-send-string (tq-process tq) question)) 118If DELAY-QUESTION is non-nil, delay sending this question until
119the process has finished replying to any previous questions.
120This produces more reliable results with some processes."
121 (let ((sendp (or (not delay-question)
122 (not (tq-queue-head-question tq)))))
123 (tq-queue-add tq (unless sendp question) regexp closure fn)
124 (when sendp
125 (process-send-string (tq-process tq) question))))
84 126
85(defun tq-close (tq) 127(defun tq-close (tq)
86 "Shut down transaction queue TQ, terminating the process." 128 "Shut down transaction queue TQ, terminating the process."
diff --git a/lispref/ChangeLog b/lispref/ChangeLog
index f16982eb414..c3591cbb64a 100644
--- a/lispref/ChangeLog
+++ b/lispref/ChangeLog
@@ -1,3 +1,8 @@
12006-04-15 Michael Olson <mwolson@gnu.org>
2
3 * processes.texi (Transaction Queues): Mention the new optional
4 `delay-question' argument for `tq-enqueue'.
5
12006-04-13 Bill Wohler <wohler@newt.com> 62006-04-13 Bill Wohler <wohler@newt.com>
2 7
3 * customize.texi (Common Keywords): Use dotted notation for 8 * customize.texi (Common Keywords): Use dotted notation for
diff --git a/lispref/processes.texi b/lispref/processes.texi
index 5f0cfb0edf0..44da398770d 100644
--- a/lispref/processes.texi
+++ b/lispref/processes.texi
@@ -1508,7 +1508,7 @@ process, or it may be a TCP connection to a server, possibly on another
1508machine. 1508machine.
1509@end defun 1509@end defun
1510 1510
1511@defun tq-enqueue queue question regexp closure fn 1511@defun tq-enqueue queue question regexp closure fn &optional delay-question
1512This function sends a transaction to queue @var{queue}. Specifying the 1512This function sends a transaction to queue @var{queue}. Specifying the
1513queue has the effect of specifying the subprocess to talk to. 1513queue has the effect of specifying the subprocess to talk to.
1514 1514
@@ -1521,6 +1521,10 @@ The argument @var{regexp} is a regular expression that should match
1521text at the end of the entire answer, but nothing before; that's how 1521text at the end of the entire answer, but nothing before; that's how
1522@code{tq-enqueue} determines where the answer ends. 1522@code{tq-enqueue} determines where the answer ends.
1523 1523
1524If the argument @var{delay-question} is non-nil, delay sending this
1525question until the process has finished replying to any previous
1526questions. This produces more reliable results with some processes."
1527
1524The return value of @code{tq-enqueue} itself is not meaningful. 1528The return value of @code{tq-enqueue} itself is not meaningful.
1525@end defun 1529@end defun
1526 1530