Mercurial > emacs
changeset 70034:db4c2d467e9a
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.
author | Miles Bader <miles@gnu.org> |
---|---|
date | Sun, 16 Apr 2006 02:17:00 +0000 |
parents | 257bb51424b3 |
children | 479ddf150263 |
files | lisp/ChangeLog lisp/emacs-lisp/tq.el lispref/ChangeLog lispref/processes.texi |
diffstat | 4 files changed, 91 insertions(+), 28 deletions(-) [+] |
line wrap: on
line diff
--- a/lisp/ChangeLog Sat Apr 15 18:51:38 2006 +0000 +++ b/lisp/ChangeLog Sun Apr 16 02:17:00 2006 +0000 @@ -1,3 +1,15 @@ +2006-04-15 Michael Olson <mwolson@gnu.org> + + * 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. + 2006-04-15 Roland Winkler <Roland.Winkler@physik.uni-erlangen.de> * calendar/appt.el (appt-add): Check whether an appointment is
--- a/lisp/emacs-lisp/tq.el Sat Apr 15 18:51:38 2006 +0000 +++ b/lisp/emacs-lisp/tq.el Sun Apr 16 02:17:00 2006 +0000 @@ -27,18 +27,56 @@ ;;; Commentary: -;; manages receiving a stream asynchronously, -;; parsing it into transactions, and then calling -;; handler functions +;; This file manages receiving a stream asynchronously, parsing it +;; into transactions, and then calling the associated handler function +;; upon the completion of each transaction. ;; Our basic structure is the queue/process/buffer triple. Each entry -;; of the queue is a regexp/closure/function triple. We buffer -;; bytes from the process until we see the regexp at the head of the -;; queue. Then we call the function with the closure and the -;; collected bytes. +;; of the queue part is a list of question, regexp, closure, and +;; function that is consed to the last element. + +;; A transaction queue may be created by calling `tq-create'. + +;; A request may be added to the queue by calling `tq-enqueue'. If +;; the `delay-question' argument is non-nil, we will wait to send the +;; question to the process until it has finished sending other input. +;; Otherwise, once a request is enqueued, we send the given question +;; immediately to the process. + +;; We then buffer bytes from the process until we see the regexp that +;; was provided in the call to `tq-enqueue'. Then we call the +;; provided function with the closure and the collected bytes. If we +;; have indicated that the question from the next transaction was not +;; sent immediately, send it at this point, awaiting the response. ;;; Code: +;;; Accessors + +;; This part looks like (queue . (process . buffer)) +(defun tq-queue (tq) (car tq)) +(defun tq-process (tq) (car (cdr tq))) +(defun tq-buffer (tq) (cdr (cdr tq))) + +;; The structure of `queue' is as follows +;; ((question regexp closure . fn) +;; <other queue entries>) +;; question: string to send to the process +(defun tq-queue-head-question (tq) (car (car (tq-queue tq)))) +;; regexp: regular expression that matches the end of a response from +;; the process +(defun tq-queue-head-regexp (tq) (car (cdr (car (tq-queue tq))))) +;; closure: additional data to pass to function +(defun tq-queue-head-closure (tq) (car (cdr (cdr (car (tq-queue tq)))))) +;; fn: function to call upon receiving a complete response from the +;; process +(defun tq-queue-head-fn (tq) (cdr (cdr (cdr (car (tq-queue tq)))))) + +;; Determine whether queue is empty +(defun tq-queue-empty (tq) (not (tq-queue tq))) + +;;; Core functionality + ;;;###autoload (defun tq-create (process) "Create and return a transaction queue communicating with PROCESS. @@ -54,33 +92,37 @@ (tq-filter ',tq string))) tq)) -;;; accessors -(defun tq-queue (tq) (car tq)) -(defun tq-process (tq) (car (cdr tq))) -(defun tq-buffer (tq) (cdr (cdr tq))) - -(defun tq-queue-add (tq re closure fn) +(defun tq-queue-add (tq question re closure fn) (setcar tq (nconc (tq-queue tq) - (cons (cons re (cons closure fn)) nil))) + (cons (cons question (cons re (cons closure fn))) nil))) 'ok) -(defun tq-queue-head-regexp (tq) (car (car (tq-queue tq)))) -(defun tq-queue-head-fn (tq) (cdr (cdr (car (tq-queue tq))))) -(defun tq-queue-head-closure (tq) (car (cdr (car (tq-queue tq))))) -(defun tq-queue-empty (tq) (not (tq-queue tq))) -(defun tq-queue-pop (tq) (setcar tq (cdr (car tq))) (null (car tq))) +(defun tq-queue-pop (tq) + (setcar tq (cdr (car tq))) + (let ((question (tq-queue-head-question tq))) + (when question + (process-send-string (tq-process tq) question))) + (null (car tq))) - -;;; must add to queue before sending! -(defun tq-enqueue (tq question regexp closure fn) +(defun tq-enqueue (tq question regexp closure fn &optional delay-question) "Add a transaction to transaction queue TQ. This sends the string QUESTION to the process that TQ communicates with. -When the corresponding answer comes back, we call FN -with two arguments: CLOSURE, and the answer to the question. + +When the corresponding answer comes back, we call FN with two +arguments: CLOSURE, which may contain additional data that FN +needs, and the answer to the question. + REGEXP is a regular expression to match the entire answer; -that's how we tell where the answer ends." - (tq-queue-add tq regexp closure fn) - (process-send-string (tq-process tq) question)) +that's how we tell where the answer ends. + +If DELAY-QUESTION is non-nil, delay sending this question until +the process has finished replying to any previous questions. +This produces more reliable results with some processes." + (let ((sendp (or (not delay-question) + (not (tq-queue-head-question tq))))) + (tq-queue-add tq (unless sendp question) regexp closure fn) + (when sendp + (process-send-string (tq-process tq) question)))) (defun tq-close (tq) "Shut down transaction queue TQ, terminating the process."
--- a/lispref/ChangeLog Sat Apr 15 18:51:38 2006 +0000 +++ b/lispref/ChangeLog Sun Apr 16 02:17:00 2006 +0000 @@ -1,3 +1,8 @@ +2006-04-15 Michael Olson <mwolson@gnu.org> + + * processes.texi (Transaction Queues): Mention the new optional + `delay-question' argument for `tq-enqueue'. + 2006-04-13 Bill Wohler <wohler@newt.com> * customize.texi (Common Keywords): Use dotted notation for
--- a/lispref/processes.texi Sat Apr 15 18:51:38 2006 +0000 +++ b/lispref/processes.texi Sun Apr 16 02:17:00 2006 +0000 @@ -1508,7 +1508,7 @@ machine. @end defun -@defun tq-enqueue queue question regexp closure fn +@defun tq-enqueue queue question regexp closure fn &optional delay-question This function sends a transaction to queue @var{queue}. Specifying the queue has the effect of specifying the subprocess to talk to. @@ -1521,6 +1521,10 @@ text at the end of the entire answer, but nothing before; that's how @code{tq-enqueue} determines where the answer ends. +If the argument @var{delay-question} is non-nil, delay sending this +question until the process has finished replying to any previous +questions. This produces more reliable results with some processes." + The return value of @code{tq-enqueue} itself is not meaningful. @end defun