syntasticでシステムではなくローカルの実行ファイルを動かす

  • 1
    Like
  • 3
    Comment

syntasitic を使って自動チェックを行うには、 vim から Rubocop や eslint などを実行する必要があるので、よくシステム全体にツールをインストールしたりする。(:warning: 後述するように eslint はグローバルにインストールしてはいけないらしい)

npm install -g eslint

しかし、これだと全てのプロジェクトで同じバージョンの eslint を使わなければならないし、プロジェクトで使っているバージョンが変わるたびにシステムに入っているパッケージもこうしなければならず DRY ではない。どうにかしてプロジェクトローカルのバージョンを使いたい。

この課題には2つの対応策がある。

環境変数を設定する

一番簡単な方法は、プロジェクトでインストールした実行ファイルを使えるように PATH を設定することだ。

こういうディレクトリ固有の環境変数を管理するには direnv を使うのが楽だろう。 direnv をインストールしたあと、プロジェクトルートに次のような .envrc ファイルを作る

.env
export PATH="$(npm bin):$PATH"

この状態で起動した vim は PATHnpm bin を含むので、 eslint を実行することができる。

この方法のいいところは、 syntastic に限らず様々なツールを一括で設定できることだ。その一方で、1つの vim の中で複数のプロジェクトを横断してファイルを編集したりすると、 vim を起動したプロジェクト以外の場所にあるファイルのチェックがうまくいかなくなってしまう。そういう状況がありうる場合は、次の都度設定する方法を取らなければならない。

都度設定する

syntastic は変数で簡単に言語ごとの設定ができるが、バッファ変数を使ってバッファごとに挙動を変えることができる。実行ファイルのパスを指定するには b:syntastic_<filetype>_<checker>_exec を使う。

augroup SyntasticConfig
  au!
  au FileType javascript call s:syntastic_javascript_settings()
augroup END

function! s:syntastic_javascript_settings()
  if executable('npm')
    let bin_path = systemlist('npm bin')[0] . '/eslint'
    if executable(bin_path)
      let b:syntastic_javascript_eslint_exec = bin_path
    endif
  endif
endfunction

このスクリプトは javascript ファイルを開くたびに npm で eslint がインストールされているか調べ、インストールされて入ればそれ使うようにする。なければシステムの eslint にフォールバックする。こうすることで、各 javascript ごとに正しい eslint を使うことができるようになる。

eslint 固有の解決方法

@mysticatea さんのコメントで知ったが eslint に限っては eslint-cli というツールをグローバルインストールすることで解決できる。 eslint-cli をインストールするとファイルごとに適切な eslint を実行する eslint コマンドがインストールされるようだ。

Note:
- The eslint module must not be installed into global.
- This module must be installed into global.

とのこと。