Added support for Microsoft Python Language Server

<<26/04/2019>>
Incorporated feedback from robbyoconnor and yyoncho.
Rebased.

<<08/04/2019>>
Rebased on develop tip

<<17/04/2019>>
Rebased

<<02/06/2019>>
Rebased. Incorporated feedback from duianto.
This commit is contained in:
cormacc 2019-01-28 10:47:03 +00:00 committed by duianto
parent 06730f24cc
commit 00b2db982d
5 changed files with 94 additions and 13 deletions

View File

@ -2045,7 +2045,11 @@ Other:
- Use =python-mode= for SCons script files (thanks to shanemikel)
- Added LSP support, which can be used by enabling the =lsp= layer and setting
the =python= layer's =python-backend= variable to =lsp=
(thanks to Yuan Fu and Sylvain Benner)
(thanks to Yuan Fu and Sylvain Benner).
- The LSP backend can use either the =pyls= (default) server or the =mspyls=
(Microsoft) implementation, which may be selected by setting the
=python-lsp-server= layer variable to =mspyls=
(thanks to Cormac Cannon).
- Added ~SPC m t l~ key binding to re-run the last test command
(thanks to Benoit Coste).
- Added support for breakpoints for the =trepan3k= python debugger

View File

@ -13,6 +13,8 @@
- [[#backends][Backends]]
- [[#anaconda][Anaconda]]
- [[#language-server-protocol][Language Server Protocol]]
- [[#python-language-server][python-language-server]]
- [[#microsoft-python-language-server][Microsoft python language server]]
- [[#additional-tools][Additional tools]]
- [[#syntax-checking][Syntax checking]]
- [[#test-runner][Test runner]]
@ -46,7 +48,9 @@ This layer adds support for the Python language.
** Features:
- Support for the following backends:
- [[https://github.com/proofit404/anaconda-mode][anaconda]] (default),
- [[https://github.com/emacs-lsp/lsp-python][Language Server Protocol]] (experimental),
- [[https://github.com/emacs-lsp/lsp-python][Language Server Protocol]] (experimental - 2 implementations),
- python-language-server
- Microsoft python language server
- Auto-completion
- Code Navigation
- Documentation Lookup using [[https://github.com/proofit404/anaconda-mode][anaconda-mode]] and [[https://github.com/tsgates/pylookup][pylookup]]
@ -87,6 +91,14 @@ Backend can be chosen on a per project basis using directory local variables
*Note:* you can easily add a directory local variable with ~SPC f v d~.
The available options are:
| symbol | description |
|-----------+----------------------------------|
| 'anaconda | Default |
| 'lsp | python-language-server package |
| 'lsp-ms | Microsoft python language server |
* Backends
** Anaconda
=anaconda-mode= tries to install the dependencies itself but sometimes
@ -113,6 +125,22 @@ setting your =PYTHONPATH= as explained at
[[https://github.com/proofit404/anaconda-mode#pythonpath]]
** Language Server Protocol
The =lsp= backend can use either of the following language server implementations:
| symbol | description |
|---------+------------------------------------------|
| 'pyls | python-language-server package (default) |
| 'mspyls | Microsoft python language server |
=pyls= is used by default - to use the Microsoft server, set the =python-lsp-server=
layer variable as follows:
#+BEGIN_SRC elisp
(python :variables python-backend 'lsp python-lsp-server 'mspyls)
#+END_SRC
*** python-language-server
You just have to install python language server package:
#+BEGIN_SRC sh
@ -133,6 +161,32 @@ dependencies in a pipenv environment, you'll want to set the ~python-pipenv-acti
config variable to ~t~. This activates your pipenv before enabling the
lsp backend.
*** Microsoft python language server
Paraphrasing the instructions provided by the author of the =lsp-python-ms= package:
#+BEGIN_SRC sh
git clone https://github.com/Microsoft/python-language-server.git
cd python-language-server/src/LanguageServer/Impl
dotnet build -c Release
dotnet publish -c Release -r <RUNTIME>
#+END_SRC
where ~<RUNTIME>~ is one of the [[https://docs.microsoft.com/en-us/dotnet/core/rid-catalog][runtime IDs supported by dotnet core]]. One of ~linux-x64~, ~osx-x64~, ~win10-x64~ should
cover most use cases.
The default package configuration assumes the executable is located in a folder included in your system path.
To use the latest built version in a cloned git repo, use the ~python-lsp-git-root~ config variable, e.g.:
#+BEGIN_SRC elisp
(setq-default dotspacemacs-configuration-layers
'((python :variables
python-backend 'lsp-ms
python-lsp-git-root "~/dev/python/python-language-server")))
#+END_SRC
N.B. If you're using Arch linux or a derivative distribution, you can install the =microsoft-python-language-server=
package from the AUR.
* Additional tools
** Syntax checking
Syntax checking uses =flake8= package:

View File

@ -18,6 +18,13 @@
"The backend to use for IDE features. Possible values are `anaconda'
and `lsp'.")
(defvar python-lsp-server 'pyls
"Language server to use for lsp backend. Possible values are `pyls'
and `mspyls'")
(defvar python-lsp-git-root nil
"If non-nil, use a development version of the language server in this folder")
(defvar python-pipenv-activate nil
"If non-nil, activate pipenv before enabling backend")

View File

@ -18,16 +18,15 @@
(defun spacemacs//python-setup-company ()
"Conditionally setup company based on backend."
(pcase python-backend
(`anaconda (spacemacs//python-setup-anaconda-company))
(`lsp (spacemacs//python-setup-lsp-company))))
(if (eq python-backend `anaconda)
(spacemacs//python-setup-anaconda-company)
(spacemacs//python-setup-lsp-company)))
(defun spacemacs//python-setup-eldoc ()
"Conditionally setup eldoc based on backend."
(pcase python-backend
;; lsp setup eldoc on its own
(`anaconda (spacemacs//python-setup-anaconda-eldoc))))
(spacemacs//python-setup-anaconda-eldoc)))
;; anaconda
@ -89,8 +88,8 @@
(defun spacemacs//python-default ()
"Defaut settings for python buffers"
(setq mode-name "Python"
tab-width python-tab-width
fill-column python-fill-column)
tab-width python-tab-width
fill-column python-fill-column)
;; since we changed the tab-width we need to manually call python-indent-guess-indent-offset here
(when python-spacemacs-indent-guess
@ -187,10 +186,10 @@ as the pyenv version then also return nil. This works around https://github.com/
"autoflake --remove-all-unused-imports -i unused_imports.py"
(interactive)
(if (executable-find "autoflake")
(progn
(shell-command (format "autoflake --remove-all-unused-imports -i %s"
(shell-quote-argument (buffer-file-name))))
(revert-buffer t t t))
(progn
(shell-command (format "autoflake --remove-all-unused-imports -i %s"
(shell-quote-argument (buffer-file-name))))
(revert-buffer t t t))
(message "Error: Cannot find autoflake executable.")))
(defun spacemacs//pyenv-mode-set-local-version ()

View File

@ -43,6 +43,8 @@
;; packages for anaconda backend
anaconda-mode
(company-anaconda :requires company)
;; packages for Microsoft LSP backend
(lsp-python-ms :requires lsp-mode)
))
(defun python/init-anaconda-mode ()
@ -420,3 +422,18 @@ fix this issue."
(eq 'yapf python-formatter))
(add-hook 'python-mode-hook 'yapf-mode)))
:config (spacemacs|hide-lighter yapf-mode)))
(defun python/init-lsp-python-ms ()
(use-package lsp-python-ms
:if (eq python-lsp-server 'mspyls)
:ensure nil
:config
(if python-lsp-git-root
;; Use dev version of language server checked out from github
(progn
(setq lsp-python-ms-dir
(expand-file-name (concat python-lsp-git-root "/output/bin/Release/")))
(message "lsp-python-ms: Using version at `%s'" lsp-python-ms-dir))
;; Use a precompiled exe
(setq lsp-python-ms-executable "Microsoft.Python.LanguageServer"))))