Subject: bug#61350: Eglot over Tramp freezes with large project

From: Stefan Monnier <[email-masked]>
Date: Thu, 16 Mar 2023 16:36:03 -0400

> The gist it is, but also very broken.  As ever, vapourware sucks. This
> is what that snippet should have been:
>
>   ;;; hal.el --- asdasd                                -*- lexical-binding: t; -*-
>   (defvar hal-proc nil)
>   (defun hal-connect()
>     (interactive)
>     (when (processp hal-proc) (delete-process hal-proc))
>     (setq hal-proc
>           (make-process
>            :name "halproc"
>            :command (list (expand-file-name "hal" default-directory))
>            :buffer (generate-new-buffer "*halbuf*")
>            :filter (lambda (proc output)
>                      (internal-default-process-filter proc output)
>                      (when-let* ((buffer (process-buffer proc))
>                                  (callback (and (buffer-live-p buffer)
>                                                 (process-get proc 'callback))))
>                        (with-current-buffer buffer
>                          (save-excursion
>                            (goto-char (point-min))
>                            (when (search-forward ", DAVE\n" nil t)
>                              (unwind-protect (funcall callback
>                                                       (buffer-substring
>                                                        (point-min) (point)))
>                                (process-put proc 'callback nil)
>                                (delete-region (point-min)
>                                (point)))))))))))
>    
>   (defun hal-command ()  "Synch command to HAL that doesn't block others."
>     (interactive)
>     (message
>      (catch 'hal-done
>        (process-put hal-proc 'callback
>                     (lambda (result) (throw 'hal-done result)))
>        (process-send-string hal-proc "OPEN THE POD BAY DOORS!\n")
>        (while (accept-process-output hal-proc)))))

:-)

I think doing more of the work asynchronously (i.e. from the process's
filters/sentinels rather than after `accept-process-output`), like in
this example, is virtually always better, yes.

The use of `catch/throw` is not applicable to code which may be used
asynchronously (i.e. where we don't know that there's always a `catch`
waiting for our `throw`), so I hope we can get code to work just as
reliably without using `catch/throw`.

This mission is too important for me to allow you to jeopardize it.

        Stefan