Emacs + Metals + lsp-mode でScalaを書く

最近重たい処理走らせてる時とかにIntelliJが遅くてつらかったのでEmacsでもある程度コード読んだり書けたり出来るようにしました。 最近はLSPが人気あるようでEmacsでもlsp-modeというのが結構使われているみたい。Scalaの場合はLSPとしてMetalsを使うことになります。

設定

  • lsp-modeが入っていればとりあえずOK
  • flycheckを入れてコンパイルエラーの表示が出来るようにしましょう
  • lsp-uiを入れてなんかUIからポチポチ出来るようにしましょう
  • companyをコード補完機能に使いましょう
(use-package flycheck
  :init (global-flycheck-mode))

(use-package lsp-mode
  :hook
  (lsp-mode . lsp-lens-mode)
  (scala-mode . lsp)
  :config
  (setq lsp-prefer-flymake nil))

(use-package lsp-ui)

(use-package company
  :hook
  (scala-mode . company-mode)
  :config
  (setq lsp-completion-provider :capf)
  (setq company-minimum-prefix-length 1))

そんなにガリガリ設定書かなくても割といい感じになるのがすごい。

使い方

  • インストールはMetalsのドキュメントでどうぞ。
  • M-., M-, で定義元にジャンプしたり戻ったりできる。
  • キーバインドの一覧は https://emacs-lsp.github.io/lsp-mode/page/keybindings/
  • 一覧に乗ってないけど s-l g e でエラー一覧表示ができた。ドキュメント更新のpull req送った方良いのかな?

f:id:tototoshi:20210406224447j:plain
コード補完

f:id:tototoshi:20210406224357p:plain
エラーの一覧表示

f:id:tototoshi:20210406224517p:plain
コンパイルエラーの表示と選択できるアクション一覧

トラブルシューティング

デバッグはとりあえず *lsp-log* バッファを見てみると何か分かる。Metalsの場合は .metals/metals.log でも良し。

必殺再起動は M-x lsp-restart-workspace

ハマったとこ

補完がうまく行かないなあ、Any型と判定されるなあとか思ってたんだけど、monorepo的なリポジトリでworkspaceのルートが誤判定されてちゃんとプロジェクトが読み込まれていないのが原因でした。M-x lsp-workspace-folder-add で設定したら補完ができるようになりました。

あと大きなプロジェクトで遅くなるけどファイルをウォッチするか?遅くなるけど?と聞かれた時に読み込まないようにしたら補完が効きませんでした。ウォッチしないとダメなのかな。とりあえずウォッチすることにして、遅くなってから考えることにしました。

制限

今のところ機能的にここが限界だろうなあというのが2つ。

  • 高度なリファクタリング機能
    • さすがにIntelliJには勝てない。なんかすごいことやろうと思ったらIntelliJを起動しよう。
  • Javaのコードを追えない
    • Metals = scalameta + LSP なのでそりゃそうかという感じ。

感想

コード読んだり、調査だったり、ちょっとした修正には十分な機能なので嬉しい。まあガッツリコード書くときはIntelliJだけどそれ以外を軽い環境でカバー出来るのは良いですね。