LSP とは?
Language Server Protocol (LSP) は、言語の解析などを行う Language Server と各ツール(クライアント)が通信・連携する際のプロトコルを規定するものです。
従来、コード補完や定義参照などの機能は各ツールが独自に、かつ言語ごとに実装してきましたが、それにはかなりの労力が必要でした。しかし LSP を用いることで、各ツールは Language Server がどの言語を取り扱っているかを意識することなく、補完や定義参照を行うことができます。
なので、Emacs ユーザにとって LSP(と Language Server) は「IDE like なコード補完、定義参照、参照検索等を提供してくれるモノ」として捉えられるんじゃないかなと思います。
参考資料1: What is the Language Server Protocol?
参考資料2: Qiita/language server protocolについて(前編)
LSP client package
Emacs では主に2つの package が LSP をサポートしています。
(各エディタのサポートツールはこちらのページ、またはこちらのページ)
lsp-mode
company-lsp や lsp-ui, imenu, xref 等と連携をして IDE like な機能を提供する package です。かなり多機能で、UI に関しても充実してます。以下、原文。
lsp-mode aims to provide IDE-like experience by providing optional integration with the most popular Emacs packages like company, flycheck and projectile
eglot
lsp-mode
とは異なるもう一方の package。xref-find-definitions
や flymake-mode
, eldoc-mode
, completion-at-point
などと連携して、定義参照や参照検索を実行させます。lsp-mode
よりも非常にシンプルになっています。以下、原文。
Eglot is considerably less code and hassle than lsp-mode.el.
In most cases, there's nothing to configure. It's a minimalist approach focused on user experience and performance
eglot 設定
eglot
に注目して設定方法を紹介します。lsp-mode
については 「Qiita/好みのエディタに快適な開発環境を提供するLSP」 などが参考になると思います。
また、今回は Ruby の LSP を元に説明しますが、他の言語でも Language Server の導入以外では特に違いがないと思います。
-
eglot
の導入
(require 'eglot)
;; eglot を ON にする mode を指定
(add-hook 'ruby-mode-hook 'eglot-ensure)
- Language Server の導入
Ruby の場合は solargraph が主流のようです。
(各言語の Language Server 対応表はこちらのページ)
$ gem install solargraph
以上を設定すると、Ruby (Rails) の Project で Mode Line に eglot
と表示されます。
eglot 使用例
Code Completion
変数が Array Class ならば to_h
が候補としてサジェストされます。
一方、String Class なら to_h
は候補に出ず、代わりに to_i
などが適切にサジェストされます。
Go to Definition
eglot
は xref-find-definitions
を用いて変数の定義箇所にジャンプすることが可能です。
ちなみに smart-jump.el を用いることで、定義参照に xref-find-definitions
を呼び出しつつ dumb-jump.el を fallback として使用することができるので、おすすめです。
(require 'smart-jump)
(smart-jump-setup-default-registers)
;; お好みでどうぞ
(define-key global-map [(super d)] 'smart-jump-go)
Find References
xref-find-references
を用いることで、変数の参照箇所を検索できます。
また、eglot-help-at-point
でシンボル箇所の詳細説明を見ることができます。
普段は counsel-rg を find-references
代わりに使っているのですが、 eglot
有効時には xref-find-references
を実行させるようにしてます。
(global-set-key (kbd "s-f") 'counsel-rg)
;; eglot-mode 時に有効にする
(define-key eglot-mode-map (kbd "s-f") 'xref-find-references)
最後に
Emacs with LSP、夢がありますね。