Commit 57b0f861 authored by David Byers's avatar David Byers
Browse files

Fix some bugs. Make server calls cancelable. Prompt for date in...

Fix some bugs. Make server calls cancelable. Prompt for date in lyskom-list-new-conferences when appropriate. Binary search on conference creation date. Cleanup.

Detailed changes:
> 2004-02-12  David Byers  <byers@lysator.liu.se>
>
> 	Make kom-list-new-conferences quittable:
> 	* commands2.el (lyskom-list-new-conferences): Handle C-g when
> 	listing conferences or persons using the new lyskom-cancel-calls.
>
> 	* internal.el (lyskom-cancel-calls): It works now.
>
> 2004-02-11  David Byers  <byers@lysator.liu.se>
>
> 	Improve ability to cancel calls:
> 	* services.el (initiate-get-text): Add lyskom-ref-no to PARSED.
> 	(initiate-get-text-stat): Ditto.
> 	(initiate-get-pers-stat): Ditto.
> 	(initiate-get-conf-stat): Ditto.
> 	(initiate-get-uconf-stat): Ditto.
> 	(initiate-get-static-session-info): Ditto.
> 	(initiate-get-stats-description): Ditto.
> 	(initiate-get-boottime-info): Ditto.
>
> 	* internal.el (lyskom-apply-handler): Allow ref-no in PARSED.
>
> 	* parse.el (lyskom-tr-call-to-parsed): Leave the ref-no in PARSED.
>
> 	* internal.el (lyskom-cancel-calls): New function.
>
> 	Prevent lyskom-ref-no from going negative:
> 	* macros.el (lyskom-ref-no): New macro to get and increment
> 	lyskom-ref-no.
>
> 	* internal.el (lyskom-send-packet): Ensure that lyskom-ref-no
> 	never goes negative.
>
> 	Fix bug 1272:
> 	* review.el (kom-review-converted): Don't bind
> 	lyskom-format-special (why did we *ever* bind it here?)
>
> 2004-02-09  David Byers  <byers@lysator.liu.se>
>
> 	* clienttypes.el (lyskom-queue-remove-matching): New function.
>
> 2004-02-07  David Byers  <byers@lysator.liu.se>
>
> 	* utilities.el (lyskom-read-date): Added optional parameter empty.
>
> 	Speed up behavior after changing user area:
> 	* async.el (lyskom-parse-async): Don't re-read settings if the new
> 	user area is one we've already read (or just created).
>
> 	* flags.el (lyskom-save-options-2): Set lyskom-current-user-area.
> 	(lyskom-read-options-eval): Ditto.
>
> 	Bug 1271 (and then some):
> 	* commands2.el (kom-list-new-conferences): Accept prefix arg to
> 	list from a specific date.
> 	(kom-list-new-persons): Ditto.
> 	(lyskom-list-new-conferences): Prompt for start date if the caller
> 	requests it or the command has never been used before.
>
> 2004-02-06  David Byers  <byers@lysator.liu.se>
>
> 	* utilities.el (lyskom-find-conf-by-date): New function.
>
1a65,67
>
> 	* macros.el (blocking-do-multiple): Use modern backquote syntax to
> 	make the code more readable.
parent 76a54e40
2004-02-12 David Byers <byers@lysator.liu.se>
Make kom-list-new-conferences quittable:
* commands2.el (lyskom-list-new-conferences): Handle C-g when
listing conferences or persons using the new lyskom-cancel-calls.
* internal.el (lyskom-cancel-calls): It works now.
2004-02-11 David Byers <byers@lysator.liu.se>
Improve ability to cancel calls:
* services.el (initiate-get-text): Add lyskom-ref-no to PARSED.
(initiate-get-text-stat): Ditto.
(initiate-get-pers-stat): Ditto.
(initiate-get-conf-stat): Ditto.
(initiate-get-uconf-stat): Ditto.
(initiate-get-static-session-info): Ditto.
(initiate-get-stats-description): Ditto.
(initiate-get-boottime-info): Ditto.
* internal.el (lyskom-apply-handler): Allow ref-no in PARSED.
* parse.el (lyskom-tr-call-to-parsed): Leave the ref-no in PARSED.
* internal.el (lyskom-cancel-calls): New function.
Prevent lyskom-ref-no from going negative:
* macros.el (lyskom-ref-no): New macro to get and increment
lyskom-ref-no.
* internal.el (lyskom-send-packet): Ensure that lyskom-ref-no
never goes negative.
Fix bug 1272:
* review.el (kom-review-converted): Don't bind
lyskom-format-special (why did we *ever* bind it here?)
2004-02-09 David Byers <byers@lysator.liu.se>
* clienttypes.el (lyskom-queue-remove-matching): New function.
2004-02-07 David Byers <byers@lysator.liu.se>
* utilities.el (lyskom-read-date): Added optional parameter empty.
Speed up behavior after changing user area:
* async.el (lyskom-parse-async): Don't re-read settings if the new
user area is one we've already read (or just created).
* flags.el (lyskom-save-options-2): Set lyskom-current-user-area.
(lyskom-read-options-eval): Ditto.
Bug 1271 (and then some):
* commands2.el (kom-list-new-conferences): Accept prefix arg to
list from a specific date.
(kom-list-new-persons): Ditto.
(lyskom-list-new-conferences): Prompt for start date if the caller
requests it or the command has never been used before.
2004-02-06 David Byers <byers@lysator.liu.se>
* utilities.el (lyskom-find-conf-by-date): New function.
2004-01-29 David Byers <byers@lysator.liu.se>
* macros.el (blocking-do-multiple): Use modern backquote syntax to
make the code more readable.
* vars.el.in (lyskom-text-buttons): Improved performance of some
regexps in lyskom-text-buttons.
......
......@@ -276,7 +276,8 @@ this function shall be with current-buffer the BUFFER."
(new-user-area (lyskom-parse-num)))
(lyskom-save-excursion
(set-buffer buffer)
(when (eq pers-no lyskom-pers-no)
(when (and (eq pers-no lyskom-pers-no)
(not (eq lyskom-current-user-area new-user-area)))
(initiate-get-pers-stat 'follow
'lyskom-async-new-user-area
pers-no
......
......@@ -319,6 +319,21 @@ element will be the new first element."
(car-safe (cdr (cdr queue))))
(defun lyskom-queue-remove-matching (queue pred)
"Remove all elements from QUEUE that satisfy PRED."
(let ((prev nil)
(ptr (car (cdr queue))))
(while ptr
(if (funcall pred (car ptr))
(progn (if prev
(setcdr prev (cdr ptr))
(setcar (cdr queue) (cdr ptr)))
(unless (cdr ptr)
(setcdr (cdr queue) prev)))
(setq prev ptr))
(setq ptr (cdr ptr)))))
(defsubst lyskom-queue-make-empty (queue)
"Make the queue QUEUE empty."
(setcdr queue (cons nil nil)))
......
......@@ -3542,58 +3542,105 @@ are advisory; clients may ignore them."
(membership->type mship)))
(lp--update-buffer (uconf-stat->conf-no uconf-stat))))))
(def-kom-command kom-list-new-conferences ()
(def-kom-command kom-list-new-conferences (arg)
"List conferences created since the last time this command
was given."
(interactive)
was given. With prefix argument, prompt for a date to start at."
(interactive "P")
(lyskom-list-new-conferences 'lyskom-last-known-conf-no
'conferences
(lambda (el)
(not (conf-type->letterbox
(conf-stat->conf-type el))))))
(conf-stat->conf-type el))))
arg))
(def-kom-command kom-list-new-persons ()
(def-kom-command kom-list-new-persons (arg)
"List persons created since the last time this command
was given."
(interactive)
was given. With prefix argument, prompt for a date to start at."
(interactive "P")
(lyskom-list-new-conferences 'lyskom-last-known-pers-no
'persons
(lambda (el)
(conf-type->letterbox
(conf-stat->conf-type el)))))
(conf-stat->conf-type el)))
arg))
(defun lyskom-list-new-conferences (varsym obj filter)
"List conferences created since the last time this command
was given."
(defun lyskom-list-new-conferences (varsym obj filter &optional list-from-date)
"List conferences created since a particular point in history.
VARSYM is the name of a variable that should be bound to a cons of the
last conference number displayed and the date when it was displayed
\(lyskom-time structure).
OBJ is the type of object. It should be a symbol that can be passed
to lyskom-get-string to get a text representation of the object type.
FILTER is a function called on each conference. It should return
non-nil for conferences that should be displayed.
If optional LIST-FROM-DATE is non-nil, prompt for a date and list
all conferences from that date forward."
(interactive)
(let* ((var (symbol-value varsym))
(conf-no (or (car var) 1))
(last-conf-no (blocking-do 'first-unused-conf-no))
(let* ((last-conf-no (blocking-do 'first-unused-conf-no))
(var (or (and (null list-from-date)
(symbol-value varsym))
(let* ((n (lyskom-read-date
(lyskom-format 'list-confs-from-date
(lyskom-get-string obj))
t))
(date (and n (lyskom-create-time 0 0 0 (elt n 2)
(elt n 1) (elt n 0)
0 0 nil)))
(conf (and n (lyskom-find-conf-by-date date))))
(cond
;; No date -- we want it all!
((null n) (cons 1 nil))
;; Date but no conf -- no confs to list!
((null conf) (cons last-conf-no date))
;; Date and conf -- list from this conf
(t (cons (conf-stat->conf-no conf) date))))))
(conf-no (car var))
(time-string (condition-case nil
(and var (lyskom-format-time
'date-and-time (cdr var)))
(and (cdr var) (lyskom-format-time
'date-and-time (cdr var)))
(error nil))))
(if (null last-conf-no)
(lyskom-format-insert 'no-support-in-server))
(let ((count (cons 0 (make-marker))))
(while (< conf-no last-conf-no)
(initiate-get-conf-stat
'main
(lambda (conf filter count time-string)
(when (and conf (funcall filter conf))
(when (eq (car count) 0)
(lyskom-format-insert 'new-conferences-since
time-string (lyskom-get-string obj)))
(rplaca count (1+ (car count)))
(lyskom-format-insert "%5#1m %#2c %#1M\n"
conf
(lyskom-list-conf-membership-char
(conf-stat->conf-no conf)))
(set-marker (cdr count) (point))))
conf-no filter count time-string)
(setq conf-no (1+ conf-no)))
(lyskom-wait-queue 'main)
;; There's a serious bug here: we can't cancel!
;; That *has* to be fixed.
(let ((count (cons 0 (make-marker)))
(calls nil))
(condition-case nil
(progn
(while (< conf-no last-conf-no)
(setq calls
(cons
(initiate-get-conf-stat
'main
(lambda (conf filter count time-string)
(when (and conf (funcall filter conf))
(when (eq (car count) 0)
(lyskom-format-insert 'new-conferences-since
time-string (lyskom-get-string obj)))
(rplaca count (1+ (car count)))
(lyskom-format-insert "%5#1m %#2c %#1M\n"
conf
(lyskom-list-conf-membership-char
(conf-stat->conf-no conf)))
(set-marker (cdr count) (point))))
conf-no filter count time-string)
calls))
(setq conf-no (1+ conf-no)))
(lyskom-wait-queue 'main))
(quit
(lyskom-message (lyskom-get-string 'canceling-command))
(lyskom-cancel-calls calls)
(signal 'quit nil)))
(when (marker-position (cdr count))
(goto-char (cdr count)))
......
......@@ -2003,6 +2003,7 @@ written a presentation.%]
(mark-confs-as-known . "Mark these %#2d %#1s as known? ")
(no-new-conferences . "No new %#2s%#1?b%[ since %#1s%]%[%].\n")
(new-conferences-since . "New %#2s%#1?b%[ since %#1s%]%[%]:\n")
(list-confs-from-date . "List %#1s created since what date (empty for everything)? ")
(privs-wheel . "wheel")
(privs-admin . "administrator")
......@@ -2044,6 +2045,8 @@ Change privileges for %#1P (%#1p)...")
(set-flg14-priv-q . "Activate unknown privilege 14? ")
(set-flg15-priv-q . "Activate unknown privilege 15? ")
(set-flg16-priv-q . "Activate unknown privilege 16? ")
(canceling-command . "Canceling command...")
))
......
......@@ -198,9 +198,10 @@ settings and save them to your emacs init file."
(defun lyskom-save-options-2 (text-no kombuf done-message error-message)
(if text-no
(initiate-set-user-area 'options 'lyskom-save-options-3
lyskom-pers-no text-no kombuf
done-message error-message text-no)
(progn (setq lyskom-current-user-area text-no)
(initiate-set-user-area 'options 'lyskom-save-options-3
lyskom-pers-no text-no kombuf
done-message error-message text-no))
(save-excursion
(set-buffer kombuf)
(lyskom-insert-string 'could-not-save-options)
......@@ -250,95 +251,96 @@ non-nil, read settings in that buffer."
Returns a list of variables that were ignored."
(let ((ignored-user-area-vars nil))
(condition-case nil
(if text ;+++ Other error handler
(let* ((lyskom-options-text (text->text-mass text))
(pointers (lyskom-read-options-eval-get-holerith t))
common-no elisp-no
(rest lyskom-options-text)
working
(when text ;+++ Other error handler
(let* ((lyskom-options-text (text->text-mass text))
(pointers (lyskom-read-options-eval-get-holerith t))
common-no elisp-no
(rest lyskom-options-text)
working
(r 1))
(let* ((lyskom-options-text pointers)
word
(r 1))
(let* ((lyskom-options-text pointers)
word
(r 1))
(while (> (length lyskom-options-text) 2)
(setq word (lyskom-read-options-eval-get-holerith t))
(cond
((lyskom-string= word "common")
(setq common-no r))
((lyskom-string= word "elisp")
(setq elisp-no r))
(t
;; Build up lyskom-other-clients-user-areas so that it
;; contains a list of pairs: (name . number). (string, int).
(setq lyskom-other-clients-user-areas
(cons (cons word r) lyskom-other-clients-user-areas))))
(++ r)))
(setq lyskom-other-clients-user-areas
(nreverse lyskom-other-clients-user-areas))
(setq lyskom-options-text rest)
(while (> (length lyskom-options-text) 2)
(setq working (lyskom-read-options-eval-get-holerith t))
(setq word (lyskom-read-options-eval-get-holerith t))
(cond
;; Note that common-no may be nil here, so the comparison
;; cannot be performed with '=.
((equal r common-no)
(let ((lyskom-options-text working)
spec name value)
(while (> (length lyskom-options-text) 2)
(setq name (intern (lyskom-read-options-eval-get-holerith)))
(setq value (lyskom-read-options-eval-get-holerith))
(setq spec
(cond ((lyskom-flag-global-variable-from-common name))
(t (let ((tmp (vector name
(intern (format "lyskom-UNK-%S" name))
nil)))
(setq lyskom-global-variables
(cons tmp lyskom-global-variables))
tmp))))
(unless (lyskom-maybe-set-var-from-string (elt spec 1) value (elt spec 2))
(setq ignored-user-area-vars
(cons (elt spec 1) ignored-user-area-vars))))))
;; Note that elisp-no may be nil here, so the comparison
;; cannot be performed with '=.
((equal r elisp-no)
(let ((lyskom-options-text working)
name value)
(while (> (length lyskom-options-text) 2)
(setq name (intern (lyskom-read-options-eval-get-holerith)))
(setq value (lyskom-read-options-eval-get-holerith))
(if (lyskom-maybe-set-var-from-string name value)
(when (functionp (cdr (assq name lyskom-transition-variables)))
(set name (funcall (cdr (assq name lyskom-transition-variables))
(symbol-value name))))
(setq ignored-user-area-vars
(cons name ignored-user-area-vars))))))
((lyskom-string= word "common")
(setq common-no r))
((lyskom-string= word "elisp")
(setq elisp-no r))
(t
(let ((pos lyskom-other-clients-user-areas))
(while (and pos
(not (equal
(cdr (car pos)) ;The position or the string.
r)))
(setq pos (cdr pos)))
(if pos
(setcdr (car pos) working))))) ;Insert the string
;; Build up lyskom-other-clients-user-areas so that it
;; contains a list of pairs: (name . number). (string, int).
(setq lyskom-other-clients-user-areas
(cons (cons word r) lyskom-other-clients-user-areas))))
(++ r)))
(setq lyskom-other-clients-user-areas
(nreverse lyskom-other-clients-user-areas))
(setq lyskom-options-text rest)
(while (> (length lyskom-options-text) 2)
(setq working (lyskom-read-options-eval-get-holerith t))
(cond
;; Note that common-no may be nil here, so the comparison
;; cannot be performed with '=.
((equal r common-no)
(let ((lyskom-options-text working)
spec name value)
(while (> (length lyskom-options-text) 2)
(setq name (intern (lyskom-read-options-eval-get-holerith)))
(setq value (lyskom-read-options-eval-get-holerith))
(setq spec
(cond ((lyskom-flag-global-variable-from-common name))
(t (let ((tmp (vector name
(intern (format "lyskom-UNK-%S" name))
nil)))
(setq lyskom-global-variables
(cons tmp lyskom-global-variables))
tmp))))
(unless (lyskom-maybe-set-var-from-string (elt spec 1) value (elt spec 2))
(setq ignored-user-area-vars
(cons (elt spec 1) ignored-user-area-vars))))))
;; Note that elisp-no may be nil here, so the comparison
;; cannot be performed with '=.
((equal r elisp-no)
(let ((lyskom-options-text working)
name value)
(while (> (length lyskom-options-text) 2)
(setq name (intern (lyskom-read-options-eval-get-holerith)))
(setq value (lyskom-read-options-eval-get-holerith))
(if (lyskom-maybe-set-var-from-string name value)
(when (functionp (cdr (assq name lyskom-transition-variables)))
(set name (funcall (cdr (assq name lyskom-transition-variables))
(symbol-value name))))
(setq ignored-user-area-vars
(cons name ignored-user-area-vars))))))
(t
(let ((pos lyskom-other-clients-user-areas))
(while (and pos
(not (equal
(cdr (car pos)) ;The position or the string.
r)))
(setq pos (cdr pos)))
(if pos
(setcdr (car pos) working))))) ;Insert the string
;where the position
;was stored.
(++ r))
(mapcar 'lyskom-recompile-filter kom-permanent-filter-list)
(mapcar 'lyskom-recompile-filter kom-session-filter-list)
(setq lyskom-filter-list (append kom-permanent-filter-list
kom-session-filter-list))
(setq lyskom-do-when-done (cons kom-do-when-done kom-do-when-done))
;; Remove not found user-areas
(let ((pos lyskom-other-clients-user-areas))
(if pos
(progn
(while (stringp (cdr (car (cdr pos))))
(setq pos (cdr pos)))
(setcdr pos nil))))))
(++ r))
(mapcar 'lyskom-recompile-filter kom-permanent-filter-list)
(mapcar 'lyskom-recompile-filter kom-session-filter-list)
(setq lyskom-filter-list (append kom-permanent-filter-list
kom-session-filter-list))
(setq lyskom-do-when-done (cons kom-do-when-done kom-do-when-done))
;; Remove not found user-areas
(let ((pos lyskom-other-clients-user-areas))
(if pos
(progn
(while (stringp (cdr (car (cdr pos))))
(setq pos (cdr pos)))
(setcdr pos nil)))))
(setq lyskom-current-user-area (text->text-no text)))
(error (lyskom-message "%s" (lyskom-get-string 'error-in-options-short))))
(setq lyskom-options-done t)
(setq lyskom-current-user-area (if text (text->text-no text) 0))
......
......@@ -87,7 +87,7 @@ KOM-QUEUE is a kom-queue.")
;;; ('CALL REF-NO PARSER PARSER-DATA HANDLER HANDLER-DATA)
;;; A call that has not yet returned.
;;;
;;; ('PARSED RESULT HANDLER HANDLER-DATA)
;;; ('PARSED REF-NO RESULT HANDLER HANDLER-DATA)
;;; A call that has returned, but the result can not be
;;; handled until all previous calls has returned.
;;;
......@@ -120,7 +120,8 @@ KOM-QUEUE is a kom-queue.")
;;;
;;; ('RUN FUNCTION FUNCTION-ARGS)
;;; Run FUNCTION when all calls before this have been handled.
;;;
;;;
;;;
(defun kom-queue-create ()
......@@ -279,6 +280,44 @@ lyskom-fake-call, or the parser might get confused."
(lyskom-check-call kom-queue)))))
(defun lyskom-cancel-calls (ref-nos)
"Cancel the calls in the list REF-NOS.
Calls that have been sent to the server will have their callbacks
canceled, but as they have been sent, the client must wait for them
to complete in some way."
(let ((unsent nil))
(lyskom-traverse queue lyskom-output-queues
(lyskom-traverse ref-no ref-nos
(when (assq ref-no (car (cdr queue)))
(setq unsent (cons ref-no unsent)))))
;; (lyskom-format-insert "REF-NOS\n")
;; (lyskom-format-insert " %#1s\n" (format "%S" ref-nos))
;; (lyskom-format-insert "UNSENT\n")
;; (lyskom-format-insert " %#1s\n" (format "%S" unsent))
(lyskom-traverse queue lyskom-output-queues
(lyskom-queue-remove-matching queue
(lambda (el) (memq (car el) unsent))))
(lyskom-traverse queue lyskom-call-data
(lyskom-queue-remove-matching (kom-queue->pending (cdr queue))
(lambda (el)
(or (and (eq (car el) 'CALL)
(memq (car (cdr el)) unsent))
(and (eq (car el) 'PARSED)
(memq (car (cdr el)) ref-nos)))))
(lyskom-traverse call-data (car (cdr (kom-queue->pending (cdr queue))))
(when (and (eq (car call-data) 'CALL)
(memq (car (cdr call-data)) ref-nos))
;; (lyskom-format-insert "Canceling callback %#1d\n" (car (cdr call-data)))
(setcdr call-data
(list (elt (cdr call-data) 0) ; ref-no
(elt (cdr call-data) 1) ; parser
(elt (cdr call-data) 2) ; parser-data
nil ; handler, then handler-data
nil)))))
(lyskom-check-output-queues)))
;;;; ================================================================
......@@ -324,8 +363,9 @@ Args: KOM-QUEUE STRING."
(setq lyskom-pending-calls
(cons (cons lyskom-ref-no kom-queue)
lyskom-pending-calls))
(++ lyskom-ref-no)
(setq lyskom-ref-no (1+ lyskom-ref-no))
(when (< lyskom-ref-no 0) (setq lyskom-ref-no 1))
;; Send something from the output queues
(lyskom-check-output-queues))
......@@ -473,9 +513,9 @@ RUN -> call function. Delete. Not allowed inside COLLECT/USE."
(kom-queue-resume queue))
(if (or (eq (kom-queue->collect-flag queue) 'COLLECT)
(and (eq (kom-queue->collect-flag queue) 'COLLECT-IGNORE)
(car (cdr first-pending))))
(car (cdr (cdr first-pending)))))
(lyskom-queue-enter (kom-queue->collect-queue queue)
(car (cdr first-pending)))))
(car (cdr (cdr first-pending))))))
((eq type 'COLLECT)
(if (kom-queue->collect-flag queue)
......@@ -539,10 +579,10 @@ RUN -> call function. Delete. Not allowed inside COLLECT/USE."
PENDING is an entry of the list as described in documentation for the variable
lyskom-call-data. The car on the list must be a PARSED:
('PARSED RESULT HANDLER HANDLER-DATA)"
(if (car (cdr (cdr pending)))
(apply (car (cdr (cdr pending))) ;Handler
(car (cdr pending)) ;Result
(car (cdr (cdr (cdr pending))))))) ;Handler-data
(if (car (cdr (cdr (cdr pending))))
(apply (car (cdr (cdr (cdr pending)))) ;Handler
(car (cdr (cdr pending))) ;Result
(car (cdr (cdr (cdr (cdr pending)))))))) ;Handler-data
(defun lyskom-apply-multi-handler (pending result-list)
"Apply a handler for a lyskom-collect - lyskom-use construct."
......
......@@ -164,26 +164,23 @@ The value of the last form in BODY is returned.
Each element in BIND-LIST is a list (SYMBOL FORM) which binds SYMBOL to
the result of the server call FORM, which is the same as used in blocking-do.
All the forms in BIND-LIST are evaluated before any symbols are bound."
(let ((bindsym 'multiple-bind-sym)
(index 0))
(` (let (((, bindsym)
(lyskom-blocking-do-multiple
(list (,@ (mapcar (function (lambda (x)
(` (list '(, (car (car (cdr x))))
(,@ (cdr (car (cdr x))))))))
bind-list))))))
(let ((,@ (mapcar (function
(lambda (bpat)
(prog1
(` ((, (car bpat))
(elt (, bindsym) (, index))))
(setq index (1+ index)))))
bind-list)))
(,@ body))))))
(put 'blocking-do-multiple 'edebug-form-spec
'(sexp body))
(let ((index 0))
`(let ((lyskom-multiple-bind-sym
(lyskom-blocking-do-multiple
(list ,@(mapcar (lambda (x)
`(list ',(car (car (cdr x)))
,@(cdr (car (cdr x)))))
bind-list)))))
(let (,@(mapcar (lambda (bpat)
(prog1
`(,(car bpat) (elt lyskom-multiple-bind-sym
,index))
(setq index (1+ index))))
bind-list))
,@body))))
(put 'blocking-do-multiple 'edebug-form-spec '(sexp body))
(put 'blocking-do-multiple 'lisp-indent-function 1)
......@@ -347,6 +344,11 @@ the current buffer, and its value is copied from the LysKOM buffer."
(` (lyskom-set-default (quote (, name))
(, value))))
(defmacro lyskom-ref-no ()
`(prog1 lyskom-ref-no
(setq lyskom-ref-no (1+ lyskom-ref-no))
(when (< lyskom-ref-no 0) (setq lyskom-ref-no 1))))
(eval-and-compile (provide 'lyskom-macros))
......