diff options
author | Miles Bader <miles@gnu.org> | 2006-04-17 08:41:12 +0000 |
---|---|---|
committer | Miles Bader <miles@gnu.org> | 2006-04-17 08:41:12 +0000 |
commit | cfc2051d0ed5a268528a647ab0911a2f5cc451de (patch) | |
tree | cb622fe0b6c1ba8b97314fb80ba2fd8fad60a5a2 /lisp/emacs-lisp/tq.el | |
parent | ca49cf1703cc20d50653c32ca2f438c8819b78bd (diff) | |
parent | e4a89ccf738861d7b9c4f611185aa0f204c9c208 (diff) | |
download | emacs-cfc2051d0ed5a268528a647ab0911a2f5cc451de.tar.gz emacs-cfc2051d0ed5a268528a647ab0911a2f5cc451de.tar.bz2 emacs-cfc2051d0ed5a268528a647ab0911a2f5cc451de.zip |
Revision: emacs@sv.gnu.org/emacs--unicode--0--patch-56
Merge from emacs--devo--0
Patches applied:
* emacs--devo--0 (patch 204-225)
- Update from CVS
- Sync from erc--emacs--0
- Merge from gnus--rel--5.10
- Improve tq.el.
- Update from CVS: src/puresize.h (PURESIZE_RATIO): Reduce to 10/6.
* gnus--rel--5.10 (patch 81-85)
- Update from CVS
- Merge from emacs--devo--0
Diffstat (limited to 'lisp/emacs-lisp/tq.el')
-rw-r--r-- | lisp/emacs-lisp/tq.el | 96 |
1 files changed, 69 insertions, 27 deletions
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 @@ ;;; 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 @@ to a tcp server on another machine." (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." |