Vim Advent Calendar 2012 ujihisa 4
Posted at 2013/02/28ツイート
Vim Advent Calendar 2012 の 90 日目の記事です。 昨日はthincaさんによる魔改造でした。ちなみにcleverは大人が子供に「デキる子だねえ」というときや、大人同士が皮肉でずるがしこいなにかを褒めるときに使える便利な単語らしいです。
Scalaとsbt
RubyにおけるRake, HaskellにおけるCabal, ClojureにおけるLeiningen, CにおけるMakeがScalaにおけるSBT (Simple Build Tool)で、これは挙動が他のほとんどのビルドツールよりも複雑なことで有名なデキる子です。毎日愛用しています。
sbt (SBTのコマンド) を起動するには果てしない時間がかかるため、一般にはsbtコマンドを対話モードで起動して、そのプロセスを使い続けるというスタイルが一般的です。つまり、sbtとvimは本質的に同じです。
:VimShellSendString
VimShellのiexe
ならびに:VimShellInteractive
で立ち上げた外部プロセスにメッセージを投げる便利な方法として:VimShellSendString
コマンドがあります。これは引数として与えられた文字列または選択範囲を”background buffer”に投げます。
たとえばfiletypeがscalaであるファイルを編集中は、
- ファイルを保存する
- sbtに
compile
メッセージを送って適切にコンパイルできるかどうか確認する
を順にまとめて行う必要がかなり頻繁にあります。
nnoremap <Space>m :<C-u>update<Cr>:VimShellSendString compile<Cr>
などと設定することでワンキーで保存・コンパイルを行うことができ、便利です。quickrunやsyntasticやwatchdogsなどのプラギンと違い、すでにライブラリの読み込みなどが完了して起動しているプロセスを再利用するので、10~30倍くらい高速で動作します。
しかしながら、シェルとしてのVimShellと対話環境としてのiexe窓の両方を開いていると、どちらが”background buffer”なのかが曖昧になるという問題があります。
失敗している様子:
成功している様子:
解決
t:
スコープの変数、vimshell#interactive#set_send_buffer()
, vimshell#interactive#send()
の合わせ技で対処します。
function! s:ujihisa_start_sbt()
execute 'VimShellInteractive sbt'
stopinsert
let t:sbt_bufname = bufname('%')
if !has_key(t:, 'sbt_cmds')
let t:sbt_cmds = [input('t:sbt_cmds[0] = ')]
endif
wincmd p
endfunction
command! -nargs=0 StartSBT call <SID>ujihisa_start_sbt()
function! s:sbt_run()
let cmds = get(t:, 'sbt_cmds', 'run')
let sbt_bufname = get(t:, 'sbt_bufname')
if sbt_bufname !=# ''
call vimshell#interactive#set_send_buffer(sbt_bufname)
call vimshell#interactive#send(cmds)
else
echoerr 'try StartSBT'
endif
endfunction
function! s:vimrc_scala()
nnoremap <buffer> <Space>m :<C-u>write<Cr>:call <SID>sbt_run()<Cr>
endfunction
augroup vimrc_scala
autocmd!
autocmd FileType scala call s:vimrc_scala()
autocmd FileType scala nnoremap <buffer> <Space>st :<C-u>StartSBT
augroup END
上記のように~/.vimrc
に記述し、scalaのファイルを編集するときにiexe sbt
や:VimShellInteractive sbt
のかわりに:StartSBT
コマンドを使います。以後、コンパイルなど行いたいときには<Space>m
を打鍵します。なおcompile
以外のコマンドにも対応するため、t:sbt_cmds
という変数を用意しています。ここに実行させたいコマンド列を指定します。なお初回起動などでそのタブにこの変数がセットされていないときは、入力を求められます。
これで<Space>m
を打鍵するだけでファイルの保存・コンパイルができ、しかも30倍高速化しました。Scalaにおける開発がはかどります。
余談
HootSuiteという会社はHootSuiteの実装に一部Scalaを用いています。Scala開発チームの約50%の人が上記テクニックを用いて|<Space>m|
だけで保存・コンパイルなどの定形操作を自動化かつ高速化しています。
もどる
blog comments powered by Disqus