Rubyプログラミングが快適になるVim環境を0から構築する


より快適なVim × Ruby環境を目指して構築したvim環境について。
0からでも構築できるように整理した。

**やること**

最初にRuby、Vim、その他必要なパッケージをガシガシインストールする。
その後、設定した下記機能について実際の操作例を見ていく。

- 自動コード補完ができるようにする（Rsense/neocomplete）
- Vim上で静的解析ができるようにする（Rubocop/syntastic）
- Vimからリファレンスを閲覧できるようにする（vim-ref/vim-ref-ri）
- メソッド定義元へのジャンプができるようにする（ctags/vim-tags）
- 構文終わりのキーワードを自動入力できるようにする（vim-endwise）

OSはLinux（CentOS6.5）を想定。検証環境は以下のとおり。

```
$ uname -a
Linux vagrant-centos65.vagrantup.com 2.6.32-431.3.1.el6.x86_64 #1 SMP Fri Jan 3 21:39:27 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
```

## Rubyのインストール
何はともあれ、Rubyをインストール。rbenvを使って、現時点で最新のRubyをインストールする。
ここはインストール手順だけ載せる。

```
$ sudo yum install zlib-devel openssl-devel libffi-devel -y
$ git clone https://github.com/sstephenson/rbenv.git ~/.rbenv
$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
$ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
$ source ~/.bash_profile
$ git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
$ rbenv install 2.2.1
$ rbenv rehash
$ rbenv global 2.2.1
```

インストール確認

```
// インストール指定したバージョンが表示されればOK
$ ruby -v
ruby 2.2.1p85 (2015-02-26 revision 49769) [x86_64-linux]
```

参考

- [sstephenson/rbenv](https://github.com/sstephenson/rbenv)

## Vimのインストール
CentOSのデフォルトvimやyumでインストールできるvimは古いのでソースから最新版を手に入れる。
configureのオプションには必要最低限と思われるものだけつけた。
Ruby同様、ここも手順だけ載せる。

```
$ sudo yum install lua-devel ncurses-devel -y
$ hg clone https://vim.googlecode.com/hg vim
$ cd vim
$ hg pull
$ hg update
$ make distclean
$ ./configure --prefix=/usr/local --with-features=huge --enable-multibyte --enable-rubyinterp --enable-luainterp --enable-cscope --enable-fail-if-missing
$ make
$ sudo make install
```

インストール確認

```
$ vim --version
VIM - Vi IMproved 7.4 (2013 Aug 10, compiled Mar  7 2015 04:25:14)
Included patches: 1-657
Compiled by vagrant@vagrant-centos65.vagrantup.com
.
.
```

参考

- [Vim from Mercurial : vim online](http://www.vim.org/mercurial.php/manual.ja.html#.E3.82.A4.E3.83.B3.E3.82.B9.E3.83.88.E3.83.BC.E3.83.AB)

## RSenseのインストール
次にRSenseをインストールする。
RsenseはEmacsやVimに特化したRubyのための開発援助ツールで、ここでは特にIDEのような自動コード補完目的のために使う。
導入には、jdkのインストールや権限の変更など少々面倒な作業があるがコマンド数的には少ない。現時点での最新版は0.3だった。

```
$ sudo yum install java-1.8.0-openjdk wget -y
$ wget http://cx4a.org/pub/rsense/rsense-0.3.tar.bz2
$ bzip2 -dc rsense-0.3.tar.bz2 | tar xvf -
$ sudo cp -r rsense-0.3 /usr/local/lib
$ sudo chmod +x /usr/local/lib/rsense-0.3/bin/rsense
```

インストール確認

```
// バージョン番号が表示されればOK
$ /usr/local/lib/rsense-0.3/bin/rsense version
RSense 0.3
```

参考

- [RSense - ユーザーマニュアル](http://cx4a.org/software/rsense/manual.ja.html)

## 利用するgemのインストール
静的解析ツールの[rubocop](https://rubygems.org/gems/rubocop)とリファレンス用の[refe2](https://rubygems.org/gems/refe2)をインストールする

```
$ gem install rubocop refe2
```

インストール確認

```
// rubocopとrefe2が表示されればOK
$ gem list | grep -e rubocop -e refe2
refe2 (0.8.0)
rubocop (0.29.1)
```

事前にリファレンスの構築をしておく

```
$ bitclust setup
```


## ctagsのインストール
メソッド定義元へのジャンプ機能を使うためにctagsをインストールする

```
$ sudo yum install ctags -y
```

## NeoBundleのインストール
NeoBundleとはvimプラグイン管理を便利にしてくれるvimプラグインのこと。Rubyで言うBundlerのような感じ。
インストールはコマンド1発で終わり！

```
$ curl https://raw.githubusercontent.com/Shougo/neobundle.vim/master/bin/install.sh | sh
```

## vimの設定とvimプラグインのインストール

### 各種ファイル作成
.vimrcと、インデント設定用の.vim/indent/ruby.vimを作成する。

```
$ mkdir ~/.vim/indent
$ touch ~/.vim/indent/ruby.vim
$ touch ~/.vimrc
```

### .vimrc
基本的な設定と、プラグインの設定を書いた.vimrcを作成。

```vim:~/.vimrc
" -------------------------------
" NeoBundle
" -------------------------------
if has('vim_starting')
  if &compatible
    set nocompatible
  endif

  set runtimepath+=~/.vim/bundle/neobundle.vim/
endif

call neobundle#begin(expand('~/.vim/bundle'))

NeoBundleFetch 'Shougo/neobundle.vim'

" コード補完
NeoBundle 'Shougo/neocomplete.vim'
NeoBundle 'marcus/rsense'
NeoBundle 'supermomonga/neocomplete-rsense.vim'

" 静的解析
NeoBundle 'scrooloose/syntastic'

" ドキュメント参照
NeoBundle 'thinca/vim-ref'
NeoBundle 'yuku-t/vim-ref-ri'

" メソッド定義元へのジャンプ
NeoBundle 'szw/vim-tags'

" 自動で閉じる
NeoBundle 'tpope/vim-endwise'

call neobundle#end()

NeoBundleCheck

" -------------------------------
" Rsense
" -------------------------------
let g:rsenseHome = '/usr/local/lib/rsense-0.3'
let g:rsenseUseOmniFunc = 1

" --------------------------------
" neocomplete.vim
" --------------------------------
let g:acp_enableAtStartup = 0
let g:neocomplete#enable_at_startup = 1
let g:neocomplete#enable_smart_case = 1
if !exists('g:neocomplete#force_omni_input_patterns')
  let g:neocomplete#force_omni_input_patterns = {}
endif
let g:neocomplete#force_omni_input_patterns.ruby = '[^.*\t]\.\w*\|\h\w*::'

" --------------------------------
" rubocop
" --------------------------------
" syntastic_mode_mapをactiveにするとバッファ保存時にsyntasticが走る
" active_filetypesに、保存時にsyntasticを走らせるファイルタイプを指定する
let g:syntastic_mode_map = { 'mode': 'passive', 'active_filetypes': ['ruby'] }
let g:syntastic_ruby_checkers = ['rubocop']

" --------------------------------
" 基本設定
" --------------------------------
" vim内部で使われる文字エンコーディングをutf-8に設定する
set encoding=utf-8

" 想定される改行コードの指定する
set fileformats=unix,dos,mac

" ハイライトを有効化する
syntax enable

" 挿入モードでTABを挿入するとき、代わりに適切な数の空白を使う
set expandtab

" 新しい行を開始したとき、新しい行のインデントを現在行と同じにする
set autoindent

" ファイル形式の検出の有効化する
" ファイル形式別プラグインのロードを有効化する
" ファイル形式別インデントのロードを有効化する
filetype plugin indent on
```

### .vim/indent/ruby.vim
インデントの設定は~/.vim/indent/ruby.vimに書く。Rubyのインデントは2スペースが一般的なのでその設定をする。

```vim:~/.vim/indent/ruby.vim
" tabstop: TABキーに対応する空白数を設定
" shiftwidth: 自動インデントや"<<"、">>"で動く幅の設定
" softtabstop: TABキーやBSキーを打ち込んだときに動く幅の設定
setlocal tabstop=2 shiftwidth=2 softtabstop=2
```

#### vimプラグインのインストール
作成した.vimrcに書いてあるが、以下のプラグインをNeoBundleを使ってインストールしていく。

- neocomplete.vim
- rsense
- neocomplete-rsense.vim
- syntastic
- vim-ref
- vim-ref-ri
- vim-tags
- vim-endwise

Vimを開いて

```
:NeoBundleInstall
```

を実行するだけ。
あるいはVimを開いた瞬間にインストールするかを問われるので、そちらでインストールをしてもOK。

ここまででインストール系の作業は終わりなので、次は設定と照らし合わせながら実際にvimを動かしていく。

## 自動コード補完を使う

**RSense × neocomplete × neocomplete-rsense.vim**を使った自動コード補完を使おう

（例）Stringオブジェクトに対してcapitalizeメソッドを呼び出す
[![Gyazo](http://i.gyazo.com/2034151db39472dbbe3ca7ef276e10ae.gif)](http://gyazo.com/2034151db39472dbbe3ca7ef276e10ae)

~/.vimrcに書いた、

```
let g:rsenseUseOmniFunc = 1
```

の設定で、自動コード補完が使える状態になっている。
最高に便利だ。RSenseにはその他にも型を確認したり、編集中のクラスやメソッド名が確認できる機能もあるようなので、興味のある人は参考リンクを見るといいかもしれない。

**参考**

- [RSense - ユーザーマニュアル](http://cx4a.org/software/rsense/manual.ja.html)
- [VimでRSenseを使って快適Rubyプログラミング - NigoroJr](http://nigorojr.com/articles/19)

## 静的解析を実行する

**rubocop × syntastic**を使って、Vimから静的解析を実行しよう

（例）`sample.rb`を保存したタイミングで静的解析が走り、使っていない変数が定義されていると注意をされている
[![Gyazo](http://i.gyazo.com/daf1182c597cb2304eb518767f82ec97.gif)](http://gyazo.com/daf1182c597cb2304eb518767f82ec97)

~/.vimrcの下記設定で、

```
let g:syntastic_mode_map = { 'mode': 'passive', 'active_filetypes': ['ruby'] }
```

保存時にRubyファイルに対してrubocopが実行される状態にしている。
これで、コード品質を高めつつ、オレオレなRubyコードから卒業できそうですね。

**参考**

- [Rubocopをsyntasticを使ってVimから自動実行する - Qiita](http://qiita.com/yuku_t/items/0ac33cea18e10f14e185)

## リファレンスを閲覧する

**vim-ref × vim-ref-ri**を使ってVimからリファレンスを参照しよう

（例）Enumerable#selectのリファレンスを参照する
[![Gyazo](http://i.gyazo.com/bb96891a6a312fa2c53118dec3e5db38.gif)](http://gyazo.com/bb96891a6a312fa2c53118dec3e5db38)

上記のgif動画ではカーソル下のメソッドのリファレンスを`Shift + k`で呼び出している。
Pryでも見れるけど、Vimから見れるのはもっと楽でいいですね。

これ以外にも`:Ref refe Enumerable#select`とか`:Ref ri Array#map`のようにして任意のリファレンスを参照することもできる。
リファレンス内は`Enter`キーでジャンプして、`Ctrl+t`で戻ることができるので覚えておくと捗る。

**参考**

- [vim-refとReFeでRubyのリファレンスマニュアルをvimで読む -- ぺけみさお](http://www.xmisao.com/2014/04/10/vim-ref-and-how-to-use-ref-refe.html)

## メソッド定義元へジャンプする
**ctags × vim-tags**を使ってメソッド定義元へジャンプしよう

まずはじめにVimを開いて

```
:TagsGenerate!
```

を実行してtagsファイルを作成する。必要な作業はこれだけ。

（例）クラス定義元へジャンプした後、元の位置に戻る
[![Gyazo](http://i.gyazo.com/e6b0be29efe4345ce8e346bfc482d2c4.gif)](http://gyazo.com/e6b0be29efe4345ce8e346bfc482d2c4)

`Ctrl + ]`でカーソル下のクラスやメソッドの定義元へ移動することができ、`Ctrl + t`で元の位置に戻ることができる。
gemのソースを読んだりするときに活躍しますね。

## 自動で構文の終わりのキーワードを入力する

`vim-endwise`で、`class`や`def`キーワードと対になる`end`を自動入力しよう

（例）class、defのendキーワードを自動で入力
[![Gyazo](http://i.gyazo.com/107b114ec0ca32da97b757ae68e493e3.gif)](http://gyazo.com/107b114ec0ca32da97b757ae68e493e3)

このプラグインはインストールするだけで使える状態になっている。

`end`3文字なんてどうってことない手間かもしれないけれど、積み重なると結構なタイプ量になると思う。タイポもなくなるし、使わない理由は無いですね。


## まとめ
今回設定したのは以下の5つ。

- Rsenseとneocompleteを使ったコードの自動補完
- Rubocopとsyntasticを使ったVim上での静的解析
- vim-refとvim-ref-riを使ったVim上でリファレンス閲覧
- ctagsとvim-tagsを使ったメソッド定義元へのジャンプ
- vim-endwiseを使った構文終わりのキーワード補完

~/.vimrcの設定についてはあまり触れていないけれど、ほとんどが推奨設定や参考リンク先のコピペなので難しいことは書いていないはず。

時間かかったけど、これで今よりだいぶ快適な環境になると思う（まだ使い込めていない）。ここまでの手順をAnsibleプレイブックとかにしておきたいなぁという気持ち。