Skip to main content

Vim

Goal

Vim setup to view Codee checks as editor diagnostics.

vim

Prerequisites

Ensure you have:

  • Codee installed on your system.
  • A compile_commands.json compilation database (You can check the Basic Workflow)
  • Vim >= 8.0, basic familiarity with how to configure it and filetype on set so that C, C++ and Fortran file types are autodetected

Install ALE

To easily display Codee checkers in VIM, install the ALE extension using its installation instructions.

Configure ALE for Codee

Add the following configuration to your .vimrc Vim configuration file:

let g:ale_codee_executable = 'codee'
let g:ale_codee_checks_options = 'checks --json'

" Register Codee for C, C++, and Fortran files
let g:ale_linters = {
\ 'c': ['codee'],
\ 'cpp': ['codee'],
\ 'fortran': ['codee'],
\}

" Function to parse severity levels
function! s:ParseSeverity(checkid) abort
if a:checkid =~# '^RMK\d\{3}'
return 'I'
elseif a:checkid =~# '^PWR\d\{3}'
return 'W'
elseif a:checkid =~# '^PWD\d\{3}'
return 'E'
endif
return 'W'
endfunction

" Function to parse location (line:column)
function! s:ParseLocation(location) abort
let l:matches = matchlist(a:location, '\(.*\):\(\d\+\):\(\d\+\)$')
if empty(l:matches)
return {'line': 0, 'column': 0}
endif
return {
\ 'line': str2nr(l:matches[2]),
\ 'column': str2nr(l:matches[3])
\}
endfunction

" Define the Codee output handler for ALE
function! HandleCodeeOutput(buffer, lines) abort
if empty(a:lines)
return []
endif

" Join the lines and parse JSON
let l:output = join(a:lines, '')
let l:json_data = json_decode(l:output)

if type(l:json_data) != v:t_dict || !has_key(l:json_data, 'Checks')
return []
endif

let l:diagnostics = []

for l:check in l:json_data.Checks
let l:location = s:ParseLocation(l:check.Location)
if l:location.line > 0
call add(l:diagnostics, {
\ 'lnum': l:location.line,
\ 'col': l:location.column,
\ 'end_col': l:location.column,
\ 'text': l:check.Title . ' - ' . l:check.Suggestion,
\ 'type': s:ParseSeverity(l:check.Check),
\ 'code': l:check.Check,
\})
endif
endfor

return l:diagnostics
endfunction

" Define the Codee linter configuration
call ale#linter#Define('c', {
\ 'name': 'codee',
\ 'executable': g:ale_codee_executable,
\ 'command': g:ale_codee_executable . ' ' . g:ale_codee_checks_options . ' %s',
\ 'callback': 'HandleCodeeOutput',
\ 'output_stream': 'stdout',
\ 'lint_file': 1,
\})

" Define the same linter for C++ and Fortran
call ale#linter#Define('cpp', {
\ 'name': 'codee',
\ 'executable': g:ale_codee_executable,
\ 'command': g:ale_codee_executable . ' ' . g:ale_codee_checks_options . ' %s',
\ 'callback': 'HandleCodeeOutput',
\ 'output_stream': 'stdout',
\ 'lint_file': 1,
\})

call ale#linter#Define('fortran', {
\ 'name': 'codee',
\ 'executable': g:ale_codee_executable,
\ 'command': g:ale_codee_executable . ' ' . g:ale_codee_checks_options . ' %s',
\ 'callback': 'HandleCodeeOutput',
\ 'output_stream': 'stdout',
\ 'lint_file': 1,
\})

" Enable ALE to run on file save and when leaving insert mode
let g:ale_lint_on_text_changed = 'never'
let g:ale_lint_on_insert_leave = 1
let g:ale_lint_on_enter = 1
let g:ale_lint_on_save = 1

You can navigate between checkers with :ALENext and :ALEPrev. You can display more information about a particular checker with :ALEDetail.