emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/async 3bd17d58e1 4/4: Merge pull request #167 from Fuco


From: ELPA Syncer
Subject: [elpa] externals/async 3bd17d58e1 4/4: Merge pull request #167 from Fuco1/feature/implement-child-messages
Date: Thu, 9 Mar 2023 07:57:24 -0500 (EST)

branch: externals/async
commit 3bd17d58e1ca14c629e72acfbd77138ff5adc1d6
Merge: 71cc50f27f a982ab7a9a
Author: Thierry Volpiatto <thievol@posteo.net>
Commit: GitHub <noreply@github.com>

    Merge pull request #167 from Fuco1/feature/implement-child-messages
    
    feat: implement reading messages sent from child process
---
 async.el | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 66 insertions(+), 7 deletions(-)

diff --git a/async.el b/async.el
index 244954feb4..3761354f73 100644
--- a/async.el
+++ b/async.el
@@ -197,6 +197,27 @@ It is intended to be used as follows:
                              (process-name proc) (process-exit-status proc))))
           (set (make-local-variable 'async-callback-value-set) t))))))
 
+(defun async-read-from-client (proc string)
+  ;; log the message in the process buffer
+  (with-current-buffer (process-buffer proc)
+    (insert string))
+
+  ;; parse message
+  (with-temp-buffer
+    (insert string)
+    (goto-char (point-min))
+    (let (msg)
+      (condition-case nil
+          (while (setq msg (read (current-buffer)))
+            (when-let ((msg-decoded (ignore-errors (base64-decode-string 
msg))))
+              (setq msg-decoded (car (read-from-string msg-decoded)))
+              (with-current-buffer (process-buffer proc)
+                (when async-callback
+                  (funcall async-callback msg-decoded)))))
+        ;; This is OK, we reached the end of the chunk subprocess sent
+        ;; at this time.
+        (end-of-file t)))))
+
 (defun async--receive-sexp (&optional stream)
   ;; FIXME: Why use `utf-8-auto' instead of `utf-8-unix'?  This is
   ;; a communication channel over which we have complete control,
@@ -280,20 +301,47 @@ its FINISH-FUNC is nil."
          #'identity async-callback-value (current-buffer))))))
 
 (defun async-message-p (value)
-  "Return non-nil of VALUE is an async.el message packet."
+  "Return non-nil if VALUE is an async.el message packet."
   (and (listp value)
        (plist-get value :async-message)))
 
-(defun async-send (&rest args)
-  "Send the given messages to the asynchronous Emacs PROCESS."
+(defun async-send (process-or-key &rest args)
+  "Send the given message to the asychronous child or parent Emacs.
+
+To send messages from the parent to a child, PROCESS-OR-KEY is
+the child process object.  ARGS is a plist.  Example:
+
+  (async-send proc :operation :load-file :file \"this file\")
+
+To send messages from the child to the parent, PROCESS-OR-KEY is
+the first key of the plist, ARGS is a value followed by
+optionally more key-value pairs.  Example:
+
+  (async-send :status \"finished\" :file-size 123)"
   (let ((args (append args '(:async-message t))))
     (if async-in-child-emacs
-        (if async-callback
-            (funcall async-callback args))
-      (async--transmit-sexp (car args) (list 'quote (cdr args))))))
+        (princ
+         (with-temp-buffer
+           (async--insert-sexp (cons process-or-key args))
+           (buffer-string)))
+      (async--transmit-sexp process-or-key (list 'quote args)))))
 
 (defun async-receive ()
-  "Send the given messages to the asynchronous Emacs PROCESS."
+  "Receive message from parent Emacs.
+
+The child process blocks until a message is received.
+
+Message is a plist with one key :async-message set to t always
+automatically added to signify this plist is an async message.
+
+You can use `async-message-p' to test if the payload was a
+message.
+
+Use
+
+   (let ((msg (async-receive))) ...)
+
+to read and process a message."
   (async--receive-sexp))
 
 ;;;###autoload
@@ -310,6 +358,7 @@ working directory."
     (with-current-buffer buf
       (set (make-local-variable 'async-callback) finish-func)
       (set-process-sentinel proc #'async-when-done)
+      (set-process-filter proc #'async-read-from-client)
       (unless (string= name "emacs")
         (set (make-local-variable 'async-callback-for-process) t))
       proc)))
@@ -351,6 +400,16 @@ When done, the return value is passed to FINISH-FUNC.  
Example:
          (message \"Async process done, result should be 222: %s\"
                   result)))
 
+If you call `async-send' from a child process, the message will
+be also passed to the FINISH-FUNC.  You can test RESULT to see if
+it is a message by using `async-message-p'.  If nil, it means
+this is the final result.  Example of the FINISH-FUNC:
+
+    (lambda (result)
+      (if (async-message-p result)
+          (message \"Received a message from child process: %s\" result)
+        (message \"Async process done, result: %s\" result)))
+
 If FINISH-FUNC is nil or missing, a future is returned that can
 be inspected using `async-get', blocking until the value is
 ready.  Example:



reply via email to

[Prev in Thread] Current Thread [Next in Thread]