blog-public/content/post/python-lsp.md
Denis Zheleztsov a5dd73f274 Initial public
Some content was deleted before this project
has been moved to public
2021-10-18 19:45:57 +03:00

5.5 KiB
Raw Permalink Blame History

+++ date = "2018-07-30T15:25:28+03:00" draft = false title = "Автодополнение для python с LSP в GNU Emacs" tags = ["emacs", "python"] comments = true

+++

The Language Server Protocol (LSP) -- это открытый, основанный на JSON-RPC протокол для использования между редакторами исходного кода и серверами, которые предоставляют специфические для языка программирования функции. Цель протокола заключается в том, чтобы обеспечить поддержку автодополнения языка программирования независимо от любого редактора или среды IDE.

LSP дает реально крутые штуки, такие как:

  • Показ документации для модуля под курсором documentation

  • Автодополнение по точке. На самом деле это company-lsp, но про это будет дальше. completion

  • Интеграция с flycheck flycheck

И еще кучу всего на самом деле. Все возможные настройки можно будет увидеть по M-x customize RET lsp RET.

Конфигурация

Для начала нужно установить сам language server для python. Для Arch/Manjaro установка будет выглядеть так:

sudo pacman -S python-language-server

С системными зависимостями разобрались. Приступаем к init.el. Будем использовать use-package, потому что не использовать его -- это отстой. Но каждый решает сам.

Включаем lsp-mode. Да, для lsp нужно что-то, чем определить корневой каталог для проекта. Я использую везде projectile.

;; LSP settings
(use-package lsp-mode
    :ensure t
    :config
    ;; make sure we have lsp-imenu everywhere we have LSP
    (require 'lsp-imenu)
    (add-hook 'lsp-after-open-hook 'lsp-enable-imenu)
    ;; get lsp-python-enable defined
    ;; NB: use either projectile-project-root or ffip-get-project-root-directory
    ;;     or any other function that can be used to find the root directory of a project
    (lsp-define-stdio-client lsp-python "python"
                             #'projectile-project-root
                             '("pyls"))

    ;; make sure this is activated when python-mode is activated
    ;; lsp-python-enable is created by macro above
    (add-hook 'python-mode-hook 'lsp-python-enable)

    ;; lsp extras
    (use-package lsp-ui
        :ensure t
        :config
        (setq lsp-ui-sideline-ignore-duplicate t)
        (add-hook 'lsp-mode-hook 'lsp-ui-mode))

    (use-package company-lsp
        :config
        (push 'company-lsp company-backends))

    ;; NB: only required if you prefer flake8 instead of the default
    ;; send pyls config via lsp-after-initialize-hook -- harmless for
    ;; other servers due to pyls key, but would prefer only sending this
    ;; when pyls gets initialised (:initialize function in
    ;; lsp-define-stdio-client is invoked too early (before server
    ;; start)) -- cpbotha
    (defun lsp-set-cfg ()
        (let ((lsp-cfg `(:pyls (:configurationSources ("flake8")))))
            ;; TODO: check lsp--cur-workspace here to decide per server / project
            (lsp--set-configuration lsp-cfg)))
    (add-hook 'lsp-after-initialize-hook 'lsp-set-cfg))

flake8, autopep8, fci, anaconda, rainbow-delimiters(я их везде юзаю):

;; Python mode hook
(defun my-python-mode-hook ()
    "Define hook."

    (use-package flymake-python-pyflakes
        :config
        (setq flymake-python-pyflakes-executable "flake8")
        (setq flymake-python-pyflakes-extra-arguments '("--max-line-length=99"))
        (flymake-python-pyflakes-load))

    (use-package py-autopep8
        :config
        (setq py-autopep8-options '("--max-line-length=99"))
        (py-autopep8-enable-on-save))

    ;; Enable rainbow
    (use-package rainbow-delimiters)
    (rainbow-delimiters-mode-enable)
    
    (use-package highlight-indent-guides)
    (use-package company)
    (use-package anaconda-mode)
    (use-package company-anaconda
        :config
        (add-to-list 'company-backends '(company-anaconda :with company-capf)))

    (use-package flycheck-pyflakes
        :config
        (setq flychek-flake8-maximum-line-lenght 99))

    (setq-default py-shell-name "ipython")
    (setq-default py-which-bufname "IPython")
    ;; Fill column indicator
    (use-package fill-column-indicator
        :init
        :config
        (setq-default fill-column 99)
        (setq fci-rule-width 1)
        (setq fci-rule-color "#696969"))

    (fci-mode)

    (anaconda-mode +1)
    (anaconda-eldoc-mode)
    (highlight-symbol-mode +1)
    (highlight-indent-guides-mode)
    (company-mode))

(use-package python
    :mode ("\\.py\\'" . python-mode)
    :interpreter ("python" . python-mode)
    :init
    (add-hook 'python-mode-hook 'my-python-mode-hook))

Все!

Спасибо вот этому чуваку.