Vim
C++
lint
ale

Vimの非同期文法チェッカALEにプロジェクト固有の情報を教える

はじめに

Vimの非同期文法チェックエンジン、ALE (Asynchronous Lint Engine)に、プロジェクト固有の情報を教えたいことがある。典型的なのがC/C++のヘッダのインクルードパスで、makefileで-Iで場所を教えていたりすると、ALEから呼ばれたgccclangがそのパスを探せずにエラーを報告してしまう。これを解決するには以下のようにすれば良い。

  1. .vimrcを修正して、カレントディレクトリに.vimrc.localがあったら読むようにする
  2. ALEに追加情報が必要な場合はそこに.vimrc.localを作って、その中に情報を書く
  3. 例えばC/C++のインクルードパスを教えるにはg:ale_cpp_clang_optionsg:ale_cpp_gcc_optionsに"-std=c++14 -Wall -Ipath/to/header"を指定する

状況

あるプログラムが参照するヘッダのインクルードパスが、コンパイル時に-Iオプションで指定されているものとする。

例えばこんな状況を考える。

project
├── includes/
│   └── hoge.hpp
└── src/
    └── test.cpp

test.cppの中身はこんな感じ。

test.cpp
#include <hoge.hpp>

もちろん、makefileには-Iで適切にヘッダファイルの場所を教えているから、問題なくコンパイルできる。

しかし、このsrc/test.cppをALEを有効にした状態のVimで編集すると、「hoge.hppが見つからないよ」と怒られてしまう。

image.png

これはALEから呼び出されるclang++g++には-Iオプションが渡されていないのでヘッダが探せないため。

解決法

直接解決するには、g:ale_cpp_clang_optionsg:ale_cpp_gcc_optionsにヘッダの場所を教えてやれば良い。デフォルト値は-std=c++14 -Wallになっているので、今回の場合は

let g:ale_cpp_clang_options = "-std=c++14 -Wall -I../includes"
let g:ale_cpp_gcc_options = "-std=c++14 -Wall -I../includes"

とやってやれば、この警告は消える。しかし、毎回Vimを起動する度に上記の設定をするのは面倒。なのでVimでプロジェクト固有の設定を適用するを参考に、まず.vimrc

~/.vimrc
augroup vimrc-local
  autocmd!
  autocmd BufNewFile,BufReadPost * call s:vimrc_local(expand('<afile>:p:h'))
augroup END

function! s:vimrc_local(loc)
  let files = findfile('.vimrc.local', escape(a:loc, ' ') . ';', -1)
  for i in reverse(filter(files, 'filereadable(v:val)'))
    source `=i`
  endfor
endfunction

と書いて、もしカレントディレクトリに.vimrc.localがあったら読み込むようにする。

その上で、先程のtest.cppと同じディレクトリに

.vimrc.local
let g:ale_cpp_clang_options = "-std=c++14 -Wall -I../includes"
let g:ale_cpp_gcc_options = "-std=c++14 -Wall -I../includes"

というファイルを作ってやればよい。ファイル構成はこんな感じになる。

project
├── includes/
│   └── hoge.hpp
└── src/
    ├── .vimrc.local
    └── test.cpp

この状況でtest.cppをVimで開いても、「ヘッダが見つからない」とは怒られない。

まとめ

ALEにプロジェクト固有の情報を伝える方法をまとめた。「C/C++のヘッダは面倒だよね」という話はALEのissueにもなってて、作者も「100%の解決策はないよね〜」みたいなことを書いている。また、冒頭に書いたように本家のFAQに「vimrc-localを使え」と書いてあるんだけれど、僕のようなVim初心者にはそれだけの情報ではきつかった。

参考