みなさんさようなら. 最近わけあってscalaを触ってます.
いつもの通りemacsで開発環境をつくろうとして,ちょっと悩んだ挙句,解決しなかったのでメモ.
emacsでscalaの開発をしようとすると,scala-modeはまず使うでしょう. ただ,それだけだとちょっと不満で,メソッドをサジェストしてほしかったり,デバッグするために,ensimeというものがよく紹介されていますね.
そして,開発環境自体はDockerで作っていたりします.
そう,このensimeとDockerを上手いこと組み合わせて開発したかった.
先に結論を書きます. 今のところできなかった.
ensime
scalaのコードをemacsで書きたくなると,ensimeを使いたくなります(vimやsublimeからも使えます). これを使えば型チェックもできるし,デバッグもやりやすいはず!
型チェックなんてことができるってことは,裏側でコンパイルが走っているということです. これをやってくれているのが,ensime-serverです.
ensimeは,emacsのプラグインとして提供されていますが,ensime-server自体は独立していて,ensime-sbtというプラグインをsbt側でインストールしておく必要があります.
導入方法等は割愛しますが,emacsはこのensime-serverを動かすことで,scalaのコンパイルを実現しています.
だとするなら,ensime-serverをdocker内で動かし,そこにローカルのemacsから接続できれば, 環境を全てdockerにした上で(ローカルにscalaの実行環境を構築しなくても),ensimeを動かせるんじゃないだろうか,と思いました.
ensimeの起動
activatorから起動
help ensime
してみました.
それっぽいコマンドが見当たりません.
ensimeRunDebugあたりはそれっぽい……5005でlistenできるし,emacsからつなげそうな気配はあります.
しかし,docker内でensimeRunDebugを立ち上げて,手元のemacsからensime-connectすると,エラーとなりました.
Cache dir in ensime configuration file appears to be unset
と言われました. .ensimeにはcache-dir項目があるのにもかかわらずできない.
これはどういうことなんだろう……(ちなみにここの謎は未だに溶けていない
起動コマンドを調べる
activatorから起動できなかったので,実際にensimeを起動するときはどうやって起動しているんだろう?と思いました. というわけで,とりあえずローカルでensimeの環境を整えてensimeを起動してみます.
非常に長ったらしいjavaっぽいコマンドが出てきました. そうですね,ensime-serverはjavaですからね.
しかしjavaっぽいコマンドはensime-emacsの中には出てきません.設定ファイルである.ensime
をひたすら読み込んでいる.
で,よくよくコマンドを眺めてみると…….
これは,.ensime
に記述されている!
そう,ensime-emacsは .ensime
に記述されているコマンドを呼び出すだけでした.
つまりensime-serverの起動コマンドは.ensime
にかかれています.
しかし……長い! これをパースして起動するような何かを作る?いやそれensime-emacsのelispそのままだろ…….
emacsで起動
というわけでコマンド起動は諦めて, docker内で emacs --daemon && emacsclient -e "(ensime)"
でensimeを起動してみました.
これをやればもちろんdocker内でensime-serverが起動します.
が,そもそもこいつはtcpなのか? どのポートで生きているのか?
起動ポートは .ensime_cache/port
に書きだされています.
しかしこれは起動毎に変わってしまう…….
そこで,先に .ensime_cache/port
を作っておきます.
$ echo "65005 > .ensime_cache/port
この状態で起動したら,ちゃんと65005で起動しているようなログが見て取れました.
が,65005ポートを開けておいても,接続できません. lsofで見るとわかるのですが,おそらくportで指定されたポート直接ではなく少しずらしたポートを使っているんじゃないでしょうか. それを調べる前に,せっかくなのでdocker内のensime-serverにdocker内からconnectしてみます.
ところが!
Cache dir in ensime configuration file appears to be unset
またですよ.
これってローカルからでもconnectできないのであればもう解決策がないのでは…….
これではポートを調べても意味がありません.
ここで今回は諦め.
あまり期待できない
そもそもデバッグをemacsから投げるためには,実際にscalaのプログラムが動いているプロセスに繋がないと駄目はなずです. となると,Dockerで,別のJVMで動いているプロセスに,ローカルからつなぐというのはやっぱり原理的に難しいのでは……と思ってきました.
さらに,ensime-emacsのソースを読んでいて思うのですが,.ensime
をいろんなところで使っています.
これ,クライアント側とサーバ側で同じconfigを読むということは,実は同じ環境でしか実行できなんじゃないでしょうか.
仮にensime-connectのときも .ensime
を読んでいて,サーバ起動の時ももちろん.ensime
を読むとなると,実行環境が別の場合,どちらかがエラーになるのは当然な気がします.
この設計をしている限り,ensime-serverをdockerに閉じ込めて外からつなぐというのは非現実的なのかもしれません.
まぁそれでもensime-connectがエラーになるのは,そもそもローカルでも発生しているので原因がわかりませんが…….
参考
一応外からつなごうとしている人がパラパラと見受けられますが,順序立てた手順等は不明です.