IRB: Let's Use Autocomplete

IRBの最新の自動補完機能を誰よりも使ってるぺん(@tompng)です。
IRBの補完についてGoogleで検索すると `disable` `turn off` などと書かれた記事ばかりが出てくるのですが、今のIRBは自動補完の問題点がかなり解消しています。
無効化設定している人はいますぐ `~/.irbrc` を開いて `IRB.conf[:USE_AUTOCOMPLETE] = false` と書かれている行を消しましょう。

## 自動補完の問題点とどう解消されたか

### 補完ダイアログが大きくて邪魔・入力行が上にずれる
ターミナルの高さとカーソルの位置に応じて、補完ダイアログの表示サイズを調整するようになりました。
https://github.com/ruby/reline/pull/542
![dialog_height.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16596/82a95e27-b8d6-a730-23ce-a82eaf7d6d3c.png)


### 色が見づらい
見た目をカスタマイズするAPI `Reline::Face` が導入されました。([ドキュメント](https://github.com/ruby/reline/blob/master/doc/reline/face.md))
https://github.com/ruby/reline/pull/552
![face.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16596/17bbce0b-7f48-5c68-fa81-1bd4ed456ffb.png)



こちらは僕の設定(デフォルトのシアンに少し変更を加えたもの)
```ruby
Reline::Face.config(:completion_dialog) do |face|
  face.define :default, foreground: '#222222', background: :cyan
  face.define :enhanced, foreground: '#ffffff', background: :magenta, style: :bold
  face.define :scrollbar, foreground: '#444444', background: '#0088aa'
end
```

カスタマイズしていない状態のIRBのデフォルトも見やすいものに変わるといいですね。

### 表示が崩れる
いくつかの不具合は修正済みです
補完を使いながらメソッドチェインを書くと補完ダイアログに穴が開く
https://github.com/ruby/reline/pull/492
ダイアログの消去と再描画の方法を変えて修正

ターミナルの表示行数よりも多い行数を入力すると、特別な操作をしなくても表示がめちゃくちゃになりやすい
https://github.com/ruby/reline/pull/614
ダイアログに限らず画面全体のレンダリングを全て書き直して修正されました。Reline 0.5.0.pre.1 で試せます。

ターミナル上で幅が2の文字のちょうど境界線上に補完ダイアログを表示させると表示が崩れる
https://github.com/ruby/reline/pull/519
これはまだ途中

### 補完が遅い
原因は3つありました。
- メソッドチェインすると正しくメソッド補完を出せないので、仕方がなく全てのクラスの全てのメソッドを補完候補に出していた。
- `:`を入力した時点で`Symbol.all_symbols`を補完候補に出している。補完候補数が多すぎる。
- 補完候補が多い場合に補完ダイアログの表示幅の計算に時間がかかる

https://github.com/ruby/irb/pull/529
一番の原因である、全メソッド列挙をやめました。

https://github.com/ruby/irb/pull/534
Symbol名の補完では、`:` の後ろに最低一文字入力するまでは候補を表示しないようにしました。

この二つの修正により、補完候補が減って補完ダイアログの表示幅の計算処理も軽くなります。
表示幅計算の高速化(計算結果のキャッシュ)まではやる必要はなさそうなのでしていません。

なお、Symbol数が非常に多い場合はSymbol.all_symbolsが多少時間かかる・最初の一文字によってはSymbol数の候補がそこまで減らずに少し待たされることがあります。

### Backspaceなどのキー入力が効かなくなる
標準入出力のrawモードとcookedモードを頻繁に切り替えていたことと、補完が遅いことの組み合わせで起きていました。
rawモードはキーを押した瞬間に入力が送信されるモードで、cookedモードはenterを押して初めて一行分が送信されるモードです。
cookedモードだとbackspaceが送られないのですが、補完に時間がかかるとその間ずっとcookedモードのままになっていました。
rawとcookedの頻繁な切り替え自体が不要なのでやめています。
https://github.com/ruby/reline/pull/474
なお、pull request作成時点ではまだこの修正がbackspace問題の原因だという事には気づいていないようです。

### リモートでIRBを使うと非常に重い
Rails production だと定義されているメソッド数もシンボルの数も非常に多いこと、リモートなのでラグがあることから、補完が遅い問題とキー入力が効かない問題が特に顕著に出ていました。
この現象から、通信が圧迫されていて重いと誤解されていたりもしたようです。

### 補完の精度が悪くて役に立たない
IRB 1.9.0から型情報を使った補完が実験的に入りました。
IRB 1.10.0では型補完機能がGem `repl_type_completor` [ruby/repl_type_completor](https://github.com/ruby/repl_type_completor/) に切り出されました。
この型補完はなかなか強力で、メソッドチェイン、ブロックパラーメータなどに対しても補完が効きます。

![completion1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16596/2d6e3b30-74f4-8929-62b4-575a218c92ad.png)
![completion2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16596/15a7eae7-be12-8ae7-96dc-5629f9d215d8.png)


同じ `has_` のメソッド補完でも、書いた場所によって適切な補完が出ている例
![class_methods.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16596/5a331a07-8984-c4ba-79b7-491fe4f03ba0.png)
![instance_methods.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16596/ceb8b60b-cd5a-1f7c-f2cd-7635d554f614.png)


`gem repl_type_completor` をインストールし、以下のいずれかの方法で有効化できます

`~/.irbrc` に `IRB.conf[:COMPLETOR] = :type` を書く
`irb --type-completor` でIRBを立ち上げる
環境変数 `IRB_COMPLETOR=type` を設定する(Rails consoleなどを想定)


近いうちにキーワード引数名なども補完できるようになる予定です。

![kwargs.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16596/4cd6d9a4-4477-a759-80ed-297e095a2ea4.png)

## まとめ
- 自動補完を使うデメリットはかなり解消された
- `gem install repl_type_completor`
- `IRB.conf[:USE_AUTOCOMPLETE]=false` を消して `IRB.conf[:COMPLETOR]=:type` を使おう