People’s vim setups tend to be very individual: some are rejecting most of the features over vi or even ed while others turn the dial to eleven and build their very own IDE. Both have their pros and cons – I tend to be somewhere in the middle with a tendency to the more purist experience.
As I worked a lot on C and C++ in recent years, I started to enjoy the
Asynchronous Lint Engine (ALE) vim
plugin. It calls clang
, clang-tidy
, clang-check
, etc. in the background and
inserts hints these linters output into the vim buffer. These work pretty well,
but require some setup to work properly. To hand clang and friends the correct
compiler flags, it relied on hacks like a project-local vimrc file.
If you’re using CMake for your projects, the whole experience can be very smooth. The setup includes:
- clangd: a Clang-based server implementing the Language Server Protocol (LSP)
- CMake: a build system that can generate a compilation database. The compilation database contains all the arguments passed to the compiler.
- compdb (optional but trivial to install): a Python tool to add header files to the compilation database.
- ALE: a (neo)vim plugin that interfaces with clangd (or any server implementing LSP).
The configuration in is rather simple. Install the software as
described in their documentation. Then, enable the generation of the
compilation database in your CMakeLists.txt
if you haven’t already.
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
Next, tell vim to use the clangd
linter for C (or C++):
" ~/.vim/ftplugin/c.vim
let b:ale_linters = ['clangd']
" parse the compile_commands.json database
let g:ale_c_parse_compile_commands = 1
" enable clangd-based go to definition with <C-X><C-O>
set omnifunc=ale#completion#OmniFunc
Because CMake usually uses out-of-source builds, link the compile_commands.json
to your projects source:
$ cd $PROJECT_ROOT && ln -s $BUILD_DIR/compile_commands.json
Alternatively, if you want support for clangd when editing your header files, you can use compdb for that:
$ compdb -p $BUILD_DIR list > $PROJECT_ROOT/compile_commands.json
This has to be done manually but could be added to the build process.