GNU Emacs で VS Code 相当のコード・デバッグ支援機能を設定する (1) – Eglot

概要

GNU Emacs >=29.1 で VS Code 相当のコード・デバッグ支援機能を設定します。 VS Code はコード支援機能に Language Server Protocol (LSP) 、デバッグ支援機能に Debug Adapter Protocol (DAP) を使用しています。 Emacs でも LSP/DAP クライアントが開発されています。

ここでは次のパッケージを使います。筆者が初心者かつものぐさなのでなるべくインストールや設定が手軽そうなものを選びます。

今回は Eglot について書きます。

具体例の環境

他の環境の方は適宜読み替えてください。

Eglot

LSP サーバーとの連携により下記のようなコード支援機能が利用できるとのこと。

  • コード補完
  • 関数・クラスの定義箇所への移動
  • 識別子の説明表示
  • リファクタリング (ソース コード整理)
  • 即時診断 (文法上の誤りなど)

インストール

Emacs 29 に内蔵 (built-in) されていますが不具合修正を目当てに ELPA 版を使います。

M-x package-install RET eglot RET

LSP サーバー

Eglot で設定ずみの LSP サーバーの情報が Connecting to a server にあります。

C/C++ 用 LSP サーバー

Eglot 1.17 に設定ずみの C/C++ 用 LSP サーバーは次のとおりです。

  1. clangd
  2. ccls

ここでは clangd を選びます。 macOS の the command line developer tools に付属していますが Homebrew の llvm パッケージに含まれているものを使うこともできます。 ccls は Homebrew にあります。

Python 用 LSP サーバー

Eglot 1.17 に設定ずみの Python 用 LSP サーバーは次のとおりです。

  1. python-lsp-server (pylsp)
    • python-language-server からのフォーク
  2. python-language-server (pyls)
    • 現在メンテナンスされていない
  3. pyright
  4. jedi-language-server
  5. ruff-lsp

そのほか次のものがあります。

python-lsp-server, pyright, ruff-lsp, basedpyright は Homebrew にあります。ここでは python-lsp-server (pylsp) と basedpyright を選びます。

% brew install python-lsp-server basedpyright

python-lsp-server はプラグインのことを考慮すると pipx でインストールしたほうがよいかもしれません (詳細は未確認) 。

% pipx install python-lsp-server
% source ~/.local/pipx/venvs/python-lsp-server/bin/activate
(python-lsp-server) % python -m pip install <plug-in>
(python-lsp-server) % deactivate

Eglot を補強するパッケージ

  • コード補完
  • コード断片
  • ドキュメント表示

コード補完についてここでは Eglot のドキュメントに一例として挙げられている Company を選びます。

実行

LSP サーバーが用意できていれば適当なソース ファイル (ここでの例では .c, .cpp, .py) を開き M-x eglot RET とタイプすると Eglot が機能し始めるはずです。一旦 Eglot が開始すると当該プロジェクト配下の同類のファイルも管理するので都度 M-x eglot する必要はありません。

使い方の要点

コード補完

Emacs 組み込み
M-x キー
complete-symbol C-M-i
Company

M-x company-mode で有効にしてタイプされた文字列がマッチすると補完候補がポップ アップします。手動で表示させるには M-x company-complete 。

キー 動作
C-n/C-p 候補の選択移動
<return> 補完確定
<tab> 候補を可能な限り絞り込む
C-s/C-r 候補内を検索
C-o フィルター (トグル)
M-(digit) 10 番目までの候補の中から直接選択
<f1> 選択位置の候補のドキュメント表示
C-w 選択位置の候補のソース表示

当方の環境と利用状況では C-w は No location available と出て効果が見られませんでした。

識別子の説明表示

M-x キー
eldoc-doc-buffer C-h .

関数・クラスの定義箇所への移動

M-x キー
xref-find-definitions M-.
xref-go-back M-,
imenu M-g i

Eglot のコマンド

詳細は 3.3 Eglot Commands などを参照。

識別子のリネーム

言語解析によっているので置換に比べ確実です。

M-x eglot-rename

フォーマット

M-x eglot-format

リファクタリング

使い込んでいないこともあり詳細は把握していません。

M-x eglot-code-actions

inlay-hints

関数の仮引数や C++ で auto 定義した変数の型などをコード中に埋め込まれたかのように表示します。 python-lsp-server ではサポートされていないようです。

M-x eglot-inlay-hints-mode でトグルするはずですが挙動が直感的でないです。非表示にした後 on にしてもソース コードに変更がないと再表示されないです (バグ?) 。

設定

多くの場合とくに設定しなくても使い始めることができますが筆者は ~/.emacs.d/init.el に次のように書きました。 use-package を活用しています。

~/.emacs.d/init.el

(use-package eglot
  :init
  ;; for Emacs 29.4 Built-In 1.12.29
  (setq warning-minimum-level :error)
  :config
  (add-to-list 'eglot-server-programs
               `((python-mode python-ts-mode) .
                 ,(eglot-alternatives
                   '("pylsp"
                     ("basedpyright-langserver" "--stdio")))))
  :bind
  (:map eglot-mode-map
        ("C-c r" . 'eglot-rename)
        ("C-c f" . 'eglot-format)
        ("C-c a" . 'eglot-code-actions)
        ("C-c o" . 'eglot-code-action-organize-imports)
        ("C-c q" . 'eglot-code-action-quickfix)
        ("C-c e" . 'eglot-code-action-extract)
        ("C-c i" . 'eglot-code-action-inline)
        ("C-c w" . 'eglot-code-action-rewrite)
        ("C-c m" . 'eglot-inlay-hints-mode)
        ("C-c h" . 'eldoc))
  :hook
  ((c-mode c++-mode) . eglot-ensure))

(use-package company
  :bind
  ("C-c SPC" . 'company-complete)
  :hook
  (eglot-managed-mode))
  1. Emacs 29.4 Built-In 1.12.29 では Warning のウインドウがたびたび開くので warning-minimum-level を調節しています。 ELPA 最新版には不要です。
  2. .py ファイルを開き M-x eglot を実行すると pylsp と basedpyright から選べるようになります (Variable: eglot-server-programs) 。 <tab> で補完が効きます。
  3. Eglot 関連コマンドにキーをバインドします (eglot-mode-map)。
  4. .c/.cpp ファイルを開くだけで Eglot が有効になります (2.2 Starting Eglot) 。

LSP サーバーの詳細設定

詳細を確認していないので参照先を示すに留めます。

Eglot 側からの LSP サーバーの設定

LSP サーバー側での設定

設定ファイルを読み込む LSP サーバーがあります。ここで取り上げた LSP サーバーはいずれも該当するようです。当然 VS Code などの他の LSP クライアントと設定を共有することになります。

続く

次回 は DAP クライアントの Dape について書きます。