From c3492d521c998daf095fccdd764b4c39a33602e5 Mon Sep 17 00:00:00 2001 From: Doug Davis Date: Fri, 7 May 2021 14:44:01 -0400 Subject: [PATCH 1/5] pyls --> pylsp --- .travis.yml | 5 ++-- README.md | 34 +++++++++++++-------------- eglot-tests.el | 62 +++++++++++++++++++++++++------------------------- eglot.el | 4 ++-- 4 files changed, 52 insertions(+), 53 deletions(-) diff --git a/.travis.yml b/.travis.yml index 085eebda..f696ac42 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,10 +18,10 @@ install: # Install RLS - rustup update - rustup component add rls-preview rust-analysis rust-src - # Install https://github.com/palantir/python-language-server + # Install https://github.com/python-lsp/python-lsp-server - virtualenv . - . ./bin/activate - - pip install 'python-language-server[all]==0.31.10' + - pip install 'python-lsp-server[all]==1.0.1' # Install eclipse.jdt.ls - curl -fSL http://download.eclipse.org/jdtls/snapshots/jdt-language-server-latest.tar.gz -o eclipse.tar.gz - mkdir eclipse.jdt.ls @@ -33,4 +33,3 @@ before_script: script: - make check - diff --git a/README.md b/README.md index 0ad6d464..e732136c 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ find-library` can help you tell if that happened. * Javascript's [TS & JS Language Server ][typescript-language-server] * Rust's [rls][rls] -* Python's [pyls][pyls] +* Python's [pylsp][pylsp] * Ruby's [solargraph][solargraph] * Java's [Eclipse JDT Language Server][eclipse-jdt] * Bash's [bash-language-server][bash-language-server] @@ -69,7 +69,7 @@ customize `eglot-server-programs`: (add-to-list 'eglot-server-programs '(foo-mode . ("foo-language-server" "--args"))) ``` -Let me know how well it works and we can add it to the list. +Let me know how well it works and we can add it to the list. To skip the guess and always be prompted use `C-u M-x eglot`. @@ -98,17 +98,17 @@ If you don't want to start it manually every time, you can configure Eglot to start it and immediately connect to it. Ruby's [solargraph][solargraph] server already works this way out-of-the-box. -For another example, suppose you also wanted start Python's `pyls` +For another example, suppose you also wanted start Python's `pylsp` this way: ```lisp (add-to-list 'eglot-server-programs - `(python-mode . ("pyls" "-v" "--tcp" "--host" + `(python-mode . ("pylsp" "-v" "--tcp" "--host" "localhost" "--port" :autoport))) ``` You can see that the element associated with `python-mode` is now a -more complicated invocation of the `pyls` program, which requests that +more complicated invocation of the `pylsp` program, which requests that 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. @@ -122,13 +122,13 @@ 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 +particular Python project always enable Pylsp'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))))))))) + . ((:pylsp . (:plugins (:jedi_completion (:include_params t))))))))) ``` This tells Emacs that any `python-mode` buffers in that directory @@ -136,7 +136,7 @@ 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 +`pylsp` with the parameters object `(:plugins (:jedi_completion (:include_params t)))`. Now, supposing that you also had some Go code in the very same @@ -146,7 +146,7 @@ a section for `go-mode`, the file's contents become: ```lisp ((python-mode . ((eglot-workspace-configuration - . ((:pyls . (:plugins (:jedi_completion (:include_params t)))))))) + . ((:pylsp . (:plugins (:jedi_completion (:include_params t)))))))) (go-mode . ((eglot-workspace-configuration . ((:gopls . (:usePlaceholders t))))))) @@ -208,17 +208,17 @@ precise and objective about the problem as you can: buffer with `M-x eglot-events-buffer`. It contains the JSONRPC messages exchanged between client and server, as well as the messages the server prints to stderr. - + 2. If Emacs errored (you saw -- and possibly heard -- an error message), make sure you repeat the process using `M-x toggle-debug-on-error` so you **get a backtrace** of the error that you should also attach to the bug report. - + 3. Try to replicate the problem with **as clean an Emacs run as possible**. This means an empty `.emacs` init file or close to it (just loading `eglot.el`, `company.el` and `yasnippet.el` for example, and you don't even need `use-package.el` to do that). - + Some more notes: it is often the case the you will have to report the problem to the LSP server's developers, too, though it's understandable that you report it Eglot first, since it is the @@ -296,7 +296,7 @@ documentation on what these do. - `eglot-ignored-server-capabilites`: LSP server capabilities that Eglot could use, but won't; -- `eglot-confirm-server-initiated-edits`: If non-nil, ask for confirmation +- `eglot-confirm-server-initiated-edits`: If non-nil, ask for confirmation before allowing server to edit the source buffer's text; There are a couple more variables that you can customize via Emacs @@ -399,7 +399,7 @@ eglot-shutdown`. - [x] textDocument/completion - [x] completionItem/resolve (works quite well with [company-mode][company-mode]) - [x] textDocument/hover -- [x] textDocument/signatureHelp (fancy stuff with Python's [pyls][pyls]) +- [x] textDocument/signatureHelp (fancy stuff with Python's [pylsp][pylsp]) - [x] textDocument/definition - [x] textDocument/typeDefinition (3.6.0) - [x] textDocument/implementation (3.6.0) @@ -414,7 +414,7 @@ eglot-shutdown`. - [ ] documentLink/resolve - [ ] textDocument/documentColor - [ ] textDocument/colorPresentation (3.6.0) -- [x] textDocument/formatting +- [x] textDocument/formatting - [x] textDocument/rangeFormatting - [ ] textDocument/onTypeFormatting - [x] textDocument/rename @@ -516,7 +516,7 @@ User-visible differences: - Server-initiated edits are confirmed with the user; - Diagnostics work out-of-the-box (no `flycheck.el` needed); - Smoother/more responsive (read below). - + Under the hood: - Message parser is much simpler. @@ -533,7 +533,7 @@ Under the hood: [lsp]: https://microsoft.github.io/language-server-protocol/ [rls]: https://github.com/rust-lang-nursery/rls -[pyls]: https://github.com/palantir/python-language-server +[pylsp]: https://github.com/python-lsp/python-lsp-server [gnuelpa]: https://elpa.gnu.org/packages/eglot.html [melpa]: http://melpa.org/#/eglot [typescript-language-server]: https://github.com/theia-ide/typescript-language-server diff --git a/eglot-tests.el b/eglot-tests.el index 1309f874..6c51ce25 100644 --- a/eglot-tests.el +++ b/eglot-tests.el @@ -324,12 +324,12 @@ Pass TIMEOUT to `eglot--with-timeout'." (ert-deftest auto-detect-running-server () "Visit a file and M-x eglot, then visit a neighbour. " - (skip-unless (executable-find "pyls")) + (skip-unless (executable-find "pylsp")) (eglot-tests--auto-detect-running-server-1)) (ert-deftest auto-shutdown () "Visit a file and M-x eglot, then kill buffer. " - (skip-unless (executable-find "pyls")) + (skip-unless (executable-find "pylsp")) (let (server buffer) (eglot--with-fixture @@ -348,7 +348,7 @@ Pass TIMEOUT to `eglot--with-timeout'." (ert-deftest auto-reconnect () "Start a server. Kill it. Watch it reconnect." - (skip-unless (executable-find "pyls")) + (skip-unless (executable-find "pylsp")) (let (server (eglot-autoreconnect 1)) (eglot--with-fixture `(("project" . (("coiso.py" . "bla") @@ -407,7 +407,7 @@ Pass TIMEOUT to `eglot--with-timeout'." (ert-deftest basic-diagnostics () "Test basic diagnostics." - (skip-unless (executable-find "pyls")) + (skip-unless (executable-find "pylsp")) (eglot--with-fixture `(("diag-project" . ; colon missing after True @@ -481,7 +481,7 @@ Pass TIMEOUT to `eglot--with-timeout'." (ert-deftest rename-a-symbol () "Test basic symbol renaming" - (skip-unless (executable-find "pyls")) + (skip-unless (executable-find "pylsp")) (eglot--with-fixture `(("rename-project" . (("main.py" . @@ -496,7 +496,7 @@ Pass TIMEOUT to `eglot--with-timeout'." (ert-deftest basic-completions () "Test basic autocompletion in a python LSP" - (skip-unless (executable-find "pyls")) + (skip-unless (executable-find "pylsp")) (eglot--with-fixture `(("project" . (("something.py" . "import sys\nsys.exi")))) (with-current-buffer @@ -508,7 +508,7 @@ Pass TIMEOUT to `eglot--with-timeout'." (ert-deftest non-unique-completions () "Test completion resulting in 'Complete, but not unique'" - (skip-unless (executable-find "pyls")) + (skip-unless (executable-find "pylsp")) (eglot--with-fixture '(("project" . (("something.py" . "foo=1\nfoobar=2\nfoo")))) (with-current-buffer @@ -525,7 +525,7 @@ Pass TIMEOUT to `eglot--with-timeout'." (ert-deftest basic-xref () "Test basic xref functionality in a python LSP" - (skip-unless (executable-find "pyls")) + (skip-unless (executable-find "pylsp")) (eglot--with-fixture `(("project" . (("something.py" . "def foo(): pass\ndef bar(): foo()")))) (with-current-buffer @@ -543,7 +543,7 @@ def foobazquuz(d, e, f): pass (ert-deftest snippet-completions () "Test simple snippet completion in a python LSP" - (skip-unless (and (executable-find "pyls") + (skip-unless (and (executable-find "pylsp") (functionp 'yas-minor-mode))) (eglot--with-fixture `(("project" . (("something.py" . ,eglot--test-python-buffer)))) @@ -551,7 +551,7 @@ def foobazquuz(d, e, f): pass (eglot--find-file-noselect "project/something.py") (yas-minor-mode 1) (let ((eglot-workspace-configuration - `((:pyls . (:plugins (:jedi_completion (:include_params t))))))) + `((:pylsp . (:plugins (:jedi_completion (:include_params t))))))) (should (eglot--tests-connect))) (goto-char (point-max)) (insert "foobar") @@ -563,7 +563,7 @@ def foobazquuz(d, e, f): pass (ert-deftest snippet-completions-with-company () "Test simple snippet completion in a python LSP" - (skip-unless (and (executable-find "pyls") + (skip-unless (and (executable-find "pylsp") (functionp 'yas-minor-mode) (functionp 'company-complete))) (eglot--with-fixture @@ -572,7 +572,7 @@ def foobazquuz(d, e, f): pass (eglot--find-file-noselect "project/something.py") (yas-minor-mode 1) (let ((eglot-workspace-configuration - `((:pyls . (:plugins (:jedi_completion (:include_params t))))))) + `((:pylsp . (:plugins (:jedi_completion (:include_params t))))))) (should (eglot--tests-connect))) (goto-char (point-max)) (insert "foo") @@ -581,12 +581,12 @@ def foobazquuz(d, e, f): pass (should (looking-back "fooba")) (should (= 2 (length company-candidates))) ;; this last one is brittle, since there it is possible that - ;; pyls will change the representation of this candidate + ;; pylsp will change the representation of this candidate (should (member "foobazquuz(d, e, f)" company-candidates))))) (ert-deftest eglot-eldoc-after-completions () "Test documentation echo in a python LSP" - (skip-unless (executable-find "pyls")) + (skip-unless (executable-find "pylsp")) (eglot--with-fixture `(("project" . (("something.py" . "import sys\nsys.exi")))) (with-current-buffer @@ -600,7 +600,7 @@ def foobazquuz(d, e, f): pass (ert-deftest eglot-multiline-eldoc () "Test if suitable amount of lines of hover info are shown." :expected-result (if (getenv "TRAVIS_TESTING") :failed :passed) - (skip-unless (executable-find "pyls")) + (skip-unless (executable-find "pylsp")) (eglot--with-fixture `(("project" . (("hover-first.py" . "from datetime import datetime")))) (with-current-buffer @@ -615,7 +615,7 @@ def foobazquuz(d, e, f): pass (ert-deftest eglot-single-line-eldoc () "Test if suitable amount of lines of hover info are shown." - (skip-unless (executable-find "pyls")) + (skip-unless (executable-find "pylsp")) (eglot--with-fixture `(("project" . (("hover-first.py" . "from datetime import datetime")))) (with-current-buffer @@ -629,11 +629,11 @@ def foobazquuz(d, e, f): pass (should (not (cl-find ?\n eldoc-last-message))))))) (ert-deftest python-autopep-formatting () - "Test formatting in the pyls python LSP. -pyls prefers autopep over yafp, despite its README stating the contrary." + "Test formatting in the pylsp python LSP. +pylsp prefers autopep over yafp, despite its README stating the contrary." ;; Beware, default autopep rules can change over time, which may ;; affect this test. - (skip-unless (and (executable-find "pyls") + (skip-unless (and (executable-find "pylsp") (executable-find "autopep8"))) (eglot--with-fixture `(("project" . (("something.py" . "def a():pass\n\ndef b():pass")))) @@ -652,8 +652,8 @@ pyls prefers autopep over yafp, despite its README stating the contrary." (string= (buffer-string) "def a(): pass\n\n\ndef b(): pass\n"))))) (ert-deftest python-yapf-formatting () - "Test formatting in the pyls python LSP" - (skip-unless (and (executable-find "pyls") + "Test formatting in the pylsp python LSP" + (skip-unless (and (executable-find "pylsp") (not (executable-find "autopep8")) (executable-find "yapf"))) (eglot--with-fixture @@ -752,7 +752,7 @@ pyls prefers autopep over yafp, despite its README stating the contrary." (ert-deftest eglot-ensure () "Test basic `eglot-ensure' functionality" - (skip-unless (executable-find "pyls")) + (skip-unless (executable-find "pylsp")) (eglot--with-fixture `(("project" . (("foo.py" . "import sys\nsys.exi") ("bar.py" . "import sys\nsys.exi"))) @@ -774,38 +774,38 @@ pyls prefers autopep over yafp, despite its README stating the contrary." (ert-deftest slow-sync-connection-wait () "Connect with `eglot-sync-connect' set to t." - (skip-unless (executable-find "pyls")) + (skip-unless (executable-find "pylsp")) (eglot--with-fixture `(("project" . (("something.py" . "import sys\nsys.exi")))) (with-current-buffer (eglot--find-file-noselect "project/something.py") (let ((eglot-sync-connect t) (eglot-server-programs - `((python-mode . ("sh" "-c" "sleep 1 && pyls"))))) + `((python-mode . ("sh" "-c" "sleep 1 && pylsp"))))) (should (eglot--tests-connect 3)))))) (ert-deftest slow-sync-connection-intime () "Connect synchronously with `eglot-sync-connect' set to 2." - (skip-unless (executable-find "pyls")) + (skip-unless (executable-find "pylsp")) (eglot--with-fixture `(("project" . (("something.py" . "import sys\nsys.exi")))) (with-current-buffer (eglot--find-file-noselect "project/something.py") (let ((eglot-sync-connect 2) (eglot-server-programs - `((python-mode . ("sh" "-c" "sleep 1 && pyls"))))) + `((python-mode . ("sh" "-c" "sleep 1 && pylsp"))))) (should (eglot--tests-connect 3)))))) (ert-deftest slow-async-connection () "Connect asynchronously with `eglot-sync-connect' set to 2." - (skip-unless (executable-find "pyls")) + (skip-unless (executable-find "pylsp")) (eglot--with-fixture `(("project" . (("something.py" . "import sys\nsys.exi")))) (with-current-buffer (eglot--find-file-noselect "project/something.py") (let ((eglot-sync-connect 1) (eglot-server-programs - `((python-mode . ("sh" "-c" "sleep 2 && pyls"))))) + `((python-mode . ("sh" "-c" "sleep 2 && pylsp"))))) (should-not (apply #'eglot--connect (eglot--guess-contact))) (eglot--with-timeout 3 (while (not (eglot-current-server)) @@ -814,7 +814,7 @@ pyls prefers autopep over yafp, despite its README stating the contrary." (ert-deftest slow-sync-timeout () "Failed attempt at connection synchronously." - (skip-unless (executable-find "pyls")) + (skip-unless (executable-find "pylsp")) (eglot--with-fixture `(("project" . (("something.py" . "import sys\nsys.exi")))) (with-current-buffer @@ -822,7 +822,7 @@ pyls prefers autopep over yafp, despite its README stating the contrary." (let ((eglot-sync-connect t) (eglot-connect-timeout 1) (eglot-server-programs - `((python-mode . ("sh" "-c" "sleep 2 && pyls"))))) + `((python-mode . ("sh" "-c" "sleep 2 && pylsp"))))) (should-error (apply #'eglot--connect (eglot--guess-contact))))))) (ert-deftest eglot-capabilities () @@ -1123,7 +1123,7 @@ are bound to the useful return values of (ert-deftest eglot--tramp-test () "Ensure LSP servers can be used over TRAMP." - (skip-unless (and (>= emacs-major-version 27) (executable-find "pyls"))) + (skip-unless (and (>= emacs-major-version 27) (executable-find "pylsp"))) ;; Set up a loopback TRAMP method that’s just a shell so the remote ;; host is really just the local host. (let ((tramp-remote-path (cons 'tramp-own-remote-path tramp-remote-path)) diff --git a/eglot.el b/eglot.el index fc82367f..c1304c65 100644 --- a/eglot.el +++ b/eglot.el @@ -96,7 +96,7 @@ :group 'applications) (defvar eglot-server-programs '((rust-mode . (eglot-rls "rls")) - (python-mode . ("pyls")) + (python-mode . ("pylsp")) ((js-mode typescript-mode) . ("typescript-language-server" "--stdio")) (sh-mode . ("bash-language-server" "start")) @@ -1277,7 +1277,7 @@ If optional MARKER, return a marker instead" (concat "file://" (if (eq system-type 'windows-nt) "/") (url-hexify-string ;; Again watch out for trampy paths. - (directory-file-name (file-local-name (file-truename path))) + (directory-file-name (file-local-name (file-truename path))) eglot--uri-path-allowed-chars))) (defun eglot--uri-to-path (uri) From c272a233a82a1ab4bc8d9be94e501d6655934a40 Mon Sep 17 00:00:00 2001 From: Doug Davis Date: Sat, 8 May 2021 10:41:16 -0400 Subject: [PATCH 2/5] whitespace --- README.md | 14 +++++++------- eglot.el | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index e732136c..10f83860 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ customize `eglot-server-programs`: (add-to-list 'eglot-server-programs '(foo-mode . ("foo-language-server" "--args"))) ``` -Let me know how well it works and we can add it to the list. +Let me know how well it works and we can add it to the list. To skip the guess and always be prompted use `C-u M-x eglot`. @@ -208,17 +208,17 @@ precise and objective about the problem as you can: buffer with `M-x eglot-events-buffer`. It contains the JSONRPC messages exchanged between client and server, as well as the messages the server prints to stderr. - + 2. If Emacs errored (you saw -- and possibly heard -- an error message), make sure you repeat the process using `M-x toggle-debug-on-error` so you **get a backtrace** of the error that you should also attach to the bug report. - + 3. Try to replicate the problem with **as clean an Emacs run as possible**. This means an empty `.emacs` init file or close to it (just loading `eglot.el`, `company.el` and `yasnippet.el` for example, and you don't even need `use-package.el` to do that). - + Some more notes: it is often the case the you will have to report the problem to the LSP server's developers, too, though it's understandable that you report it Eglot first, since it is the @@ -296,7 +296,7 @@ documentation on what these do. - `eglot-ignored-server-capabilites`: LSP server capabilities that Eglot could use, but won't; -- `eglot-confirm-server-initiated-edits`: If non-nil, ask for confirmation +- `eglot-confirm-server-initiated-edits`: If non-nil, ask for confirmation before allowing server to edit the source buffer's text; There are a couple more variables that you can customize via Emacs @@ -414,7 +414,7 @@ eglot-shutdown`. - [ ] documentLink/resolve - [ ] textDocument/documentColor - [ ] textDocument/colorPresentation (3.6.0) -- [x] textDocument/formatting +- [x] textDocument/formatting - [x] textDocument/rangeFormatting - [ ] textDocument/onTypeFormatting - [x] textDocument/rename @@ -516,7 +516,7 @@ User-visible differences: - Server-initiated edits are confirmed with the user; - Diagnostics work out-of-the-box (no `flycheck.el` needed); - Smoother/more responsive (read below). - + Under the hood: - Message parser is much simpler. diff --git a/eglot.el b/eglot.el index c1304c65..0f2a45ac 100644 --- a/eglot.el +++ b/eglot.el @@ -1277,7 +1277,7 @@ If optional MARKER, return a marker instead" (concat "file://" (if (eq system-type 'windows-nt) "/") (url-hexify-string ;; Again watch out for trampy paths. - (directory-file-name (file-local-name (file-truename path))) + (directory-file-name (file-local-name (file-truename path))) eglot--uri-path-allowed-chars))) (defun eglot--uri-to-path (uri) From c5870a662ca66ad1cbbc1e496275af2cb715391b Mon Sep 17 00:00:00 2001 From: Doug Davis Date: Sat, 8 May 2021 10:43:14 -0400 Subject: [PATCH 3/5] whitespace --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 10f83860..38df4a1d 100644 --- a/README.md +++ b/README.md @@ -208,7 +208,7 @@ precise and objective about the problem as you can: buffer with `M-x eglot-events-buffer`. It contains the JSONRPC messages exchanged between client and server, as well as the messages the server prints to stderr. - + 2. If Emacs errored (you saw -- and possibly heard -- an error message), make sure you repeat the process using `M-x toggle-debug-on-error` so you **get a backtrace** of the error that @@ -218,7 +218,7 @@ precise and objective about the problem as you can: possible**. This means an empty `.emacs` init file or close to it (just loading `eglot.el`, `company.el` and `yasnippet.el` for example, and you don't even need `use-package.el` to do that). - + Some more notes: it is often the case the you will have to report the problem to the LSP server's developers, too, though it's understandable that you report it Eglot first, since it is the From ec2e3dba7a3d8afc81cc6524f63696a9f05a7bb5 Mon Sep 17 00:00:00 2001 From: Doug Davis Date: Sat, 8 May 2021 10:44:25 -0400 Subject: [PATCH 4/5] whitespace --- .travis.yml | 1 + README.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index f696ac42..9fab4ec8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,3 +33,4 @@ before_script: script: - make check +- diff --git a/README.md b/README.md index 38df4a1d..1867609a 100644 --- a/README.md +++ b/README.md @@ -516,7 +516,7 @@ User-visible differences: - Server-initiated edits are confirmed with the user; - Diagnostics work out-of-the-box (no `flycheck.el` needed); - Smoother/more responsive (read below). - + Under the hood: - Message parser is much simpler. From cd704d761ca4e7cf1abc39a3f1d8af1601638630 Mon Sep 17 00:00:00 2001 From: Doug Davis Date: Sat, 8 May 2021 10:45:20 -0400 Subject: [PATCH 5/5] whitespace --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 9fab4ec8..277db8ad 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,4 +33,4 @@ before_script: script: - make check -- +