diff --git a/.travis.yml b/.travis.yml index 085eebda..277db8ad 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 diff --git a/README.md b/README.md index 0ad6d464..1867609a 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] @@ -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))))))) @@ -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) @@ -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..0f2a45ac 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"))