$shibayu36->blog;

株式会社はてなでエンジニアをしています。プログラミングや読書のことなどについて書いています。

Emacsでscala-mode2とensimeを使ってScala環境を作る

Scalaを書くにはIntelliJを使うのが良さそうだったのだけど、使ってみたらいつもの感覚で使うのがけっこう難しかった。そこでEmacsでの環境構築を行ってみた。今回はscala-mode2とensimeを利用した。特にensimeに関してけっこうはまってしまったので、そのあたりを多めに書く。

scala-mode2

最近はscalaemacsで書くならscala-mode2を使うみたい。セットアップは簡単でM-x package-list-packagesしてscala-mode2をインストールした後、以下をどこかに書いておけば良いだけ。

;;; scala mode
(require 'scala-mode2)

これでひとまずハイライトなどを行うことが出来た。

ensime(セットアップ編)

続いてensimeのセットアップを行う。ensimeを利用することで、型を利用した補完、エラーのハイライト、定義ジャンプなどが利用できる。ensimeはensime-serverというものにemacsのclientでアクセスすることによって、これらの機能を実現している。この仕組みのため、Emacs以外にもSublime TextやAtomで使うことができる。Vimでは使えないみたい(VimIntelliJにいい感じのプラグインがあるみたいなのでそっちで良さそう)。

基本的には https://github.com/ensime/ensime-emacs/wiki/Quick-Start-Guide に書いてある通りに実行していくと良い。このセットアップのやり方が少し分かりにくくてはまってしまった。


まずemacs側にensimeのclientをインストールする。これは簡単。まずM-x package-list-packagesしてensimeをインストール。その後以下の様な設定を書いておく。

(require 'ensime)
(add-hook 'scala-mode-hook 'ensime-scala-mode-hook)


ensimeではプロジェクトごとに.ensimeというファイルが必要になるので、続いてこちらを作れるようにする。これはsbt-pluginが提供されているので、そちらを利用する。

このプラグインを利用するため、~/.sbt/0.13/plugins/plugins.sbtを編集する。

addSbtPlugin("org.ensime" % "ensime-sbt" % "0.1.7")

これでsbt gen-ensimeが利用できるため、ensimeを利用したいプロジェクトのルートディレクトリに移動して、コマンドを実行する。

$ sbt gen-ensime

.ensimeファイルが出来上がり、ensimeを利用する準備が出来た。


最後にそのプロジェクトのファイルを開いている時にM-x ensimeを実行することで、ensime-serverが自動的に立ち上がり、補完などをすることができる。

ensimeの補完でauto-completeを利用する

ここまでの設定で補完ができるようになっている。しかしensimeのデフォルトの設定では補完にはcompany-modeが利用されている。僕は補完を使うときはいつもauto-completeを利用しているためこれに合わせたい。調べてみると、これはensime-completion-styleという変数でカスタマイズが出来る。

auto-completeを利用するには設定に追記すれば良い。

(setq ensime-completion-style 'auto-complete)

ensimeをさらに便利にする

せっかくなのでさらに便利にしてみる。

  • ドットを入力した際に自動的に補完が起動する
  • カーソル下の情報をEldocで表示する
    • エラーがあるときはエラー内容を、そうでない場合は型情報を表示する

これはid:taraoさんの設定 が非常に参考になるので、パクってみた。

最終的な設定はこちら

Tips

今回はパクっただけだけど、この設定がどのように実現されているか軽く調べてみた。


ドットを入力した際に自動的に補完を起動するのは、仕組みさえ分かるとけっこう簡単。まずドットを入力した後補完のためのコマンドを実行するというinteractiveなコマンドを作成する。その後ドットに対するキーバインドにこのコマンドを設定すれば、ドットを入力した時に自動的に補完を起動してくれる。

(define-key scala-mode-map (kbd ".") 'scala/completing-dot)


Eldocで表示する内容を生成するには、eldoc-documentation-functionというのをカスタマイズすれば良い。バッファごとに内容を切り替えたいと思うので、setq-localを利用すると良さそう。

以下の様なものをensime-modeのhookに入れておくと、ensime-modeが立ち上がった時にeldoc-documentation-functionが変更され、eldocにエラー情報や型情報を表示できる。

(defun scala/enable-eldoc ()
  "Show error message or type name at point by Eldoc."
  (setq-local eldoc-documentation-function
              #'(lambda ()
                  (when (ensime-connected-p)
                    (let ((err (ensime-print-errors-at-point)))
                      (or (and err (not (string= err "")) err)
                          (ensime-print-type-at-point))))))
  (eldoc-mode +1))

まとめ

Scalaやsbt、ensimeの仕組みがあまりわかってないままカスタマイズを始めたので、ensimeが動くところまで行くのに結構時間がかかってしまった。しかしこれで補完を行ったり定義に飛んだりといったことができるようになったので、Scalaの開発が出来そうになった。