Eglot: fix M-x eglot-show-workspace-configuration (bug#61866)

Now consult .dir-locals.el every time the workspace configuration is
needed:

- workspace/configuration server request
- workspace/didChangeConfiguration signal
- M-x eglot-show-workspace-configuration

The major-mode/hack-dir-local-variables-non-file-buffer trick is used.
When there is more than one, the server connection's "main" major mode
is used to find the relevant .dir-locals.el section.

* lisp/progmodes/eglot.el (eglot--lookup-mode): Fix docstring.
(eglot--connect): Simplify.
(eglot-show-workspace-configuration): Fix.
(eglot--workspace-configuration): Remove.
(eglot--workspace-configuration-plist): Rework.
(eglot-handle-request): Simplify.
This commit is contained in:
João Távora 2023-03-01 01:22:15 +00:00
parent 48a0804d10
commit 97a83ff31f

View file

@ -961,7 +961,7 @@ PRESERVE-BUFFERS as in `eglot-shutdown', which see."
"Lookup `eglot-server-programs' for MODE. "Lookup `eglot-server-programs' for MODE.
Return (MANAGED-MODES LANGUAGE-ID CONTACT-PROXY). Return (MANAGED-MODES LANGUAGE-ID CONTACT-PROXY).
MANAGED-MODES is a list with MODE as its first elements. MANAGED-MODES is a list with MODE as its first element.
Subsequent elements are other major modes also potentially Subsequent elements are other major modes also potentially
managed by the server that is to manage MODE. managed by the server that is to manage MODE.
@ -1335,10 +1335,7 @@ This docstring appeases checkdoc, that's all."
(lambda () (lambda ()
(setf (eglot--inhibit-autoreconnect server) (setf (eglot--inhibit-autoreconnect server)
(null eglot-autoreconnect))))))) (null eglot-autoreconnect)))))))
(let ((default-directory (project-root project)) (run-hook-with-args 'eglot-connect-hook server)
(major-mode (car managed-modes)))
(hack-dir-local-variables-non-file-buffer)
(run-hook-with-args 'eglot-connect-hook server))
(eglot--message (eglot--message
"Connected! Server `%s' now managing `%s' buffers \ "Connected! Server `%s' now managing `%s' buffers \
in project `%s'." in project `%s'."
@ -2444,9 +2441,7 @@ format described above.")
(defun eglot-show-workspace-configuration (&optional server) (defun eglot-show-workspace-configuration (&optional server)
"Dump `eglot-workspace-configuration' as JSON for debugging." "Dump `eglot-workspace-configuration' as JSON for debugging."
(interactive (list (and (eglot-current-server) (interactive (list (eglot--read-server "Show workspace configuration for" t)))
(eglot--read-server "Server configuration"
(eglot-current-server)))))
(let ((conf (eglot--workspace-configuration-plist server))) (let ((conf (eglot--workspace-configuration-plist server)))
(with-current-buffer (get-buffer-create "*EGLOT workspace configuration*") (with-current-buffer (get-buffer-create "*EGLOT workspace configuration*")
(erase-buffer) (erase-buffer)
@ -2457,14 +2452,23 @@ format described above.")
(json-pretty-print-buffer)) (json-pretty-print-buffer))
(pop-to-buffer (current-buffer))))) (pop-to-buffer (current-buffer)))))
(defun eglot--workspace-configuration (server) (defun eglot--workspace-configuration-plist (server &optional path)
(if (functionp eglot-workspace-configuration) "Returns SERVER's workspace configuration as a plist.
(funcall eglot-workspace-configuration server) If PATH consider that file's `file-name-directory' to get the
eglot-workspace-configuration)) local value of the `eglot-workspace-configuration' variable, else
use the root of SERVER's `eglot--project'."
(defun eglot--workspace-configuration-plist (server) (let ((val (with-temp-buffer
"Returns `eglot-workspace-configuration' suitable for serialization." (setq default-directory
(let ((val (eglot--workspace-configuration server))) (if path
(file-name-directory path)
(project-root (eglot--project server))))
;; Set the major mode to be the first of the managed
;; modes. This is the one the user started eglot in.
(setq major-mode (car (eglot--major-modes server)))
(hack-dir-local-variables-non-file-buffer)()
(if (functionp eglot-workspace-configuration)
(funcall eglot-workspace-configuration server)
eglot-workspace-configuration))))
(or (and (consp (car val)) (or (and (consp (car val))
(cl-loop for (section . v) in val (cl-loop for (section . v) in val
collect (if (keywordp section) section collect (if (keywordp section) section
@ -2489,25 +2493,17 @@ When called interactively, use the currently active server"
(apply #'vector (apply #'vector
(mapcar (mapcar
(eglot--lambda ((ConfigurationItem) scopeUri section) (eglot--lambda ((ConfigurationItem) scopeUri section)
(with-temp-buffer (cl-loop
(let* ((uri-path (eglot--uri-to-path scopeUri)) with scope-uri-path = (and scopeUri (eglot--uri-to-path scopeUri))
(default-directory for (wsection o)
(if (and uri-path on (eglot--workspace-configuration-plist server scope-uri-path)
(not (string-empty-p uri-path)) by #'cddr
(file-directory-p uri-path)) when (string=
(file-name-as-directory uri-path) (if (keywordp wsection)
(project-root (eglot--project server))))) (substring (symbol-name wsection) 1)
(setq-local major-mode (car (eglot--major-modes server))) wsection)
(hack-dir-local-variables-non-file-buffer) section)
(cl-loop for (wsection o) return o))
on (eglot--workspace-configuration-plist server)
by #'cddr
when (string=
(if (keywordp wsection)
(substring (symbol-name wsection) 1)
wsection)
section)
return o))))
items))) items)))
(defun eglot--signal-textDocument/didChange () (defun eglot--signal-textDocument/didChange ()