Vim
flow
ESLint

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

More than 1 year has passed since last update.

はじめに

[Vim]SyntasticによるESLintチェックが遅いのでNeomakeに乗り換えた - dackdive's blog
ここで書いたように ESLint を Syntastic で実行するのはちょっと重いなというのがあって
Neomake という非同期で lint チェックできるプラグインに乗り換えた。

それからしばらくして Flow を触り始めたのだが、
ESLint と Flow を同時に使おうとすると Neomake では色々問題があったので
ALE という別のプラグインを使うことになった。

最初にまとめ

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

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

元々、ESLint だけを使っていたときの .vimrc の設定はこのようになっていた(参考)。

.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 を使うにあたって

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

というように単純に g:neomake_javascript_enabled_makersflow を追加した。
その状態で Neomake から Flow を実行したところ、以下のようになった。
(その前に Neomake のバージョンが古くて変なエラーにハマった(参考))

SS_2017-01-21_15_00_40.png

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

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

キャプチャは Flow の getting-started を勉強し始めたときのもので、
このときプロジェクトには 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
かつそれを解決するための flow-vim-quickfix というプラグインも公開されている。

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

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

というわけでどうにかならないか模索した結果、以前 Neomake についてブログに書いたときの はてブコメント で知った ALE というプラグインに乗り換えることにした。

w0rp/ale: Asynchronous Lint Engine

サポートしている lint ツールの一覧は README に記載されている。
インストールは dein.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)

ステータスラインに

%{ALEGetStatusLine()}

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

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

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

SS 2017-01-21 19.03.48.png

(README より)

私は

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

とした。

また、ステータスラインには lightline.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

(設定に関しては作者のこちらの記事が参考になった。
作者が教える! lightline.vimの設定方法! 〜 中級編 - 展開コンポーネントを理解しよう - プログラムモグモグ

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

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

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

.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 で設定可能

私は

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

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

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

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

TODO

flowtype/vim-flow: A vim plugin for Flow

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

(2017/01/27追記)

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

Vim + Syntastic + eslint が動かないのはPATHをzshrcに書いていたのが原因だった - Qiita
にあるように、nodebrew の PATH.zshrc でなく .zshenv に記載すると元通り動いた。

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