emacs-elpa-diffs
[Top][All Lists]
Advanced

[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)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]