From: João Távora Date: Fri, 11 May 2018 09:59:59 +0000 (+0100) Subject: Rework autoreconnection logic X-Git-Tag: emacs-29.0.90~1616^2~524^2~4^2~584 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=4af0193fad1ca40b48db4fba5b27e8a6f6c8d11a;p=emacs.git Rework autoreconnection logic Can't be a global var, has to be a per process thing. * eglot.el (eglot-autoreconnect): New defcustom (eglot--inhibit-autoreconnect): Renamed from eglot--inhibit-autoreconnect (eglot--connect): Run autoreconnect timer here. (eglot--inhibit-auto-reconnect): Removed. (eglot--process-sentinel): Don't run timer here. Rework. (eglot, eglot-reconnect): Pass INTERACTIVE to eglot--connect. --- diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index 3b3aada055b..aabaf5407f5 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -59,9 +59,19 @@ "Face for package-name in EGLOT's mode line.") (defcustom eglot-request-timeout 10 - "How many seconds to way for a reply from the server." + "How many seconds to wait for a reply from the server." :type :integer) +(defcustom eglot-autoreconnect 3 + "Control EGLOT's ability to reconnect automatically. +If t, always reconnect automatically (not recommended). If nil, +never reconnect automatically after unexpected server shutdowns, +crashes or network failures. A positive integer number says to +only autoreconnect if the previous successful connection attempt +lasted more than that many seconds." + :type '(choice (boolean :tag "Whether to inhibit autoreconnection") + (integer :tag "Number of seconds"))) + ;;; Process management (defvar eglot--processes-by-project (make-hash-table :test #'equal) @@ -129,6 +139,9 @@ A list (ID WHAT DONE-P).") "Status as declared by the server. A list (WHAT SERIOUS-P).") +(eglot--define-process-var eglot--inhibit-autoreconnect eglot-autoreconnect + "If non-nil, don't autoreconnect on unexpected quit.") + (eglot--define-process-var eglot--contact nil "Method used to contact a server. Either a list of strings (a shell command and arguments), or a @@ -206,8 +219,9 @@ CONTACT is as `eglot--contact'. Returns a process object." :publishDiagnostics `(:relatedInformation :json-false)) :experimental (eglot--obj))) -(defun eglot--connect (project managed-major-mode short-name contact) - "Connect for PROJECT, MANAGED-MAJOR-MODE, SHORT-NAME and CONTACT." +(defun eglot--connect (project managed-major-mode short-name contact interactive) + "Connect for PROJECT, MANAGED-MAJOR-MODE, SHORT-NAME and CONTACT. +INTERACTIVE is t if inside interactive call." (let* ((proc (eglot--make-process short-name managed-major-mode contact)) (buffer (process-buffer proc))) (setf (eglot--contact proc) contact @@ -215,6 +229,15 @@ CONTACT is as `eglot--contact'. Returns a process object." (eglot--major-mode proc) managed-major-mode) (with-current-buffer buffer (let ((inhibit-read-only t)) + (setf (eglot--inhibit-autoreconnect proc) + (cond + ((booleanp eglot-autoreconnect) (not eglot-autoreconnect)) + (interactive nil) + ((cl-plusp eglot-autoreconnect) + (run-with-timer eglot-autoreconnect nil + (lambda () + (setf (eglot--inhibit-autoreconnect proc) + (null eglot-autoreconnect))))))) (setf (eglot--short-name proc) short-name) (push proc (gethash project eglot--processes-by-project)) (erase-buffer) @@ -317,7 +340,8 @@ INTERACTIVE is t if called interactively." (let ((proc (eglot--connect project managed-major-mode short-name - command))) + command + interactive))) (eglot--message "Connected! Process `%s' now \ managing `%s' buffers in project `%s'." proc managed-major-mode short-name)))))) @@ -331,12 +355,10 @@ INTERACTIVE is t if called interactively." (eglot--connect (eglot--project process) (eglot--major-mode process) (eglot--short-name process) - (eglot--contact process)) + (eglot--contact process) + interactive) (eglot--message "Reconnected!")) -(defvar eglot--inhibit-auto-reconnect nil - "If non-nil, don't autoreconnect on unexpected quit.") - (defun eglot--process-sentinel (proc change) "Called when PROC undergoes CHANGE." (eglot--log-event proc `(:message "Process state changed" :change ,change)) @@ -364,22 +386,13 @@ INTERACTIVE is t if called interactively." (setf (gethash (eglot--project proc) eglot--processes-by-project) (delq proc (gethash (eglot--project proc) eglot--processes-by-project))) - (cond ((eglot--moribund proc) - (eglot--message "(sentinel) Moribund process exited with status %s" - (process-exit-status proc))) - ((null eglot--inhibit-auto-reconnect) - (eglot--warn - "(sentinel) Reconnecting after process unexpectedly changed to `%s'." - change) - (setq eglot--inhibit-auto-reconnect - (run-with-timer 3 nil - (lambda () - (setq eglot--inhibit-auto-reconnect nil)))) + (eglot--message "Server exited with status %s" (process-exit-status proc)) + (cond ((eglot--moribund proc)) + ((not (eglot--inhibit-autoreconnect proc)) + (eglot--warn "Reconnecting unexpected server exit.") (eglot-reconnect proc)) (t - (eglot--warn - "(sentinel) Not auto-reconnecting, last one didn't last long." - change))) + (eglot--warn "Not auto-reconnecting, last one didn't last long."))) (delete-process proc)))) (defun eglot--process-filter (proc string)