diff options
| author | Miles Bader | 2006-04-16 02:17:00 +0000 |
|---|---|---|
| committer | Miles Bader | 2006-04-16 02:17:00 +0000 |
| commit | 51fa34bc588ffe6b6d6d20791ffaa3a855873e13 (patch) | |
| tree | 565fb7d3a99103c90d41ba3d37e9c5c24cb77139 | |
| parent | 21acd4c9d34373a2798a13fabe0e5f36313e6316 (diff) | |
| download | emacs-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/ChangeLog | 12 | ||||
| -rw-r--r-- | lisp/emacs-lisp/tq.el | 96 | ||||
| -rw-r--r-- | lispref/ChangeLog | 5 | ||||
| -rw-r--r-- | lispref/processes.texi | 6 |
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 @@ | |||
| 1 | 2006-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 | |||
| 1 | 2006-04-15 Roland Winkler <Roland.Winkler@physik.uni-erlangen.de> | 13 | 2006-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. |
| 77 | This sends the string QUESTION to the process that TQ communicates with. | 109 | This sends the string QUESTION to the process that TQ communicates with. |
| 78 | When the corresponding answer comes back, we call FN | 110 | |
| 79 | with two arguments: CLOSURE, and the answer to the question. | 111 | When the corresponding answer comes back, we call FN with two |
| 112 | arguments: CLOSURE, which may contain additional data that FN | ||
| 113 | needs, and the answer to the question. | ||
| 114 | |||
| 80 | REGEXP is a regular expression to match the entire answer; | 115 | REGEXP is a regular expression to match the entire answer; |
| 81 | that's how we tell where the answer ends." | 116 | that'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)) | 118 | If DELAY-QUESTION is non-nil, delay sending this question until |
| 119 | the process has finished replying to any previous questions. | ||
| 120 | This 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 @@ | |||
| 1 | 2006-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 | |||
| 1 | 2006-04-13 Bill Wohler <wohler@newt.com> | 6 | 2006-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 | |||
| 1508 | machine. | 1508 | machine. |
| 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 |
| 1512 | This function sends a transaction to queue @var{queue}. Specifying the | 1512 | This function sends a transaction to queue @var{queue}. Specifying the |
| 1513 | queue has the effect of specifying the subprocess to talk to. | 1513 | queue 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 | |||
| 1521 | text at the end of the entire answer, but nothing before; that's how | 1521 | text 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 | ||
| 1524 | If the argument @var{delay-question} is non-nil, delay sending this | ||
| 1525 | question until the process has finished replying to any previous | ||
| 1526 | questions. This produces more reliable results with some processes." | ||
| 1527 | |||
| 1524 | The return value of @code{tq-enqueue} itself is not meaningful. | 1528 | The return value of @code{tq-enqueue} itself is not meaningful. |
| 1525 | @end defun | 1529 | @end defun |
| 1526 | 1530 | ||