githubはこちら
※英語が苦手なので、READMEはかなりテキトーです
https://github.com/daikitigogo/vim-scala-sbt-compiler
このプラグインで出来ること
- vimで設定済みのキーマップ叩くと、コンパイルエラーが出た場所に順にジャンプ出来る
- 「sbt ~compile」で待機してても、更新されるごとにジャンプ出来る
最低限の設定
基本的にファイルタイプごとにvimプラグインを設定する場合は拡張子で判断しますが、sbtでは決まったディレクトリ配下のファイルはすべて同じファイルタイプとしたいので、sbtプロジェクトのルートパスを.vimrcに追加する必要があります。
こんな感じに。
let g:ssc_application_settings = {
\ "sample1" : {
\ "rootPath" : $HOME."/workspace/sample1",
\ },
\ "sample2" : {
\ "rootPath" : $HOME."/workspace/sample2",
\ },
\ "sample3" : {
\ "rootPath" : $HOME."/workspace/sample3",
\ }
\}
キーマップの設定
キーマップを設定する場合は、以下を設定してください。
※それぞれの使い方は後ほど説明します。
nmap [お好きなキー] <Plug>ScalaSbtCompilerMake
nmap [お好きなキー] <Plug>ScalaSbtCompilerShow
nmap [お好きなキー] <Plug>ScalaSbtCompilerNext
nmap [お好きなキー] <Plug>ScalaSbtCompilerSet
使い方
まず初めのキーマップ(ScalaSbtCompilerMake)を叩きます。
すると↑で設定したrootPathで「sbt compile」を実行し、コンパイルエラーがある場合はその場所にジャンプします。
その後、2番めのキーマップ(ScalaSbtCompilerShow)を叩きます。
エラーの詳細が見れます。(↓参照)
type mismatch;
found : Int(2)
required: String
val samp1 = new Sample(2)
次のコンパイルエラー箇所にジャンプするには3番めのキーマップ(ScalaSbtCompilerNext)を叩きます。
4番目のキーマップ(ScalaSbtCompilerSet)はsbtの継続的ビルド時に使用します。
まず、普段「sbt ~compile」と叩くところを「sbt -Dsbt.log.noformat=true compile | tee quickFixFile」のような感じにします。
※linuxの場合
※要するに、「sbt compile」コマンドの実行結果を別のファイルにも出力出来るようにしてください。(こんな感じでOKです。 sbt -Dsbt.log.noformat=true compile > quickFixFile)
※-Dsbt.log.noformat=trueは出力に色付けしないようにするオプションです。
4番目のキーマップ(ScalaSbtCompilerSet)では、デフォルトでrootPath直下のquickFixFileを読み込むように設定しています。
読み込むファイルを指定したい場合はコマンドで、「:SSCSet 任意のファイル」と入力してください。
すいません。説明があまり上手くないので(というか雑)、少しでも興味持った方は気軽にご質問ください。
すべてはscala-vimmerを増やしたい一心です。
一応、自分への備忘メモも兼ねて、vim-compilerプラグインの作成手順を書いておきます。
興味のある方はどうぞ。。
vimのmakeコマンドとは
vimでmakeコマンドを実行すると、makeprgに設定されているコマンドをパイプでteeに渡しつつ実行します。(ubuntuの場合)
具体的にいうと、以下のような感じに動きます。
:set makeprg=scalac
:make sample1
→scalac sample1 2>$1| tee /tmp/xxxx/1
2>$1が何なのかはよく分かっていないのですが、要はmakeprgで設定したコンパイル結果を別ファイルにも出力しておき、そのファイルをquickfixlistに読み込んでいるようです。
※quickfixlistとは、vimgrepとかにも使われる、まあvimの便利機能ですね。
※errorformatというものを正しく設定しておくことで、コンパイル結果をquickfixlistに読み込むことが出来ます。
vim-compilerプラグインの作り方
vimで「:compiler sbt」のような感じでコマンドを打ちます。
するとvimは$VIMRUNTIME/compiler/配下のsbt.vimファイルを探しに行きます。
makeでsbtを実行させるには、↑で書いたようにmakeprgにsbtを設定すれば良いので、$VIMRUNTIME/conpiler/配下にこんな感じのファイルを置きます。
1 if exists("current_compiler")
2 finish
3 endif
4 let current_compiler = "sbt"
5
6 if exists(":CompilerSet") != 2 " older Vim always used
7 :setlocal
8 command -nargs=* CompilerSet setlocal <args>
9 endif
10
11 let s:cpo_save = &cpo
12 set cpo&vim
13
14 CompilerSet makeprg=sbt
15 CompilerSet errorformat=%A[%t%.%#]\ %f:%l:%c:\ %m,
16 \%Z[error]\ %.%#errors\ found,
17 \%Z[warn]\ %.%#warning\ found,
18 \%C[%.%#]\ %m
19
20 let &cpo = s:cpo_save
21 unlet s:cpo_save
まあ14行目〜18行目以外はvimプラグインを作る際のテンプレみたいなものなので、詳細は説明しません。
※基本、vimでscala書く人は僕よりvim上級者ではないかと勝手に決めつけているので。
で、14行目ですが、↑でも書いた通りmakeprg時の実行コマンドを設定しています。
これはまあそれだけです。
で、重要なのは15〜18行目、このerrorformatを正しく設定しないとコンパイルエラー箇所をジャンプすることが出来ません。
ただ、このerrorformatの設定が難解なんですよね
errorformat読み込み時のルール
- %A以降に指定されたパターンが見つかった場合は複数行エラーの開始とする
- %Z以降に指定されたパターンが見つかった場合は複数行エラーの終了とする
- %C以降に指定されたパターンが見つかった場合は複数行エラーの継続とする
まあ、すいません。上手く説明出来ないですが、sbtでコンパイルした場合、こんな出力が出ると思います。
[info] Loading project definition from ~/workspace/vim-make-test/sbt/project
[info] Loading settings from build.sbt ...
[info] Set current project to My-Item-Search (in build file:~/workspace/vim-make-test/sbt/)
[info] Executing in batch mode. For better performance use sbt's shell
[info] Compiling 1 Scala source to ~/workspace/vim-make-test/sbt/target/scala-2.12/classes ...
[error] ~/workspace/vim-make-test/sbt/src/main/scala/sample/Main.scala:7:28: type mismatch;
[error] found : Int(2)
[error] required: String
[error] val samp1 = new Sample(2)
[error] ^
[error] ~/workspace/vim-make-test/sbt/src/main/scala/sample/Main.scala:8:17: not found: value Sample
[error] val samp2 = Sample("Scala")
[error] ^
[warn] ~/workspace/vim-make-test/sbt/src/main/scala/sample/Main.scala:3:13: Unused import
[warn] import test._
[warn] ^
[warn] one warning found
[error] two errors found
[error] (compile:compileIncremental) Compilation failed
[error] Total time: 2 s, completed 2017/12/17 0:07:21
これに対して、errorformatはカンマ区切りで指定された各パターンに一致するかを確認します。
1個目の指定だと、
- %tはエラー(警告)の種別を取得します()
- %.%#は正規表現の .* と同じ意味です。
- スペースは\でエスケープします。
- %fはファイル名を取得します。
- %lは行番号を取得します。
- %cは絡む番号を取得します。
- %mはエラーメッセージを取得します。
要するに、
[error] /home/daikitigogo/workspace/vim-make-test/sbt/src/main/scala/sample/Main.scala:7:28: type mismatch;
は、
[%t(エラータイプ)rror] %f(ファイルゲット):(行番号ゲット):(カラム番号ゲット) (残りはエラーメッセージ)
と解析され、
{type : "e", "file" : "~/workspace/vim-make-test/sbt/src/main/scala/sample/Main.scala", line : "7", col : "28", msg : "type mismatch;"}
こんな感じのオブジェクトに変換されます。(オブジェクト構成は例えです)
ダメですね。このerrorformatについては上手く説明出来る気がしません。
詳細は以下を、もしくは初心者で気になる方はお気軽にご質問ください(私もまだまだ理解が足りないとは思いますが。。)
- http://vim-jp.org/vimdoc-ja/quickfix.html#error-file-format
次はscala用のtag設定の予定。
ctagsを使うとすぐにvimで「scalaの関数定義先にジャンブ」とかが出来るようになるが、もうちょい使い勝手良く改良したい。
vimでscalaプログラミングの需要ってあるんやろうか?
相性は良いと思うんですが。。