- 従来うまく動いていた lsp-mode ベースの LSP 環境を、GNU Emacs 組み込みの LSP ソリューションである Eglot に全面的に置き換えた実際の移行経験のまとめ
- Eglot は lsp-mode と比べて ミニマルで静かなインターフェースを提供し、Corfu・Consult・Flycheck などの外部パッケージと標準 Emacs Lisp API を通じて連携する構成
- 移行作業の大半は Eglot 自体の設定ではなく、補助パッケージの探索・設定・試行錯誤に費やされた
- pylsp、gopls など LSP サーバーごとに workspace 設定の方式が異なり、プロジェクト単位の設定には
.dir-locals.el の活用が必要
- Eglot は GNU Emacs に組み込まれているだけに、長期的には Emacs ユーザーなら移行を検討する価値がある
移行の動機と全体的な印象
- 特別に強い理由があったわけではなく、Corfu への移行後に Eglot を試験的に使い始め、そのまま継続したケース
- lsp-mode + lsp-ui はさまざまな情報が同時に表示される 忙しい(busy)インターフェースであり、より静かな LSP 体験を求めて移行
- Eglot は lsp-mode よりミニマルだが、追加パッケージで機能を補強してこそ完全な体験になる
- 結果として満足しており、Go と Python モードでは **「common prefix による自動補完」**のような機能がよりうまく動作
- lsp-ui の設定をさらに調整することもできたが、Eglot への移行がすべての問題を一度に解決した
補助パッケージとの連携
- Corfu は追加設定なしで、既存設定のまま自動補完に動作
- クロスリファレンスで lsp-ui スタイルのプレビューを得るには consult パッケージを接続し、
xref-show-xrefs-function を consult-xref に設定する必要がある
- Flycheck と Flymake の間で検討した末、Flycheck を選択
- Flymake は Eglot とよりよく統合されるが、全体としては Flycheck を好む
- Eglot は自動的に flymake-mode を有効化するため、
eglot-stay-out-of に flymake を追加して無効化
- flycheck-eglot のグローバルモードが安定して動作しないため、hook を直接設定する方式を使用
キーバインド設定
- Eglot は デフォルトのキーバインドを提供しないため、自分で設定する必要がある
- 現在使用中のバインド例:
C-c r → eglot-rename, C-c o → eglot-code-action-organize-imports
C-c h → eldoc, C-c a → eglot-code-actions, C-c q → eglot-code-action-quickfix
C-M-<mouse-2> → eglot-code-actions-at-mouse (flycheck-eglot の 統合上の限界を回避するためのマウスバインド)
eglot-format は意図的にバインドしていない — Go ではすでに go-mode の gofmt を使用中
eglot-extend-to-xref を t に設定すると、外部項目へジャンプした後でも M-? でプロジェクト内の他の使用箇所を検索できる
LSP サーバーの自動起動
- Eglot の公式ドキュメントは手動起動を推奨しているが、ローカルファイルに限って自動起動するよう設定
eglot-ensure-local-only 関数を定義し、file-remote-p でリモートファイルかどうかを確認したうえで eglot-ensure を呼び出す
eglot-ensure の制限事項: 1つの言語に 複数の LSP サーバー(例: Python の pylsp と ruff) がある場合、デフォルトサーバーだけが自動選択され、変更するには現在のサーバーを終了して eglot を手動で呼び出す必要がある
- 複数の LSP サーバーを同時に実行するには、rassumfrassum のようなマルチプレクサープログラムを利用できる
Code Actions の使いやすさ
- LSP サーバーが提供する code actions は多いが、Eglot では手軽にアクセスしづらい (lsp-mode でも同様)
- LSP サーバーはリクエスト時にのみ code actions を提供し、特定の位置に依存する
- Eglot はサーバーが返す長い code action 一覧に対して フィルタリング機能を提供しないため、Go と Python の両方で一覧が煩雑になる問題がある
pylsp の Workspace 設定
- pylsp(Python LSP サーバー) でスタイル系リンターを常時診断から無効化するには eglot-workspace-configuration を使う必要がある
- lsp-mode は個別の診断ツール(mccabe など)を無効化する便利なコントロールを提供するが、Eglot では JSON 形式の workspace configuration を自分で書く必要がある
- 例として、mccabe、pylint、mypy、pycodestyle などを
:enabled :json-false で無効化
- mypy 関連キーが
pylsp_mypy と mypy の 2つの名前で混在しているが、これは pylsp 内部実装の詳細によるもの
- 必ず
setq-default を使う必要があり、setq では動作しない
プロジェクト別設定と .dir-locals.el
- プロジェクトごとの LSP サーバーパラメータを一時的に設定する 便利な方法は Eglot にはない
- 特定の設定が必要なら、
.dir-locals.el ファイルに正しい形式で記述するのが最も簡単な方法
- gopls(Go) と pylsp(Python) では 設定構造がまったく異なり、LSP サーバーごとに個別に学ぶ必要がある
- 設定をランタイムで変更するには、
dir-locals-set-class-variables で新しいクラスを定義し、その後 dir-locals-set-directory-class と eglot-signal-didChangeConfiguration を呼び出す 専用関数の作成が必要
- Eglot はプロジェクト(ディレクトリツリー)全体に 1 つの LSP サーバーを実行するため、ファイル・バッファ単位の LSP 設定は不可能で、必ずプロジェクト単位で適用する必要がある
eglot-workspace-configuration を通常の手段で設定すると バッファローカル変数になってしまい、実質的に役に立たない
Flymake vs Flycheck の使用感
- Flymake は Eglot とより密接に統合されており、診断ノート上に LSP サーバー由来の修正提案(quickfix code action) をボタン 2 のポップアップメニューとして直接表示する
- Flycheck はエラーマークのみを行い、LSP code actions は別途トリガーする必要があるという制約がある
- 最初は Flymake に移行したが、その後 Flycheck のほうが優れている点もあり、両方の設定を維持
- flycheck-eglot の作者がこの問題に対する 回避策を提示したため、Flycheck に復帰
- Flycheck は Flymake より チェッカーのコレクションが豊富で、チェッカー間の切り替えもしやすい
- Flymake の **「行末に診断を表示」**オプションが惜しい
- flycheck-inline は現在位置の警告のみを表示し、スクロール時に全体の警告を見せない
- Sideline + sideline-flycheck も同じ制限があるが、UI 体験はより良い
2件のコメント
https://web.archive.org/web/20260513001754/…
Lobste.rsの意見
言語によっては、Eglot を自動起動する助言は 致命的に危険になりうる。多くの言語の LSP サーバーは信頼できないコードに対して安全に使えるようにはできておらず、攻撃者が制御する Rust や Elixir のプロジェクトのファイルを開いただけでマシンが侵害される可能性がある
安全だと知られている LSP サーバーがある言語でない限り、LSP の自動有効化は避けるべき。根拠: https://rust-analyzer.github.io/book/security.html
git statusでさえ攻撃対象領域になりうる: https://github.com/justinsteven/advisories/…違いは、上の事例ではリポジトリ自体にエクスプロイトが存在する必要があるのに対し、LSP では依存関係側でも問題が起きうる点。それでも、習慣的に LSP を有効にすることに慣れてしまうと、警告に鈍感になるのを防ぐのは難しそうだ
rust-analyzerプロセスが数分間動作し、1GB を超えるtarget/debug/ディレクトリが作られることがあるcargo buildを実行した時点で、もう同じようなものではある。もちろん LSP の自動ロード と、ユーザーが明示的に実行したコマンドには大きな違いがあるが、実際の利用では思ったより差が小さいかもしれないlsp-modeのように有効化前に確認し、プロジェクトを 許可リスト に追加する方式のほうがよい。すでに「自動実行」するフックがあるなら、read-from-minibufferで先に「このフォルダを信頼しますか?」と尋ねるようにするのは 10 行程度ででき、projectileのようなもので基準ディレクトリを決めればセキュリティ上の利点の大半を得られる自分の設定では
lsp-modeの許可リストを使いつつセッションごとに消去しており、Emacs を再起動するたびにプロジェクトごとに再同意が必要になる。もともとは性能のためにそうしていた気がする。lsp-modeが特定のプロジェクトを開く前から複数のプロセスを立ち上げることがあったからだ。セキュリティ上のリスクは現実的だが、妥当なワークフローを作るのはそれほど難しくないEglot でいちばん気になるのは、大半のコマンドを関数として公開せず、
xrefのような Emacs インターフェース の上に定義していること。Clojure のようにCIDERとclojure-lspの両方のxrefバックエンドがある場合、読み込まれたコードの実際のランタイム状態を知っているCIDER側を優先したくなるclojure-lspの静的解析は、とくにリモート REPL ワークフローでは同期がずれることがある。lsp-modeでは定義ジャンプのような機能をコマンドとして直接呼び出しつつxrefも使い続けられるが、Eglot では特定のxrefバックエンドだけを外すのがかなり面倒だ。lsp-modeにある他のコマンドも Eglot には欠けているが、実際にはxrefに似た Emacs 統合ポイントを通じて提供できる機能だlsp-modeを一度使ってみたが、ややこしいポップアップや通知が多すぎてすぐ消した。Eglot はずっと 静かな LSP 体験 を提供してくれる有効にしておいて、準備ができた時に機能を使えばいい。~cks が逆方向からアプローチしつつ、いろいろなヒントや代案に触れているのが興味深い
lsp-modeでは多くの機能をオフにして、かなり静かなインターフェースとして使っている。Eglot へ移ろうとしたが、欲しい統合機能がなさそうに見えたので、その時はそれ以上試さなかった本当に探したいのは 非常に大きなリポジトリ を扱える LSP サーバーだ。これがしばしば限界として現れ、ソースの索引付けを一度に大半処理してから複数の LSP 的な作業に再利用するものを作るべきかと思うが、また別の大海を沸かそうとしているのではないかと心配になる
Emacs 用 LSP クライアントとしては Eglot と
lsp-modeが最も有名だが、lspce や lsp-bridge のような代替もあるEglot を数年間満足して使ってきたが、今後さらに問題になりうる 設計上の限界 がある。バッファごとにクライアント 1 つを前提としているのだが、Eglot が作られた当時は妥当でも、今では 1 つのバッファで複数の LSP サーバーを動かしたいケースがますます一般的になっている。現在の recommendation は、別プログラムを LSP マルチプレクサのように使うことだ
4 日前に Python 用として
lsp-modeから Eglot に移行し、満足している現在の設定の最小版をここで公開した: https://discuss.afpy.org/t/configuration-emacs-minimale-en-2026/3001
ただし補完まわりには不満がある。たとえば
foo<tab><tab>を押すと、現在のスコープに合うシンボルがあるのにbasedpyrightが妙なものを自動 import してしまうことがあり、最長共通文字列までだけ補完する方法もまだ見つけられていない。それ以外はかなり良いEmacs をモダンな IDE のように使える人たちがうらやましい。Emacs キーバインドは使っているが、6〜8 時間かけても Emacs を IDE のように動かせなかった
昔、Linux と FreeBSD の開発環境で TypeScript の代わりに使っていた FB Flow に合わせようとして諦め、先週末には Windows で tree-sitter を添えたフル機能の Python 環境を作ろうとしてまた諦めた。設定することが多すぎるし、tree-sitter パーサーのような DLL も別途たくさん入手しなければならず、まともな IDE のようにするまでに必要なものが多すぎる。もう時間を投資したくはないが、ときどきどの端末でも
emacs -nwと打てば慣れた編集環境が出てくるのは良いfido-vertical-mode、which-key-mode、global-completion-preview-mode、yasnippet、eglot-ensure、basedpyrightくらいの 最小構成 で十分に始められるbasedpyrightがパスに入っていれば、tree-sitter の文法なしでもちゃんとした補完と構文ハイライトが得られる。全体設定から最小限に削った版で、完全な設定は my full config にあるdoom emacsを試してみるといい。設定がとても簡単で、デフォルト状態でも大半がうまく動く。evil-modeが気に入らなければ Emacs キーバインド に戻すこともできる