nathangrigg / vim-beancount

Vim ftplugin for beancount
161 stars 41 forks source link

Syntax checker should respect beancount_root variable #35

Open wzyboy opened 7 years ago

wzyboy commented 7 years ago

A year ago @yegle added syntax checker feature to vim-beancount (https://github.com/nathangrigg/vim-beancount/pull/8). It suddenly occurred to me that this syntax checker does not respect beancount_root variable. That is to say, if you split your leger into multiple files, that single bean-check command has no way to find all account names, leading to "Invalid account references" errors.

Since I am a n00b to VimL. Could you help?

yegle commented 7 years ago

I'm a noob on VimL too. But I suspect you can workaround this issue by including necessary file (in your case, the file that contains all open directives) in all your ledger files.

This won't work if you don't have a separate file containing all your open directives.

jonsmithers commented 4 years ago

I fixed this for the ALE linter with some changes to my vimrc. Maybe I should put together a pull request.

augroup vimrc_beancount
  au!
  autocmd FileType beancount let b:beancount_root='main.beancount'

  " override ALE linter definition from nathangrigg/vim-beancount
  autocmd FileType beancount call ale#linter#PreventLoading('beancount')
  autocmd FileType beancount call ale#linter#Define('beancount', {
        \   'name': 'bean_check',
        \   'output_stream': 'stderr',
        \   'executable': 'bean-check',
        \   'command': 'bean-check ' . (exists('b:beancount_root') ? b:beancount_root : '%s'),
        \   'callback': function('<SID>HandleBeancountLint'),
        \})
augroup END

" this function is a modification of ale#handlers#unix#HandleAsError
function! <SID>HandleBeancountLint(buffer, lines) abort
  let l:pattern = '\v^([^:]+):(\d+):?(\d+)?:? ?(.+)$'
  let l:output = []

  let l:matches = ale#util#GetMatches(a:lines, l:pattern)

  for l:match in l:matches
    let l:file = l:match[1]
    let l:lnum = l:match[2] + 0
    let l:text = trim(l:match[4])
    if (l:file != expand('%:p'))
      " This error is for a different file, so assign it to line 0 and prepend
      " the culprit filename to the lint text
      let l:lnum = 0
      let l:relativefile = fnamemodify(l:file, ':.')
      let l:text = '('.l:relativefile.') '.l:text
    endif
    call add(l:output, {
          \   'lnum': l:lnum,
          \   'col': l:match[3] + 0,
          \   'text': l:text,
          \   'type': 'E',
          \})
  endfor

  return l:output
endfunction