VimでESLintとFlowを使うためにNeomakeからALEに乗り換える

## はじめに

[[Vim]SyntasticによるESLintチェックが遅いのでNeomakeに乗り換えた - dackdive's blog](http://dackdive.hateblo.jp/entry/2016/10/24/095000)
ここで書いたように ESLint を Syntastic で実行するのはちょっと重いなというのがあって
[Neomake](https://github.com/neomake/neomake) という非同期で lint チェックできるプラグインに乗り換えた。

それからしばらくして [Flow](https://flowtype.org/) を触り始めたのだが、
ESLint と Flow を同時に使おうとすると Neomake では色々問題があったので
[ALE](https://github.com/w0rp/ale) という別のプラグインを使うことになった。

## 最初にまとめ

* 以下を満たすのは Neomake では無理で、ALE では可能だった
    * ESLint・Flow のどちらか一方がインストールしたプロジェクトでも問題なく使える
    * 現在編集中のファイルに対してだけチェックをかけることができる
    * 軽い（非同期で実行される）
* ALE はインストールすれば特に設定せず使えた。ESLint や Flow のグローバルインストールも不要
* ステータスラインに lint 結果表示したりできて便利


## Neomake で Flow を使ったときの問題点

元々、ESLint だけを使っていたときの `.vimrc` の設定はこのようになっていた（[参考](http://dackdive.hateblo.jp/entry/2016/10/24/095000)）。

```vim:.vimrc
call dein#add('neomake/neomake')
call dein#add('benjie/neomake-local-eslint.vim')

autocmd! BufWritePost * Neomake
let g:neomake_javascript_enabled_makers = ['eslint']
```

そして今回 Flow を使うにあたって

```vim
let g:neomake_javascript_enabled_makers = ['eslint', 'flow']
```

というように単純に `g:neomake_javascript_enabled_makers` に `flow` を追加した。
その状態で Neomake から Flow を実行したところ、以下のようになった。
（その前に Neomake のバージョンが古くて変なエラーにハマった（[参考](http://dackdive.hateblo.jp/entry/2017/01/21/152905)））

![SS_2017-01-21_15_00_40.png](https://qiita-image-store.s3.amazonaws.com/0/36518/8221351e-d6ff-8224-4945-8c30d192d150.png)

一応編集中のファイルにはエラー行に Sign が出ているし、その行に移動した際にメッセージは表示される。
が、location list（キャプチャ赤枠部分）を見るといくつか問題がある。

### 問題1. command not found: eslint が出ている

キャプチャは Flow の [getting-started](https://flowtype.org/docs/getting-started.html) を勉強し始めたときのもので、
このときプロジェクトには ESLint はインストールしていない。

「プロジェクトに `eslint` コマンドがあれば `g:neomake_javascript_enabled_makers` に追加する」みたいなことを `.vimrc` 側でやればいいんだろうけど今のところうまくいってなくて、
できればプロジェクトにインストールされている linter だけが使われるようプラグイン側でよきに計らってほしい。


### 問題2. 現在編集中のファイル以外の結果も表示されている

キャプチャはプロジェクト直下の `01_hello.js` というファイルを編集しているときに lint を実行したのだが
プロジェクト内の `examples/` ディレクトリに存在するファイルの結果まで表示されてしまっている。


### 問題3. エラーメッセージのフォーマットが崩れている

```
examples/02_TypeAnnotations/type_annotations.js|4 col 10 error| number This type is incompatible with the expected return type of
examples/02_TypeAnnotations/type_annotations.js|3 col 37 error| string
```

とか、おそらくエラーとしては1つですよね。あと変な改行入ってんのも気になる。

実はこの問題自体は Issue として挙げられていて、
[Flow error format issue · Issue #477 · neomake/neomake](https://github.com/neomake/neomake/issues/477)
かつそれを解決するための [flow-vim-quickfix](https://github.com/ryyppy/flow-vim-quickfix) というプラグインも公開されている。

が、依然として問題2は解決できなかったので諦めた。

## 上記の問題を解決するための、ALE というプラグイン

というわけでどうにかならないか模索した結果、以前 Neomake についてブログに書いたときの [はてブコメント](http://b.hatena.ne.jp/entry/dackdive.hateblo.jp/entry/2016/10/24/095000) で知った ALE というプラグインに乗り換えることにした。

[w0rp/ale: Asynchronous Lint Engine](https://github.com/w0rp/ale)

サポートしている lint ツールの一覧は [README](https://github.com/w0rp/ale#supported-languages) に記載されている。
インストールは dein.vim の場合

```vim:.vimrc
call dein#add('w0rp/ale')
```

で OK。

ESLint も Flow も、グローバルインストールされたものを使うよう設定することもできるが
基本的にはプロジェクトにローカルインストールされたものを自動で使うようになっている。
インストールされていない場合はその linter についてのチェックは行われないようなので、location list に変な行が表示されることもない。

## ALE をさらに便利にカスタマイズする

というわけでインストールしてちょっと触ってみただけだが、今のところ問題なさそうなのでこれからは ALE を使うことにする。
最後に ALE をより便利にするためちょっとしたカスタマイズを行う。

### ステータスラインに lint 結果を表示する

（参考：https://github.com/w0rp/ale#4iv-how-can-i-show-errors-or-warnings-in-my-statusline）

ステータスラインに

```vim
%{ALEGetStatusLine()}
```

を追加すると、「Error ◯件、Warning ×件」という結果を表示しておくことができる。
フォーマットは `g:ale_statusline_format` で指定する。

```vim
let g:ale_statusline_format = ['⨉ %d', '⚠ %d', '⬥ ok']
```

この場合の見た目はこんな感じになるらしい。

![SS 2017-01-21 19.03.48.png](https://qiita-image-store.s3.amazonaws.com/0/36518/06abbf08-39d7-f438-2b07-191b5dcb0b01.png)

（README より）

私は

```vim:.vimrc
let g:ale_statusline_format = ['E%d', 'W%d', '']
```

とした。

また、ステータスラインには [lightline.vim](https://github.com/itchyny/lightline.vim) を使っており、その場合は以下のような設定になる。

```vim:.vimrc
call dein#add('itchyny/lightline.vim')
let g:lightline = {
  \'active': {
  \  'left': [
  \    ['mode', 'paste'],
  \    ['readonly', 'filename', 'modified'],
  \    ['ale'],
  \  ]
  \},
  \'component_function': {
  \  'ale': 'ALEStatus'
  \}
\ }

function! ALEStatus()
  return ALEGetStatusLine()
endfunction
```

結果。Error 2件、Warning 1件あるのがすぐわかって便利（色変えたい...！）
![SS 2017-01-21 19.13.30.png](https://qiita-image-store.s3.amazonaws.com/0/36518/7c253112-5490-b846-74c3-5bc5b9e11c91.png)

（設定に関しては作者のこちらの記事が参考になった。
[作者が教える！ lightline.vimの設定方法！ 〜 中級編 - 展開コンポーネントを理解しよう - プログラムモグモグ](http://itchyny.hatenablog.com/entry/20130918/1379461406)）

### エラー行にショートカットキーでジャンプする

（参考：https://github.com/w0rp/ale#4vii-how-can-i-navigate-between-errors-quickly）

`<Plug>(ale_previous_wrap)` および `<Plug>(ale_next_wrap)` を適切なキーに割り当てることで
前後のエラー行にショートカットキーでジャンプすることができる。

```vim:.vimrc
nmap <silent> <C-w>j <Plug>(ale_next_wrap)
nmap <silent> <C-w>k <Plug>(ale_previous_wrap)
```

私は `Ctrl-j` `Ctrl-k` をウィンドウの移動に割り当ててしまっているので、`Ctrl-w + j/k` とした。

### エラーメッセージのフォーマットを変更する

（参考：https://github.com/w0rp/ale#4v-how-can-i-change-the-format-for-echo-messages）

`g:ale_echo_msg_format` でエラーフォーマットをカスタマイズできる。
フォーマットには

* `%s`：エラーメッセージ本体
* `%linter%`：linter 名
* `%severity`：エラーレベル（Error/Warning）
    * それぞれのレベルで表示する文字列は `g:ale_echo_msg_error_str`, `g:ale_echo_msg_warning_str` で設定可能

私は

```vim:.vimrc
let g:ale_echo_msg_format = '[%linter%] %s'
```

のように linter 名だけ表示するようにした。

```zsh
# before
Missing trailing comma. [Error/comma-dangle]

# after
[eslint] Missing trailing comma. [Error/comma-dangle]
```

## TODO

[flowtype/vim-flow: A vim plugin for Flow](https://github.com/flowtype/vim-flow)

公式のプラグインは全然触ってなかった。
lint はもう問題ないけど omnifunc による補完とかが気になる。

## （2017/01/27追記）

ある日突然 ALE が動かなくなったので調べてみたところ、Node.js のバージョン管理に [nodebrew](https://github.com/hokaccha/nodebrew) を導入したことが原因だった。

[Vim + Syntastic + eslint が動かないのはPATHをzshrcに書いていたのが原因だった - Qiita](http://qiita.com/ktrysmt/items/4d8194b0f82bfa91bcdc)
にあるように、nodebrew の `PATH` を `.zshrc` でなく `.zshenv` に記載すると元通り動いた。

```zsh:~/.zshenv
# nodebrew
export PATH=$HOME/.nodebrew/current/bin:$PATH
```