Table of Contents
1. はじめに
一昨年2020年にPythonに(何度めかの)入門をして以来、エディタというかIDE相当の開発環境としてemacs + elpyを使ってきましたが、リモートサーバー上のファイル等を扱う tramp モードに elpy が対応していないことを知り、対応しているらしい eglot を試してみることにしました。
2. LSP
Language Server Protocol (LSP) はマイクロソフトが決めて公開しているプロトコルです。PythonやJavaといった言語ごとのLSPサーバーと、それらの機能を利用するemacs(上で動くeglot)のようなクライアントに分かれていて、それぞれ独立して開発が可能です。
プロトコル部分が標準化されているため、eglotのようなLSPクライアントは、既存の多くのLSPサーバーを使うことができます。elpyのように、何か一つの言語に特化した開発環境を一から実装することは時代遅れになってきたのですね。
3. eglot
4. 設定
4.1. lsp server
Python用のlspサーバーとしては python-language-server と python-lsp-server というよく似た名前のものがありますが、前者はすでにメンテナンスされていないようなので、後者を入れます。
pip install 'python-lsp-server[all]'
簡単に入りました。
4.2. eglot
~/.emacs.d/init.el に以下を書きました。もしまだ use-package を使っていないようなら、ぜひとも使ってみてください。パッケージのインストールを自動化してくれ、とても便利です。私の環境ではなぜか自動インストールが失敗し、 M-x list-packages から手動インストールすることがよくありますが。。
(use-package eglot)
(add-to-list 'eglot-server-programs
'(python-mode "pylsp"))
(use-package python-mode
:ensure nil
:hook
(python-mode . eglot-ensure))
これで最低限の設定が完了です。試しにローカルの .py ファイルを開いてみてください。
4.2.1. tramp-modeでの注意点
私の場合、ローカルではうまくいくのですが tramp でリモートの .py ファイルを開こうとすると pylsp が見つからないというエラーに悩まされました。試行錯誤の結果、以下の行をinit.elに入れて解決しました。
(add-to-list 'tramp-remote-path 'tramp-own-remote-path)
4.3. その他のパッケージ
他に、以下のパッケージを追加しました。
company: オートコンプリート。pythonファイル以外にも適用するhighlight-indent-guides: インデントをよりビジュアル的にわかりやすくするパッケージblack: 整形ツール。セーブ時に規定フォーマットを強制するflycheck: 動的に構文チェックしてくれるツール。flycheck-inlineはエラーをインラインで表示させる
(use-package company
:init
(global-company-mode)
(setq company-idle-delay 0.3)
(setq company-minimum-prefix-length 1)
(setq company-transformers '(company-sort-by-occurrence))
:bind
(:map company-active-map
("C-n". company-select-next)
("C-p". company-select-previous)
("M-<". company-select-first)
("M->". company-select-last)))
(use-package highlight-indent-guides
:config
(add-hook 'prog-mode-hook 'highlight-indent-guides-mode))
;; black
(use-package blacken
:config
(add-hook 'python-mode-hook 'blacken-mode))
;; Flycheck
(use-package flycheck
:init
(add-hook 'after-init-hook 'global-flycheck-mode))
(use-package flycheck-inline
:init
(with-eval-after-load 'flycheck
(add-hook 'flycheck-mode-hook #'flycheck-inline-mode)))
5. おまけ
elpyがtrampに 対応していない らしいことは、実際にやってみてわかりました。