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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/eglot b406818 07/54: Fix #326: support workspace/config


From: João Távora
Subject: [elpa] externals/eglot b406818 07/54: Fix #326: support workspace/configuration
Date: Thu, 16 Apr 2020 05:31:45 -0400 (EDT)

branch: externals/eglot
commit b4068181a8db1129dcd4eaf3e881f10067662e0e
Author: João Távora <address@hidden>
Commit: João Távora <address@hidden>

    Fix #326: support workspace/configuration
    
    This helps users configure servers such as Gopls, which doesn't
    support didChangeConfiguration signals.
    
    * README.md (Per-project server configuration): New section.
    
    * eglot.el (eglot-workspace-configuration): Fix docstring.
    (eglot-signal-didChangeConfiguration): Rename a variable.
    (eglot-handle-request workspace/configuration): New request
    handler.
---
 NEWS.md   |  8 ++++++++
 README.md | 52 +++++++++++++++++++++++++++++++++++++++++++++++-----
 eglot.el  | 40 ++++++++++++++++++++++++++++++++--------
 3 files changed, 87 insertions(+), 13 deletions(-)

diff --git a/NEWS.md b/NEWS.md
index 2e05aa2..0b4cb9e 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -1,3 +1,10 @@
+# 1.6 (upcoming)
+
+##### Support workspace/configuration requests ([#326][github#326])
+
+Also a new section "Per-project server configuration" in the README.md
+should answer some faq's in this regard.
+
 # 1.5 (20/10/2019)
 
 Thanks a lot to Felicián Németh, Ingo Lohmar, and everyone else who
@@ -197,3 +204,4 @@ and now said bunch of references-->
 [github#313]: https://github.com/joaotavora/eglot/issues/313
 [github#316]: https://github.com/joaotavora/eglot/issues/316
 [github#324]: https://github.com/joaotavora/eglot/issues/324
+[github#326]: https://github.com/joaotavora/eglot/issues/326
diff --git a/README.md b/README.md
index f0cbc1e..231266e 100644
--- a/README.md
+++ b/README.md
@@ -94,12 +94,54 @@ it be started as a server.  Notice the `:autoport` symbol 
in there: it
 is replaced dynamically by a local port believed to be vacant, so that
 the ensuing TCP connection finds a listening server.
 
-## Handling quirky servers
+## Per-project server configuration
 
 Most servers can guess good defaults and will operate nicely
-out-of-the-box, but some need to be configured specially via LSP's
-interfaces.  If your server has some quirk or non-conformity, it's
-possible to extend Eglot to adapt to it.  Here's an example on how to
+out-of-the-box, but some need to be configured specially via LSP
+interfaces.  Additionally, in some situations, you may also want a
+particular server to operate differently across different projects.
+
+Per-project settings are realized with Emacs's _directory variables_
+and the Elisp variable `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:
+
+```lisp
+((python-mode
+  . ((eglot-workspace-configuration
+      . ((:pyls . (:plugins (:jedi_completion (:include_params t)))))))))
+```
+
+This tells Emacs that any `python-mode` buffers in that directory
+should have a particular buffer-local value of
+`eglot-workspace-configuration`.  That variable's value should be
+_association list_ of _parameter sections_ which are presumably
+understood by the server.  In this example, we associate section
+`pyls` with the parameters object `(:plugins (:jedi_completion
+(:include_params t)))`.
+
+Now, supposing that you also had some Go code in the very same
+project, you can configure the Gopls server in the same file.  Adding
+a section for `go-mode`, the file's contents become:
+
+```lisp
+((python-mode
+  . ((eglot-workspace-configuration
+      . ((:pyls . (:plugins (:jedi_completion (:include_params t))))))))
+ (go-mode
+  . ((eglot-workspace-configuration
+      . ((:gopls . (:usePlaceholders t)))))))
+```
+
+If you can't afford an actual `.dir-locals.el` file, or if managing
+these files becomes cumbersome, the Emacs manual teaches you
+programmatic ways to leverage per-directory local variables.
+
+## Handling quirky servers
+
+Some servers need even more special hand-holding to operate correctly.
+If your server has some quirk or non-conformity, it's possible to
+extend Eglot via Elisp to adapt to it.  Here's an example on how to
 get [cquery][cquery] working:
 
 ```lisp
@@ -283,7 +325,7 @@ eglot-shutdown`.
 - [ ] workspace/workspaceFolders (3.6.0)
 - [ ] workspace/didChangeWorkspaceFolders (3.6.0)
 - [x] workspace/didChangeConfiguration
-- [ ] workspace/configuration (3.6.0)
+- [x] workspace/configuration (3.6.0)
 - [x] workspace/didChangeWatchedFiles
 - [x] workspace/symbol
 - [x] workspace/executeCommand
diff --git a/eglot.el b/eglot.el
index 75ce937..b9496e1 100644
--- a/eglot.el
+++ b/eglot.el
@@ -218,6 +218,7 @@ let the buffer grow forever."
   (defvar eglot--lsp-interface-alist
     `(
       (CodeAction (:title) (:kind :diagnostics :edit :command))
+      (ConfigurationItem () (:scopeUri :section))
       (Command (:title :command) (:arguments))
       (CompletionItem (:label)
                       (:kind :detail :documentation :deprecated :preselect
@@ -474,7 +475,8 @@ treated as in `eglot-dbind'."
                         :executeCommand `(:dynamicRegistration :json-false)
                         :workspaceEdit `(:documentChanges :json-false)
                         :didChangeWatchedFiles `(:dynamicRegistration t)
-                        :symbol `(:dynamicRegistration :json-false))
+                        :symbol `(:dynamicRegistration :json-false)
+                        :configuration t)
             :textDocument
             (list
              :synchronization (list
@@ -1655,9 +1657,9 @@ Records BEG, END and PRE-CHANGE-LENGTH locally."
             '((name . eglot--signal-textDocument/didChange)))
 
 (defvar-local eglot-workspace-configuration ()
-  "Alist of (SETTING . VALUE) entries configuring the LSP server.
-Setting should be a keyword, value can be any value that can be
-converted to JSON.")
+  "Alist of (SECTION . VALUE) entries configuring the LSP server.
+SECTION should be a keyword or a string, value can be anything
+that can be converted to JSON.")
 
 (put 'eglot-workspace-configuration 'safe-local-variable 'listp)
 
@@ -1669,12 +1671,34 @@ When called interactively, use the currently active 
server"
    server :workspace/didChangeConfiguration
    (list
     :settings
-    (cl-loop for (k . v) in eglot-workspace-configuration
-             collect (if (keywordp k)
-                         k
-                       (intern (format ":%s" k)))
+    (cl-loop for (section . v) in eglot-workspace-configuration
+             collect (if (keywordp section)
+                         section
+                       (intern (format ":%s" section)))
              collect v))))
 
+(cl-defmethod eglot-handle-request
+  (server (_method (eql workspace/configuration)) &key items)
+  "Handle server request workspace/configuration."
+  (apply #'vector
+         (mapcar
+          (eglot--lambda ((ConfigurationItem) scopeUri section)
+            (let* ((path (eglot--uri-to-path scopeUri)))
+              (when (file-directory-p path)
+                (with-temp-buffer
+                  (let ((default-directory path))
+                    (setq-local major-mode (eglot--major-mode server))
+                    (hack-dir-local-variables-non-file-buffer)
+                    (alist-get section eglot-workspace-configuration
+                               nil nil
+                               (lambda (wsection section)
+                                 (string=
+                                  (if (keywordp wsection)
+                                      (substring (symbol-name wsection) 1)
+                                    wsection)
+                                  section))))))))
+          items)))
+
 (defun eglot--signal-textDocument/didChange ()
   "Send textDocument/didChange to server."
   (when eglot--recent-changes



reply via email to

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