Windowsでvspec

Vimスクリプトのテスティングフレームワーク[vspec](https://github.com/kana/vim-vspec)をWindowsで動かす方法を紹介します。

![vspec.png](https://qiita-image-store.s3.amazonaws.com/0/36771/1a690863-60af-026c-5e2c-2b0ed86d14ec.png)

vspecはbashに依存しているため、Windows環境で動かすためには特別な準備が必要となります。
1. Cygwinを導入する
2. Cygwinでvspecを実行する環境を整える
3. QuickRunでvspec実行を設定する

vspec自体については以下を参照。
[Vim プラグイン開発でもユニットテストがしたい! (vim-vspec 編) - TIM Labs](http://labs.timedia.co.jp/2013/02/vim-vspec-introduction.html)

また[vspec](https://github.com/kana/vim-vspec)や[QuickRun](https://github.com/thinca/vim-quickrun)のインストールは各プラグインのREADMEなどを参考にしてください。
私はNeoBundleでインストールしました。

## 1. Cygwinを導入する
Cygwinをインストールします。
インストール方法は色んなところで紹介されているのでここでは割愛します。
私は以下の記事を参考にしました。
[ゼロからはじめる「Cygwin」 - WindowsでUNIXを動かしてみよう！ (1) 1969年生まれのOS - UNIX | マイナビニュース](http://news.mynavi.jp/articles/2013/08/06/cygwin/)

## 2. Cygwinでvspecを実行する環境を整える
ruby環境をCygwinにインストールします。
Cygwinへの追加パッケージのインストール方法はsetup.exeを使う方法やapt-cygコマンドを使用する方法があります。
以下に解説があるのでお好みでインストールしてください。

[ゼロからはじめる「Cygwin」 - コマンドプロンプトでUNIXコマンドを使う編 (2) 追加パッケージをインストールして行こう | マイナビニュース](http://news.mynavi.jp/articles/2013/11/25/zerokaracygwin/001.html)

インストールが必要なのは「ruby」、「ruby-rake」、「vim」、「vim-common」パッケージです。
またデフォルトで「vim-minimal」がインストールされる設定になっているので、アンインストールをしてください。

インストールが完了すればCygwinのコマンドプロンプトからrubyやgemコマンドが使用できるようになります。
あとで必要になるため、rubygemsで「bundle」をインストールしましょう。

```bash
gem install bundle
```

## 3. QuickRunでvspec実行を設定する
ここまででCygwinのコマンドプロンプトからvspecを実行する準備は整っているのですが、Vimには[QuickRun](https://github.com/thinca/vim-quickrun)という素晴らしいプラグインがあります。
QuickRun経由でテストスクリプトを実行できるように、.vimrcに設定を追記していきます。

### vim.vspecファイルタイプの準備
まず通常のvimファイルと区別するために、vim.vspecというファイルタイプを用意します。
*_spec.vimというファイルを読みこんだ場合、ファイルタイプにvim.vspecを設定するようにします。

```vim
au myvimrc BufRead,BufNew,BufNewFile *_spec.vim setlocal ft=vim.vspec
```

### vim.vspecのQuickRun設定を追加する
vspecプラグインに含まれているvspecコマンドを使用します。
ここではNeoBundle（またはVundle）を使用してvspecプラグインを導入した前提でvspecコマンドのパスを指定していますが、各々の環境に合わせて読み替えてください。（~/vimfiles/bundle/vim-vspecの部分）
またCygwinのインストールパスも各々のインストール先に合わせて読み替えてください。（c:/cygwinの部分。32bit版だとデフォルトのインストール先。）

以下の設定を.vimrcに追加してください。各行の意味は後述。

```vim
function! MyGetCygwinDir(fullpath)
  return "/cygdrive/" . substitute(a:fullpath, ':', '', '')
endfunction
let g:quickrun_config['vim.vspec'] = {
\ 'exec': '%c --login -c ' .
\         '"cd %%{MyGetCygwinDir(%s:p:h)}/..; ' .
\         '%%{MyGetCygwinDir(expand($HOME))}/vimfiles/bundle/vim-vspec/bin/vspec ' .
\         '%%{MyGetCygwinDir(expand($HOME))}/vimfiles/bundle/vim-vspec . ' .
\         '%%{MyGetCygwinDir(%s:p)}"',
\ 'command': 'c:\cygwin\bin\bash.exe',
\}
let g:quickrun_config['vim.vspec.alt'] = {
\ 'exec': '%c --login -c ' .
\         '"cd %%{MyGetCygwinDir(%s:p:h)}/..; rake test"',
\ 'command': 'c:\cygwin\bin\bash.exe',
\}
```

1～3行目
Cygwin環境ではファイルパスが変わってしまう（例えば、C:\hogeの場合、/cygdrive/c/hogeになる）ので、ファイルパスをcygwin環境のものに変更してやる必要があります。
何度も出てくるのでMyGetCygwinDir()というfunctionを定義しています。

4～11行目
QuickRun設定部分です。
まずcdでテストスクリプトの一つ上の位置までCygwinコマンドプロンプトのワークディレクトリを移動させています。
vspecではプラグインルートに```t```ディレクトリを作成し、その中にテストスクリプトを配置することになっているため、これでプラグインのルートディレクトリの位置に移動できます。

次にvspecコマンドを実行しています。
vspecコマンドのフォーマットは以下の通りです。
```vspec [{追加のランタイムパス}] {実行対象のテストスクリプト}```
追加のランタイムパスにvspecや自作プラグインのパスを追加する必要があります。
[vspec-matchers](https://github.com/rhysd/vim-vspec-matchers)などを使用している場合はそれも指定が必要です。

引数の最後で実行対象のソース自体が指定されて、カレントバッファのソースが実行されるようになります。

12～16行目
おまけでrake経由でtディレクトリにあるテストスクリプト全てを実行する設定を追加しています。
単体実行の時と同様にプラグインのルートまで移動し、```rake test```を実行しています。
rake実行の前には「Cygwin環境で」```bundle install```をするのを忘れないようにしてください。

※QuickRunのキーマップ設定として、ファイルタイプのデフォルトと「ファイルタイプ＋.alt」の設定をしておくと便利です。
私はデフォルトを「,r」、altを「,R」に設定してします。

```vim
nmap ,r <Plug>(quickrun)
nnoremap ,R :<C-u>call quickrun#run([{'type': &filetype . '.alt'}])<CR>
```

以上です。
質問、指摘、補足などありましたら、コメント頂けますと幸いです。


## おまけ：CygwinコマンドプロンプトをVimから立ち上げる
Cygwin操作をVimから実行したい方向けの情報です。（vspecとは無関係です）
Vimshellのiexeでは文字化けや動作が不安定だったので、[Conque](http://code.google.com/p/conque/)を使用しています。

```vim
" Conqueのインストール
NeoBundleLazy 'http://conque.googlecode.com/svn/trunk/'
\, {'autoload': {'commands': ['ConqueTerm', 'ConqueTermSplit', 'ConqueTermTab', 'ConqueTermVSplit']
\,               'functions': ['conque_term#open', 'conque_term#subprocess', 'conque_term#register_function']}
\,  'name': 'Conque'}

" Cygwin
command! Cygwin call s:my_cygwin()
function! s:my_cygwin() "{{{
  let my_conque_term = conque_term#open('C:\cygwin\Cygwin.bat', ['topleft split', 'resize 10'])
  while my_conque_term.read() == ''
  endwhile
  call my_conque_term.writeln('cd ' . MyGetCygwinDir(getcwd()))
endfunction "}}}
```
```:Cygwin``` でCygwin.batが開かれます。
```while my_conque_term.read() == ''``` でプロンプトが返ってくるまで待ってから、
```call my_conque_term.writeln('cd ' . MyGetCygwinDir(getcwd()))``` でワークディレクトリを変更してやっているのがポイントかなと思います。
Vimのカレントディレクトリと同じディレクトリが開かれる方が便利かなと。