[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/eglot 18d4627329 2/2: Per #590: Rework README.md about
From: |
ELPA Syncer |
Subject: |
[elpa] externals/eglot 18d4627329 2/2: Per #590: Rework README.md about workspace configuration again |
Date: |
Fri, 16 Sep 2022 21:57:36 -0400 (EDT) |
branch: externals/eglot
commit 18d462732946a2cb23f4d69b427d56b6f2d274e5
Author: João Távora <joaotavora@gmail.com>
Commit: João Távora <joaotavora@gmail.com>
Per #590: Rework README.md about workspace configuration again
Also tweak eglot-show-workspace-configuration a bit.
* README.md (Workspace configuration): Rework.
* eglot.el (eglot-show-workspace-configuration): Rework.
(eglot--workspace-configuration-plist): New helper.
---
README.md | 103 ++++++++++++++++++++++++++++++++++++++++++++++----------------
eglot.el | 43 +++++++++++++++-----------
2 files changed, 102 insertions(+), 44 deletions(-)
diff --git a/README.md b/README.md
index a98cfb643f..808c78b664 100644
--- a/README.md
+++ b/README.md
@@ -137,41 +137,83 @@ the ensuing TCP connection finds a listening server.
## Workspace configuration
Many servers can guess good defaults and operate nicely
-out-of-the-box, but some need to be configured via a special LSP
-`workspace/configuration` RPC call to work at all. Additionally, you
-may also want a particular server to operate differently across
-different projects.
+out-of-the-box, but some need to know project-specific settings, which
+LSP calls "workspace configuration".
-Per-project settings are realized with the Elisp variable
-`eglot-workspace-configuration`.
+These per-project settings are realized with the Elisp variable
+`eglot-workspace-configuration`.
+
+This variable's value is sent over to the server:
+
+* initially, as a [`didChangeConfiguration`
notification][did-change-configuration];
+* as the response to [configuration request][configuration-request] from the
server.
Before considering what to set the variable to, one must understand
-_how_ to set it. `eglot-workspace-configuration` is a
-"directory-local" variable, and setting its variable globally or
-buffer-locally likely makes no sense. It should be set via
-`.dir-locals.el` or equivalent mechanisms.
+_how_ to set it. `eglot-workspace-configuration` is a ["directory
+variable"][dir-locals-emacs-manual]. Setting it globally or
+buffer-locally makes little sense. It is usually set via
+`.dir-locals.el` or [special-purpose elisp
+functions][dir-locals-emacs-manual].
+
+#### Format
+
+The variable's value is an _association list_:
+
+```
+((SECTION-1 . PARAM-OBJECT-1)
+ ...
+ (SECTION-N . PARAM-OBJECT-N))
+```
+
+`SECTION-N` is an Elisp keyword naming the parameter section
+understood by the server. `PARAM-OBJECT-N` contains one or more
+settings pertaining to that server.
-The variable's value is an _association list_ of _parameter sections_
-to _parameter objects_. Names and formats of section and parameter
-objects are server specific.
+`PARAM-OBJECT-N` is an Elisp object serialized to JSON by
+[`json-serialize`][json-serialize]. The recommended format used in
+this manual's examples is a [plist][plist] of keyword-value pairs,
+though `json-serialize` also accepts other formats.
+
+When experimenting with settings, one may use `M-x
+eglot-show-workspace-configuration` to inspect/debug the definite JSON
+value sent over to the server. This helper function works even before
+actually connecting to the server.
#### Simple `eglot-workspace-configuration`
To make a particular Python project always enable Pyls's snippet
-support, put a file named `.dir-locals.el` in the project's root:
+support, you may put a file named `.dir-locals.el` in the project's
+root:
```lisp
((python-mode
. ((eglot-workspace-configuration
- . ((:pyls . (:plugins (:jedi_completion (:include_params t)))))))))
+ .
+ ;; the value in the format described above starts here
+ ((:pyls . (:plugins (:jedi_completion (:include_params t
+ :fuzzy t)
+ :pylint (:enabled :json-false)))))
+ ;; and ends here
+ ))))
```
This tells Emacs that any `python-mode` buffers in that directory
should have a particular value of `eglot-workspace-configuration`.
-Here, the value in question associates section `:pyls` with parameters
-`(:plugins (:jedi_completion (:include_params t)))`. The parameter
-object is a plist converted to JSON before being sent to the server.
+Here, the value in question associates a parameter section `:pyls`
+with a parameter objct that is a plist of plists. It is converted to
+JSON before being sent to the server:
+
+```json
+{
+ "pyls": {
+ "plugins": {
+ "jedi_completion": { "include_params": true, "fuzzy": true },
+ "pylint": { "enabled": false }
+ }
+ }
+}
+```
#### Multiple servers in `eglot-workspace-configuration`
@@ -182,20 +224,25 @@ a section for `go-mode`, the file's contents now become:
```lisp
((python-mode
. ((eglot-workspace-configuration
- . ((:pyls . (:plugins (:jedi_completion (:include_params t))))))))
+ . ((:pyls . (:plugins (:jedi_completion (:include_params t
+ :fuzzy t)
+ :pylint (:enabled :json-false))))))))
(go-mode
. ((eglot-workspace-configuration
. ((:gopls . (:usePlaceholders t)))))))
```
Alternatively, as a matter of taste, you may choose this equivalent
-setup, which sets the variables value in all all major modes of all
-buffers of a given project.
+setup. This sets the value in all major-modes inside the project: the
+major-mode specification is unneeded because the LSP server will
+retrieve only the parameter section it is interested in.
```lisp
((nil
. ((eglot-workspace-configuration
- . ((:pyls . (:plugins (:jedi_completion (:include_params t))))
+ . ((:pyls . (:plugins (:jedi_completion (:include_params t
+ :fuzzy t)
+ :pylint (:enabled :json-false))))
(:gopls . (:usePlaceholders t)))))))
```
@@ -211,10 +258,10 @@ leverage per-directory local variables. Look for the
functions
If you need to determine the workspace configuration base on some
dynamic context, make `eglot-workspace-configuration` a function. It
-is passed the `eglot-lsp-server` instance and runs with
-`default-directory` set to the root of your project. The function
-should return a value of the same form as described in the previous
-paragraphs.
+is passed the `eglot-lsp-server` instance of the connected server (if
+any) and runs with `default-directory` set to the root of your
+project. The function should return a value of the same form as
+described in the previous paragraphs.
## Handling quirky servers
@@ -626,3 +673,7 @@ for the request form, and we'll send it to you.
[copyright-assignment]: https://www.fsf.org/licensing/contributor-faq
[legally-significant]:
https://www.gnu.org/prep/maintain/html_node/Legally-Significant.html#Legally-Significant
[dir-locals-emacs-manual]:
https://www.gnu.org/software/emacs/manual/html_node/emacs/Directory-Variables.html
+[configuration-request]:
https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#workspace_configuration
+[did-change-configuration]:
https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#workspace_didChangeConfiguration
+[json-serialize]:
https://www.gnu.org/software/emacs/manual/html_node/elisp/Parsing-JSON.html
+[plist]:
https://www.gnu.org/software/emacs/manual/html_node/elisp/Property-Lists.html
diff --git a/eglot.el b/eglot.el
index 91733a8d7a..f02ec73043 100644
--- a/eglot.el
+++ b/eglot.el
@@ -58,7 +58,6 @@
;;; Code:
-(require 'json)
(require 'imenu)
(require 'cl-lib)
(require 'project)
@@ -2204,23 +2203,28 @@ SECTION should be a keyword or a string. VALUE is a
plist or a primitive type converted to JSON.
The value of this variable can also be a unary function of a
-`eglot-lsp-server' instance, the server connection requesting the
-configuration. It should return an alist of the format described
-above.")
+single argument, which will be a connected `eglot-lsp-server'
+instance. The function runs with `default-directory' set to the
+root of the current project. It should return an alist of the
+format described above.")
;;;###autoload
(put 'eglot-workspace-configuration 'safe-local-variable 'listp)
-(defun eglot-show-configuration (server)
- "Dump `eglot-workspace-configuration' as json for debugging."
- (interactive (list (eglot--read-server "Server configuration"
- (eglot-current-server))))
- (let ((conf (eglot--workspace-configuration server)))
- (with-current-buffer (get-buffer-create " *eglot configuration*")
+(defun eglot-show-workspace-configuration (&optional server)
+ "Dump `eglot-workspace-configuration' as JSON for debugging."
+ (interactive (list (and (eglot-current-server)
+ (eglot--read-server "Server configuration"
+ (eglot-current-server)))))
+ (let ((conf (eglot--workspace-configuration-plist server)))
+ (with-current-buffer (get-buffer-create "*EGLOT workspace configuration*")
(erase-buffer)
(insert (jsonrpc--json-encode conf))
- (json-mode)
- (json-pretty-print-buffer)
+ (with-no-warnings
+ (require 'json)
+ (require 'json-mode)
+ (json-mode)
+ (json-pretty-print-buffer))
(pop-to-buffer (current-buffer)))))
(defun eglot--workspace-configuration (server)
@@ -2228,6 +2232,14 @@ above.")
(funcall eglot-workspace-configuration server)
eglot-workspace-configuration))
+(defun eglot--workspace-configuration-plist (server)
+ "Returns `eglot-workspace-configuraiton' suitable serialization."
+ (or (cl-loop for (section . v) in (eglot--workspace-configuration server)
+ collect (if (keywordp section) section
+ (intern (format ":%s" section)))
+ collect v)
+ eglot--{}))
+
(defun eglot-signal-didChangeConfiguration (server)
"Send a `:workspace/didChangeConfiguration' signal to SERVER.
When called interactively, use the currently active server"
@@ -2236,12 +2248,7 @@ When called interactively, use the currently active
server"
server :workspace/didChangeConfiguration
(list
:settings
- (or (cl-loop for (section . v) in (eglot--workspace-configuration server)
- collect (if (keywordp section)
- section
- (intern (format ":%s" section)))
- collect v)
- eglot--{}))))
+ (eglot--workspace-configuration-plist server))))
(cl-defmethod eglot-handle-request
(server (_method (eql workspace/configuration)) &key items)