Function: async-read-from-client

async-read-from-client is a natively compiled function defined in async.el.

Signature

(async-read-from-client PROC STRING &optional PROMPT-FOR-PWD)

Documentation

Process text from client process.

The string chunks usually arrive in maximum of 4096 bytes, so a long client message might be split into multiple calls of this function.

We use a marker async-read-marker to track the position of the lasts complete line. Every time we get new input, we try to look for newline, and if found, process the entire line and bump the marker position to the end of this next line.

Argument PROMPT-FOR-PWD allow binding lexically the value of async-prompt-for-password, if unspecified its global value is used.

Source Code

;; Defined in /nix/store/jhxqyr2zk061dl3wd3vm38lw3zin47b9-emacs-packages-deps/share/emacs/site-lisp/elpa/async-20260729.1431/async.el
(defun async-read-from-client (proc string &optional prompt-for-pwd)
  "Process text from client process.

The string chunks usually arrive in maximum of 4096 bytes, so a
long client message might be split into multiple calls of this
function.

We use a marker `async-read-marker' to track the position of the
lasts complete line.  Every time we get new input, we try to look
for newline, and if found, process the entire line and bump the
marker position to the end of this next line.

Argument PROMPT-FOR-PWD allow binding lexically the value of
`async-prompt-for-password', if unspecified its global value
is used."
  (with-current-buffer (process-buffer proc)
    (when (and prompt-for-pwd
               (boundp 'tramp-password-prompt-regexp)
               tramp-password-prompt-regexp
               (string-match tramp-password-prompt-regexp string))
      (process-send-string
       proc (concat (read-passwd (match-string 0 string)) "\n")))
    (goto-char (point-max))
    (save-excursion
      (insert string))

    (while (search-forward "\n" nil t)
      (save-excursion
        (save-restriction
          (widen)
          (narrow-to-region async-read-marker (point))
          (goto-char (point-min))
          (let (msg)
            (condition-case nil
                ;; It is safe to throw errors in the read because we
                ;; send messages always on their own line, and they
                ;; are always a base64 encoded string, so a message
                ;; will always read.  We will also ignore the rest
                ;; of this line since there won't be anything
                ;; interesting.
                (while (setq msg (read (current-buffer)))
                  (let ((msg-decoded (ignore-errors (base64-decode-string msg))))
                    (when msg-decoded
                      (setq msg-decoded (car (read-from-string msg-decoded)))
                      (when (and (listp msg-decoded)
                                 (async-message-p msg-decoded)
                                 async-callback)
                        (funcall async-callback msg-decoded)))))
              ;; This is OK, we reached the end of the chunk subprocess sent
              ;; at this time.
              (invalid-read-syntax t)
              (end-of-file t)))
          (goto-char (point-max))
          (move-marker async-read-marker (point)))))))