[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/eglot e8f859e 031/139: Rework commands for connecting a
From: |
João Távora |
Subject: |
[elpa] externals/eglot e8f859e 031/139: Rework commands for connecting and reconnecting |
Date: |
Mon, 14 May 2018 09:54:48 -0400 (EDT) |
branch: externals/eglot
commit e8f859e77e5e6109efdc62ee257b261c54137aca
Author: João Távora <address@hidden>
Commit: João Távora <address@hidden>
Rework commands for connecting and reconnecting
* eglot.el (eglot--current-process-or-lose): Add doc.
(eglot--command): Remove.
(eglot--bootstrap-fn): New process-local variable.
(eglot--connect): Redesign.
(eglot-make-local-process): New function.
(eglot-reconnect): New interactive command.
(eglot-new-process): Redesign.
(eglot--process-sentinel): Add doc.
(eglot--protocol-initialize): Rework.
(eglot--mode-line-format): Use eglot-reconnect.
---
eglot.el | 139 +++++++++++++++++++++++++++++++++++++--------------------------
1 file changed, 81 insertions(+), 58 deletions(-)
diff --git a/eglot.el b/eglot.el
index fe63a29..c7bb5d4 100644
--- a/eglot.el
+++ b/eglot.el
@@ -54,6 +54,7 @@
(gethash cur eglot--processes-by-project)))))
(defun eglot--current-process-or-lose ()
+ "Return the current EGLOT process or error."
(or (eglot--current-process)
(eglot--error "No current EGLOT process%s"
(if (project-current) ""
@@ -109,29 +110,62 @@ A list (ID WHAT DONE-P)." t)
"Status as declared by the server.
A list (WHAT SERIOUS-P)." t)
-(defun eglot--command (&optional errorp)
- (let ((probe (cdr (assoc major-mode eglot-executables))))
- (unless (or (not errorp)
- probe)
- (eglot--error "Don't know how to start EGLOT for %s buffers"
- major-mode))
- probe))
+(eglot--define-process-var eglot--bootstrap-fn nil
+ "Function for returning processes/connetions to LSP servers.
+Must be a function of one arg, a name, returning a process
+object.")
-(defun eglot--connect (name filter sentinel)
- "Helper for `eglot-new-process'.
+(defun eglot-make-local-process (name command)
+ "Make a local LSP process from COMMAND.
NAME is a name to give the inferior process or connection.
-FILTER and SENTINEL are filter and sentinel.
-Should return a list of (PROCESS BUFFER)."
- (let ((proc (make-process :name name
- :buffer (get-buffer-create
- (format "*%s inferior*" name))
- :command (eglot--command 'error)
- :connection-type 'pipe
- :filter filter
- :sentinel sentinel
- :stderr (get-buffer-create (format "*%s stderr*"
- name)))))
- (list proc (process-buffer proc))))
+Returns a process object."
+ (let* ((readable-name (format "EGLOT server (%s)" name))
+ (proc
+ (make-process
+ :name readable-name
+ :buffer (get-buffer-create
+ (format "*%s inferior*" readable-name))
+ :command command
+ :connection-type 'pipe
+ :filter 'eglot--process-filter
+ :sentinel 'eglot--process-sentinel
+ :stderr (get-buffer-create (format "*%s stderr*"
+ name)))))
+ proc))
+
+(defun eglot--connect (short-name bootstrap-fn &optional success-fn)
+ "Make a connection with SHORT-NAME and BOOTSTRAP-FN.
+Call SUCCESS-FN with no args if all goes well."
+ (let* ((proc (funcall bootstrap-fn short-name))
+ (buffer (process-buffer proc)))
+ (setf (eglot--bootstrap-fn proc) bootstrap-fn)
+ (with-current-buffer buffer
+ (let ((inhibit-read-only t))
+ (setf (eglot--short-name proc) short-name)
+ (puthash (project-current) proc eglot--processes-by-project)
+ (erase-buffer)
+ (read-only-mode t)
+ (with-current-buffer (eglot-events-buffer proc)
+ (let ((inhibit-read-only t))
+ (insert
+ (format "\n-----------------------------------\n"))))
+ (eglot--protocol-initialize
+ proc
+ (cl-function
+ (lambda (&key capabilities)
+ (setf (eglot--capabilities proc) capabilities)
+ (setf (eglot--status proc) nil)
+ (when success-fn (funcall success-fn)))))))))
+
+(defun eglot-reconnect (process &optional interactive)
+ "Reconnect to PROCESS.
+INTERACTIVE is t if called interactively."
+ (interactive (list (eglot--current-process-or-lose) t))
+ (eglot-quit-server process 'sync interactive)
+ (eglot--connect (eglot--short-name process)
+ (eglot--bootstrap-fn process)
+ (lambda ()
+ (eglot--message "Reconnected"))))
(defun eglot-new-process (&optional interactive)
"Start a new EGLOT process and initialize it.
@@ -140,32 +174,28 @@ INTERACTIVE is t if called interactively."
(let ((project (project-current)))
(unless project (eglot--error "(new-process) Cannot work without a current
project!"))
(let ((current-process (eglot--current-process)))
- (when (and current-process
- (process-live-p current-process))
- (eglot--message "(new-process) Asking current process to terminate
first")
- (eglot-quit-server current-process 'sync interactive)))
- (let* ((short-name (file-name-base
- (directory-file-name
- (car (project-roots (project-current))))))
- (good-name
- (format "EGLOT server (%s)" short-name)))
- (pcase-let ((`(,proc ,buffer)
- (eglot--connect good-name
- 'eglot--process-filter
- 'eglot--process-sentinel)))
- (with-current-buffer buffer
- (let ((inhibit-read-only t))
- (setf (eglot--short-name proc) short-name)
- (puthash (project-current) proc eglot--processes-by-project)
- (erase-buffer)
- (read-only-mode t)
- (with-current-buffer (eglot-events-buffer proc)
- (let ((inhibit-read-only t))
- (insert
- (format "\n-----------------------------------\n"))))
- (eglot--protocol-initialize proc interactive)))))))
+ (cond ((and current-process
+ (process-live-p current-process))
+ (eglot--message "(new-process) Reconnecting instead")
+ (eglot-reconnect current-process interactive))
+ (t
+ (eglot--connect
+ (file-name-base
+ (directory-file-name
+ (car (project-roots (project-current)))))
+ (lambda (name)
+ (eglot-make-local-process
+ name
+ (let ((probe (cdr (assoc major-mode eglot-executables))))
+ (unless probe
+ (eglot--error "Don't know how to start EGLOT for %s
buffers"
+ major-mode))
+ probe)))
+ (lambda ()
+ (eglot--message "Connected"))))))))
(defun eglot--process-sentinel (process change)
+ "Called with PROCESS undergoes CHANGE."
(eglot--debug "(sentinel) Process state changed to %s" change)
(when (not (process-live-p process))
;; Remember to cancel all timers
@@ -459,10 +489,10 @@ identifier. ERROR is non-nil if this is an error."
;;; Requests
;;;
-(defun eglot--protocol-initialize (process interactive)
+(defun eglot--protocol-initialize (process success-fn)
"Initialize LSP protocol.
-PROCESS is a connected process (network or local).
-INTERACTIVE is t if caller was called interactively."
+PROCESS is a connected process (network or local). SUCCESS-FN is
+called with capabilites after connection."
(eglot--request
process
:initialize
@@ -476,14 +506,7 @@ INTERACTIVE is t if caller was called interactively."
:workspace (eglot--obj)
:textDocument (eglot--obj
:publishDiagnostics `(:relatedInformation t))))
- :success-fn (cl-function
- (lambda (&key capabilities)
- (setf (eglot--capabilities process) capabilities)
- (when interactive
- (setf (eglot--status process) nil)
- (eglot--message
- "Server reports %d capabilities"
- (length capabilities)))))))
+ :success-fn success-fn))
(defun eglot-quit-server (process &optional sync interactive)
"Politely ask the server PROCESS to quit.
@@ -687,12 +710,12 @@ running. INTERACTIVE is t if called interactively."
keymap ,(let ((map (make-sparse-keymap)))
(define-key map [mode-line mouse-1] 'eglot-events-buffer)
(define-key map [mode-line mouse-2] 'eglot-quit-server)
- (define-key map [mode-line mouse-3] 'eglot-new-process)
+ (define-key map [mode-line mouse-3] 'eglot-reconnect)
map)
mouse-face mode-line-highlight
help-echo ,(concat "mouse-1: go to events buffer\n"
"mouse-2: quit server\n"
- "mouse-3: new process"))
+ "mouse-3: reconnect to server"))
,@(when serious-p
`("/"
(:propertize
- [elpa] externals/eglot efd14d6 015/139: Fix mode line, (continued)
- [elpa] externals/eglot efd14d6 015/139: Fix mode line, João Távora, 2018/05/14
- [elpa] externals/eglot 63f2208 030/139: Less obstrusive flymake stuff for now, João Távora, 2018/05/14
- [elpa] externals/eglot 8bd634c 016/139: Start working on this again, João Távora, 2018/05/14
- [elpa] externals/eglot 3403f86 027/139: Correctly report what we currently are capable of, João Távora, 2018/05/14
- [elpa] externals/eglot 7c82a03 024/139: Start experimenting with python, João Távora, 2018/05/14
- [elpa] externals/eglot 8e6488f 023/139: Don't switch to possibly dead buffer in sentinel, João Távora, 2018/05/14
- [elpa] externals/eglot e1d36d2 014/139: Fix some byte-compilation warnings, João Távora, 2018/05/14
- [elpa] externals/eglot 6f6f01d 018/139: Doc fixes, João Távora, 2018/05/14
- [elpa] externals/eglot 7ec0dcf 029/139: Events buffer uses eglot-mode, source buffers use eglot-editing-mode, João Távora, 2018/05/14
- [elpa] externals/eglot 22dc2f7 034/139: Ready to start fixing flymake integration, João Távora, 2018/05/14
- [elpa] externals/eglot e8f859e 031/139: Rework commands for connecting and reconnecting,
João Távora <=
- [elpa] externals/eglot 92bf3a0 038/139: Signal textDocument/didClose, João Távora, 2018/05/14
- [elpa] externals/eglot b511b7d 036/139: Redesign and simplify parser, João Távora, 2018/05/14
- [elpa] externals/eglot 328c7ae 025/139: Auto update mode-line after setting some process properties, João Távora, 2018/05/14
- [elpa] externals/eglot 2b61a3b 048/139: Delete two useless forward declarations, João Távora, 2018/05/14
- [elpa] externals/eglot 88e3655 040/139: Appease checkdoc.el, João Távora, 2018/05/14
- [elpa] externals/eglot c948713 035/139: Auto-reconnect on unexpected connection loss, João Távora, 2018/05/14
- [elpa] externals/eglot 1dc2a9f 021/139: Implement spinners and RLS's window/progress, João Távora, 2018/05/14
- [elpa] externals/eglot 931093e 032/139: Don't clutter UI with warnings, João Távora, 2018/05/14
- [elpa] externals/eglot 95983c9 028/139: Change status to error everytime an error is found, João Távora, 2018/05/14
- [elpa] externals/eglot be52e1e 037/139: Rework connection restarting again, João Távora, 2018/05/14