;; gnuserv asynchronous extensions ;; it should be compatible with previous versions for non-extensions (defvar gnuserv-async-clients '()) (defun gnuserv-delayed-eval (form) "Evaluate form, but don't return result to client. This can be used to implement asynchronous communication: The code executed needs to grab the value of the top of the `gnuserv-current-client' stack and send the value back later using (gnuserv-write-to-client client value). " (push gnuserv-current-client gnuserv-async-clients) (eval form) (setq gnuserv-current-client nil)) (defun gnuserv-async-reply (client form) (if (member client gnuserv-async-clients) (progn (set 'gnuserv-async-clients (remove client gnuserv-async-clients)) (gnuserv-write-to-client client form)) (error (format "Client ID %d is not in gnuserv-async-clients." client)))) (defun gnuserv-reply (value) "Send reply to current client if `gnuserv-current-client' is non-nil." (if gnuserv-current-client (gnuserv-write-to-client gnuserv-current-client value))) (defun gnuserv-eval (form) "Evaluate form and send back to current client. (see gnuserv-reply)." (let ((value (eval form))) (gnuserv-reply value))) (defun gnuserv-write-eval (form) "Like gnuserv-eval, but using write semantics. (lisp channel)." (let ((value (eval form))) (gnuserv-reply (pp-to-string value)))) ; (gnuserv-async-reply (gnuserv-async-last-client) 'done) ; (gnuserv-async-reply 4 123) ; (gnuserv-start) ; (gnuserv-write-to-client 4 123) ; gnuserv-async-clients ;; some hacks (defvar gnuserv-async-edits '()) (defun gnuserv-async () (gnuserv-delayed-eval nil)) ; side effect: gnuserv-eval won't send reply (defun gnuserv-async-edit (text) (gnuserv-async) (let ((buffer (find-file (tempfile "async-edit")))) ; we'll put it in a temp file for safety (push (cons buffer (car gnuserv-async-clients)) gnuserv-async-edits) (insert text))) (defun fix-unicode-char (x) (if (> x 127) 64 x)) (defun fix-unicode-string (str) (apply 'string (mapcar 'fix-unicode-char (string-to-list str)))) (defun gnuserv-async-edit-reply () (interactive) (let ((async-edit (assoc (current-buffer) gnuserv-async-edits))) (let ((text (buffer-string))) (kill-this-buffer) (gnuserv-async-reply (cdr async-edit) (pp-to-string ;; so output can be read to string (fix-unicode-string ;; weird crashes without this... text)))))) ; (gnuserv-async-edit-reply) ; gnuserv-async-clients