Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert usage of pyls to pylsp. #688

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
20 changes: 10 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down Expand Up @@ -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.
Expand All @@ -122,21 +122,21 @@ 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
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
Expand All @@ -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)))))))
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down
62 changes: 31 additions & 31 deletions eglot-tests.el
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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")
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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" .
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -543,15 +543,15 @@ 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))))
(with-current-buffer
(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")
Expand All @@ -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
Expand All @@ -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")
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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"))))
Expand All @@ -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
Expand Down Expand Up @@ -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")))
Expand All @@ -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))
Expand All @@ -814,15 +814,15 @@ 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
(eglot--find-file-noselect "project/something.py")
(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 ()
Expand Down Expand Up @@ -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))
Expand Down
2 changes: 1 addition & 1 deletion eglot.el
Original file line number Diff line number Diff line change
Expand Up @@ -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"))
Expand Down