Rubyの開発環境を整え、今後に備える(NeoVim,dein入門)

# 概要
割と最近Rubyに入門するようになりVSCodeでコーディングしていましたが、使い勝手悪いなーと思う箇所がいくつかありVimに乗り換えました。
[ALE](https://github.com/w0rp/ale)(Asynchronous Lint Engine)という良さげなSyntaxCheckerを途中で使いたくなったのですが、NeoVimかVim 8を想定したPluginであった為deinを導入してからNVimに乗り換えています。
今回は下記のような流れで開発環境を整えるまでを説明します。
1. NeoVim導入
2. dein導入
3. deinでPluginを管理する
    3-1. dein.tomlでPluginを設定してみる(ALE、lightline導入)
    3-2. dein_lazy.tomlでPluginを設定してみる(vim-endwise導入)
4. 補足(覚え書き)
5. 参照

## この記事で目指す所
NeoVimとdeinを導入して、今後何か自分で入れたいPluginを出てきたときにも自分で対応できる様になる。

# 1. NeoVim導入
https://neovim.io/
最初はvimにそのままPluginを足していけばいいやと思っていましたが、NeoVimを想定したPluginが思った以上に多かったので環境構築中にNeoVimに切り替えました。
macOS/OS Xを利用している場合Homebrewを使って導入するのが一番簡単だと思います。
[Installing NeoVim macOS/OS X](https://github.com/neovim/neovim/wiki/Installing-Neovim#macos--os-x)

```
$ brew install neovim
```
その他の環境に関しても上記Githubをご確認頂ければ簡単に導入することができます。
terminalから`nvim`入力すると導入に成功していることが確認できるかと思います。
<img width="1053" alt="スクリーンショット 2018-03-11 12.28.08.png" src="https://qiita-image-store.s3.amazonaws.com/0/172190/e0609200-53ed-69f5-629a-20533c47228f.png">
NeoVimの設定ファイルはデフォルトだと`~/.config/nvim/init.vim`に配置するみたいです。
設定に関してはdeinを導入してから追加していきます。

# 2. dein導入

調べてみたところvimでのPlugin管理は[dein](https://github.com/Shougo/dein.vim)がを使うのがさそうだったので導入することにしました。
Install先の例として`"~/.vim/bundles" or "~/.cache/dein" or "~/.local/share/dein"`が挙げられていたので今回は`~/.cache/dein`にInstallしていきます。
## install

```
# 任意の場所にinstaller.shを落としてくる。
$ curl https://raw.githubusercontent.com/Shougo/dein.vim/master/bin/installer.sh > installer.sh
$ sh ./installer.sh ~/.cache/dein
```
installerが実行すると下記の様なコードが出力される。
`Please add the following settings for dein to the top of your vimrc (Vim) or init.vim (NeoVim) file:`
と出力されているので本来ならばコードをNeoVimの設定先`~/.config/nvim/init.vim`に追記するのですが、
すぐに肥大化してしまいそうだったので今のうちにファイルを分割しておきます。
## ファイルの分割
`~/.config/nvim/bundles`というディレクトリをきってPluginの設定等をまとめることにしました。
deinの設定は`bundles/dein`にまとめていきます。

```
$ mkdir -p ~/.config/nvim/bundles/dein
```
deinのinstallerを実行した際に下記のようなコードが出力されたかと思います。
(Requiredあたりとか見るとわかるようにinstallerの引数として渡したディレクトリが
書かれている箇所があるので、自身の環境で出力されたコードを利用すること。)

```
"dein Scripts-----------------------------
if &compatible
  set nocompatible               " Be iMproved
endif

" Required:
set runtimepath+=/Users/<username>/.cache/dein//repos/github.com/Shougo/dein.vim

" Required:
if dein#load_state('/Users/<username>/.cache/dein/')
  call dein#begin('/Users/<username>/.cache/dein/')

  " Let dein manage dein
  " Required:
  call dein#add('/Users/<username>/.cache/dein//repos/github.com/Shougo/dein.vim')

  " Add or remove your plugins here:
  call dein#add('Shougo/neosnippet.vim')
  call dein#add('Shougo/neosnippet-snippets')

  " You can specify revision/branch/tag.
  call dein#add('Shougo/deol.nvim', { 'rev': 'a1b5108fd' })

  " Required:
  call dein#end()
  call dein#save_state()
endif

" Required:
filetype plugin indent on
syntax enable

" If you want to install not installed plugins on startup.
"if dein#check_install()
"  call dein#install()
"endif

"End dein Scripts-------------------------

```
上記コードから必要な箇所を抜き出し、必要に合わせて追加で設定を`dein.vim`というファイルを作成し記述していきます。

```~/.config/nvim/bundles/dein/dein.vim
"dein Scripts-----------------------------
if &compatible
  set nocompatible               " Be iMproved
endif

let s:dein_dir = expand('~/.cache/dein')
let s:dein_repo_path = s:dein_dir . '/repos/github.com/Shougo/dein.vim'

"deinがinstallされてなければgit clone
if !isdirectory(s:dein_repo_path)
  execute '!git clone https://github.com/Shougo/dein.vim' s:dein_repo_path
endif
execute 'set runtimepath^=' . s:dein_repo_path

if dein#load_state(s:dein_dir)
  call dein#begin(s:dein_dir)

  let g:config_dir  = expand('~/.config/nvim/bundles/dein')
  let s:toml        = g:config_dir . '/dein.toml'
  let s:lazy_toml   = g:config_dir . '/dein_lazy.toml'

  " TOML 読み込み
  call dein#load_toml(s:toml,      {'lazy': 0})
  call dein#load_toml(s:lazy_toml, {'lazy': 1})

  call dein#end()
  call dein#save_state()
endif

" Required:
filetype plugin indent on

" If you want to install not installed plugins on startup.
if dein#check_install()
  call dein#install()
endif

"End dein Scripts-------------------------
```
上記設定に登場する`dein.toml`や`dein_lazy.toml`については次の「deinでPluginを管理する」で説明します。
上記ファイルを`dein.vim`に配置しただけではNeoVimが読み込んでくれないので`~/.config/nvim/init.vim`に
`dein.vim`を読み込ませるよう記述します。

```~/.config/nvim/init.vim
runtime! bundles/dein/dein.vim
```
以上でdeinの導入は完了です。
上記まででnvimを開けばdeinが自動でinstallされるようになっているので動作確認を行っていただいても問題ないです。
# 3. deinでPluginを管理する
deinでPluginを管理する際にはTOML形式でスッキリ書くことができるらしい。
## TOML
https://github.com/toml-lang/toml
TOMLの[Array of Tables](#aot)で下記のような形でPluginを記述していきます。

```
# https://github.com/Shougo/dein.vimをinstallする場合
[[plugins]]
 repo = 'Shougo/dein.vim'
```
上記はJsonで書くと下記の様な表現になります。

```
{
  "products": [
    { "repo": "Shougo/dein.vim"}
  ]
}
```
こちらの設定を`dein.toml`や`dein_lazy.toml`に記述していきます。
`dein.toml`には起動時毎度読み込む設定を記述し、`dein_lazy.toml`には特定の条件下で読み込む設定を記述します。
`dein.toml`には何も考えず前の項目で説明した記法でpluginを追加していけば問題ないです。

`dein_lazy.toml`に記述する内容の例を挙げるとすれば、rbファイルを編集する場合やpyファイルを編集する場合にのみ条件を絞り込み設定を読み込ませることができます。
まずは`dein.toml`に設定を記述していきます。
# 3-1. dein.tomlでPluginを設定してみる(ALE、lightline導入)
いよいよいい感じのSyntaxChecker[ALE](https://github.com/w0rp/ale)を入れてみます。
このままALEを入れてしまってもいいのですが、構文エラーがあった場合今のままだとメッセージが読みにくいです。
そこでステータスラインが見やすくなる[lightline.vim](https://github.com/itchyny/lightline.vim)も合わせて入れてみます。
今回はnvim起動時に毎回読み込んでほしい設定なので`dein.toml`に追記を行います。

```~/.config/nvim/bundles/dein/dein.toml
[[plugins]]
repo = 'Shougo/dein.vim'

# Syntax checker
[[plugins]]
repo = 'w0rp/ale'

# statusline plugin
[[plugins]]
repo = 'itchyny/lightline.vim'
```
nvimを起動する前にステータスラインを常時起動するように`init.vim`に設定を追記します。

```~/.config/nvim/init.vim
"" Statusline
set laststatus=2
```
これでnvimを起動するとインストールが始まり、いい感じのステータスラインが表示されるようになると思います。
<img width="1055" alt="スクリーンショット 2018-03-11 13.37.01.png" src="https://qiita-image-store.s3.amazonaws.com/0/172190/1b324850-5cce-2018-87aa-c49cb43014f3.png">
今の状態でもファイル編集時にSyntaxCheckerが走るようになりますが、今回はエラーと警告数をステータスラインに表示するよう設定を行います。
Plugin毎の設定はdeinのoption`hook_add`を使ってファイルを分離します。
設定ファイルは`~/.config/nvim/bundles/plugins`ディレクトリをきりファイルを追加していきます。  

```
# ディレクトリ作成
$ mkdir ~/.config/nvim/bundles/plugins
```

```~/.config/nvim/bundles/plugins/ale_settings.vim
let g:lightline = {
  \'active': {
  \  'left': [
  \    ['mode', 'paste'],
  \    ['readonly', 'filename', 'modified', 'ale'],
  \  ]
  \},
  \'component_function': {
  \  'ale': 'ALEGetStatusLine'
  \}
\ }
```
`add_hook`の設定を使い`ale_settings.vim`を読み込ませます。

```~/.config/nvim/bundles/dein/dein.toml
[[plugins]]
repo = 'Shougo/dein.vim'

# Syntax checker
[[plugins]]
repo = 'w0rp/ale'
hook_add = 'source ~/.config/nvim/bundles/plugins/ale_settings.vim'

# statusline plugin
[[plugins]]
repo = 'itchyny/lightline.vim'
```
以上でステータスラインにエラーと警告数が表示されるようになります。
# 3-2. dein_lazy.tomlでPluginを設定してみる(vim-endwise導入)
それでは最後にdein_lazyの説明をしたいと思います。
今回は説明を行うために[vim-endwise](https://github.com/tpope/vim-endwise)というrubyで`def`や`class`や`if`等を宣言したときにendを閉じてくれるPluginを導入してみます。
`dein_lazy.toml`を作成しPluginの設定を記述します。

```~/.config/nvim/bundles/dein/dein_lazy.toml
[[plugins]]
repo = 'tpope/vim-endwise'
on_ft = ['ruby']
```
ここで`on_ft`というOptionが登場します。
valueとしてListかString形式で[FileType](#filetype)を指定するとそのFileTypeを編集するときにのみ
Pluginを読み込んでくれるようです。
今回の場合はrbファイルを編集している場合に読み込ませたいのでvalueとしてrubyを設定します。
これでnvimを開くと`end`で勝手に閉じてくれるようになります。

ひとまずここまでdeinの書き方がわかれば今後何か新しいPluginを足したくなってもぱっと足せるじゃないかと思います。
Rubyを書くときに保管するPluginとかも本当は導入したかったのですが、結局どれを使うのが良さそうなのかわからなかったので良い物があれば教えていただけると嬉しいです。(Rsenseは開発が止まってるみたいだったので候補から外しました)

# 4. 補足(覚え書き)
## <a name="aot">Array of Tables</a>
https://github.com/toml-lang/toml#array-of-tables
何か書こうとしたけど忘れてしまいました。。
思い出したら書きます。

## <a name="filetype">filetype</a>
on_ftで指定できるrubyとかpythonとかってどこで定義されてるの？
バッファのFileType名を使っているみたい。
現在開いているFiletypeは

```
:echo &filetype
```
で確認することができる。
定義されているFileTypeの一覧は下記で確認可能
neovimを使っている場合は下記ディレクトリにあるファイル群
(/usr/local/Cellar/neovim/0.2.2_1/share/nvim/runtime/ftplugin)

```
 :echo glob($VIMRUNTIME . '/ftplugin/*.vim')
 :echo glob($VIMRUNTIME . '/indent/*.vim')
 :echo glob($VIMRUNTIME . '/syntax/*.vim')
```

拾いミスしてなければ210種類定義されてました。
設定したいFileType名でうまく設定できなければ上記で定義されているか確認するのがよさそうです。
ちなみに新たなFileTypeを定義することもできるようです。
[[vim] 新たなfiletypeを定義する](https://qiita.com/ntakahashi/items/3f441dc10e81d7ceb8fe)

# 参照
[Vimメモ : filetypeの確認](https://wonderwall.hatenablog.com/entry/2016/03/20/222308)
[Vimメモ : ALE(Asynchronous Lint Engine)で非同期コードチェック](https://wonderwall.hatenablog.com/entry/2017/03/01/223934)