Vim で Ruby を書くためのプラグイン3つ書いた

普段 Vim で Ruby を書いているのですが，そういえば Ruby を書くのを補助する Vim プラグイン少ないなぁと思って先月は Ruby プラグイン作成月間にしてみました．
本エントリでは僕が作成した3つのプラグインを紹介します．

- [unite-ruby-require.vim](https://github.com/rhysd/unite-ruby-require.vim)
`require` 対象の補完をする unite.vim ソース．

- [neco-ruby-keyword-args](https://github.com/rhysd/neco-ruby-keyword-args)
neocomplcache で Ruby 2.0 のキーワード引数を補完

- [vim-textobj-ruby](https://github.com/rhysd/vim-textobj-ruby)
Ruby のブロックをテキストオブジェクト化



# unite-ruby-require.vim

Ruby で外部のソースを読み込むのに使う `require` ですが，標準だけでも大量のライブラリがあり，なかなか全部覚えるのは大変です．
そこで，unite.vim で `require` の候補をインクリメンタルに検索できるプラグイン [unite-ruby-require.vim](https://github.com/rhysd/unite-ruby-require.vim) を作りました．

```
:Unite ruby/require
```

で起動すると，Ruby の標準のライブラリやインストールした gem，bundler でプロジェクトローカルにインストールしているライブラリのパスを収集し，`require` の候補を一覧表示します．
あとは unite.vim のインクリメンタルサーチで目的のライブラリを探すだけです．

例として，URI 関連のクラスを探したい場合は，`:Unite ruby/require` で開き，`uri` と入力するとこんな感じに抽出されます．

![uri で検索した場合](https://raw.github.com/rhysd/unite-ruby-require.vim/master/screen.jpg)

ここで `open-uri` を選択してエンターキーを押すと，カーソル行に `require 'open-uri'` が挿入されます．

なお，rbenv などで Vim の Ruby インターフェースと異なる Ruby を使用している場合は，

```vim
let g:unite_source_ruby_require_ruby_command = '$HOME/.rbenv/shims/ruby'
```

という風に，Ruby へのパスを定義しておいて下さい．



# neco-ruby-keyword-args

Ruby 2.0 では，引数を名前で指定するキーワード引数が追加されました．
今まではハッシュを引数にすることで擬似的に名前渡しを実現していましたが，もうそんなことをする必要はありません．

```ruby
# ハッシュのような書き方で引数の名前とデフォルト値を指定
def test(tsura: 'poyo', yaba: 'poyo')
  puts tsura+yaba
end

# 指定しないとデフォルト値が使われる
test #=> poyopoyo
# 名前で指定するので順番は意識しなくて良い
test(yaba: 'dameda', tsura: 'mou') #=> moudameda
```

これにより，引数の順序を守らないといけないなどの煩わしさから開放され，どの引数が何の値を示しているのか呼び出し側で明示できます．
しかし，当然ですが代わりに引数に付けられた名前を覚えておかなければなりません．
そこで，ソース内のキーワード引数名を収集し，自動で補完してくれるプラグイン[neco-ruby-keyword-args](https://github.com/rhysd/neco-ruby-keyword-args)を作りました．
neocomplcache のソースとして実装しているので，neocomplcache を使っていることが前提です．

使用中のスクリーンショットはこんな感じです．
![スクリーンショット](https://raw.github.com/rhysd/neco-ruby-keyword-args/master/screenshot.jpg)

少し分かりにくいですが，一番下の行で `test` メソッドの `tsura` 引数を補完しようとしているところです．
補完候補の `[K]` というのがキーワード引数補完のマークで，その次にデフォルト値が `'poyo'` であることが表示されています．

候補収集の範囲については，相対パスで `require` した先のソースからも再帰的に収集します．なので，

```ruby:hoge.rb
def hoge(foo: 'a', bar: 'b')
end
```

```ruby:huga.rb
require './hoge.rb'
```

```ruby:piyo.rb
require './huga.rb'

hoge #ここで補完できる
```

のように，再帰的に piyo.rb → huga.rb → hoge.rb と潜っていって候補を収集してくれます．


# vim-textobj-ruby

まず，テキストオブジェクトについて知らない方は `:help text-object` してみてください．Vim のとても便利な機能です．

[vim-textobj-ruby](https://github.com/rhysd/vim-textobj-ruby) では，Ruby の `class` や `if`，`begin` のような
`end` で終わるブロックをテキストオブジェクトにして一発で削除や選択やヤンクが行えるようになります．
似たようなプラグインに vim-textobj-rubyblock があるのですが，自分の環境でうまく動かなかったのと，シンタックスハイライトなどを使ってもっとうまく選択できると判断したため新しく作りました．
なお，kana さんの [vim-textobj-user](https://github.com/kana/vim-textobj-user) が必要です．

プラグインをインストールすると，モーション待ちモードに `r` マッピングが追加されます．（モーション待ちモードについては `:help mapmode-o` を参考にしてみて下さい）

いくつかの使用例を示します．
以下の例では `#%` はカーソル位置です．

```ruby
def hoge(yo)
    if yo
        puts "yo!"
        #%
    end
    puts "everyone!"
end
```

`def` と `if` の2つのブロックがネストしています．
`if` 文の内部にカーソルがある状態で `dar` を入力すると `if` のブロック全体が削除され，

```ruby
def hoge(yo)
    #%
    puts "everyone!"
end
```

となります．また，

```ruby
def hoge(yo)
    if yo
        puts "yo!"
    end
    #%
    puts "everyone!"
end
```

のように `if` の外で `def` の内部にカーソルがある場合に `vir` とすると `def` の内部（`if yo` から `puts ...` まで）がビジュアルモードで選択されます．

つまり，カーソルがある位置のブロックが対象になってテキストオブジェクト化されます．


#その他のプラグイン

その他，僕が書いたものではないですが，気になっているプラグインを挙げておきます．

- [neocomplcache-rsense](https://github.com/Shougo/neocomplcache-rsense)
Ruby の開発援助ツール，RSense を vimproc で非同期に実行し補完を行うプラグインです．


- [vim-ruby](https://github.com/vim-ruby/vim-ruby)
Vim で Ruby を書くための色々便利な機能が詰まったプラグインです．
オールインワンなプラグインがあまり好きでは無いため試していないですが，Vim の Ruby インターフェースを使って編集中のソースコードを部分的に実行しメソッドなどを取ってくる補完などがあるようです．ただし，rbenv などを使っている場合は Vim が使う Ruby と書いているソースを実際に実行する Ruby のバージョンがずれたりするため，注意が必要そうです．