openFrameworks / Nvim / Arch Linux
Published on: 2020-02-07
Lately I have had to get into C++ programming in order to do some live analysis of our MiniBees. We also want to start working with live visuals in our performances as well, so last year I got a hold of a second-hand Kinect, and the last couple of weeks I've been playing around with this in oF, a C++ version of the excellent java-based graphics programming environment Processing.
I have spent a lot of time tweaking my preferred coding environment, which is based on the text editor neovim, a modern fork of vim, so I wanted to keep using this for my C++ coding as well. Turns out this is not too hard!
Installing openFrameworks on Arch Linux
In order to get oF to work in Arch Linux you need to follow
this guide. It's all
pretty straightforward: download the repository to your computer and put
it in a reasonable location, run a couple of scripts, and off you go!
The first script you need to run is
$OF_ROOT/scripts/linux/archlinux/install_dependencies.sh. This is a
wrapper script for pacman that will download and install all the
necessary dependencies. After this you probably want to run
$OF_ROOT/scripts/linux/compileOF.sh. This will compile all the
libraries you need. Finally, you probably want to use the
projectGenerator to create new projects, so run
$OF_ROOT/scripts/linux/compilePG.sh as well.
The oF developers do not officially support the AUR package. Sticking with the official method of installation makes it easier to juggle different versions of oF later on.
Set up Neovim
In order to get an ergonomic environment set up, I use a couple of
plugins: a.vim and vim-gutentags. I don't use YouCompleteMe or any
such thing, as I find nvims omnicomplete function sufficient for my
needs. Use your favorite plugin manager to install these. I use
vim-plug:
Plug 'ludovicchabant/vim-gutentags' Plug 'vim-scripts/a.vim'
Autocompletion
To get autocompletion (somehow) working for oF, you need to tweak
gutentags a little bit. The plugin uses some default markers (the
presence of .git, for example) to define the root of a project. Setting
up the entire oF tree as one git project would be total overkill and
defeat the whole purpose of this kind of framework, so it is easier and
better to disable gutentags' defaults and add your own. In
$XDG_CONFIG_HOME/nvim/init.vim add these lines:
let g:gutentags_project_root = ['.gutctags'] let g:gutentags_add_default_project_roots = 0
Next, add the .gutctags file to the oF root folder:
$ touch $OF_ROOT/.gutctags
Now, whenever you do anything in your oF tree, gutentags will quietly fill up a tag file with anything you need for nvim's omnicomplete to work as expected.
The one downside to this approach is that your tag file does indeed
fill up with EVERYTHING, so every little typo you made or other apps you
wrote in the same oF tree become food for the tag generator. I don't
have a good solution for this yet.
[EDIT, 19 April 2020] In the meanwhile, my good friend Mads Kjeldgaard
has gone through the trouble of setting up
YouCompleteMe with
openFrameworks, and has described the process in his
blog.
He's also describing a better way of dealing with ctags.
[EDIT, 29 August 2020] After a bit of an openFrameworks hiatus, I am now getting back into it again, and have picked up a thing or two about the Language Server Protocol, an editor-agnostic way to deal with autocompletion, debugging, linting, tagging and so on. In order to make this work in neovim you need to install a couple of plugins:
Plug 'autozimu/LanguageClient-neovim', {
\ 'branch': 'next',
\ 'do': 'bash install.sh',
\ }
Plug 'Shougo/deoplete.nvim', { 'do': ':UpdateRemotePlugins' }
Install ccls, a language server for the C language family:
sudo pacman -S ccls
Use your favorite AUR installation method to get hold of compiledb:
yay -S compiledb
Configure LanguageClient-neovim in your init.vim:
let g:LanguageClient_serverCommands = {
\ 'cpp': ['ccls', '--log-file=/tmp/cc.log'],
\ }
function LC_maps()
if has_key(g:LanguageClient_serverCommands, &filetype)
nnoremap <buffer> <silent> K :call LanguageClient#textDocument_hover()<cr>
nnoremap <buffer> <silent> gd :call LanguageClient#textDocument_definition()<CR>
nnoremap <buffer> <silent> <F2> :call LanguageClient#textDocument_rename()<CR>
endif
endfunction
autocmd FileType * call LC_maps()
We will need to generate a database. Go to the root directory of your project and create it like this:
cd ~/openFrameworks/apps/myExcellentApp
compiledb -n make
Finally we will generate the tags file for the entire openFrameworks
tree locally. I experimented with a few different approaches, but this
seems to work. Assuming that we are in the myExcellentApp directory,
run this command:
ctags -R ~/openFrameworks/*
This will take a little while. In my case it generated roughly 42.000 tags. But now you should be able to go to any class definition by hitting Ctrl-]
Make Make Work
Coming from an interpreted language like SuperCollider to a compiled
language like C++ is a bit painful, but with a couple of tweaks to nvim
the transition can be smoother. This is where nvim's excellent
terminal capabilities enter into the picture. Add these lines to your
init.vim:
augroup c
autocmd!
autocmd FileType c,cpp,h,hpp,glsl call MakeRun()
augroup end
function! MakeRun()
nnoremap <C-e> :terminal make -j8 && make run<cr>
inoremap <C-e> <esc>:terminal make -j8 && make run<cr>
endfunction
This will make nvim behave in a similar way to the scnvim plugin that
I use for SuperCollider development. Whenever I'm in a source file I can
hit ctrl-E, and a terminal window will open up, compile the project and
then run it. Very sweet indeed.