You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

177 lines
6.2 KiB
VimL

" @Author: Tom Link (mailto:micathom AT gmail com?subject=[vim])
" @License: GPL (see http://www.gnu.org/licenses/gpl.txt)
" @Revision: 145
" :doc:
" Syntax checkers for R:
"
" codetools::checkUsageEnv ... Requires http://cran.r-project.org/web/packages/codetools/
" lint::lint ... Requires http://cran.r-project.org/web/packages/lint/
" svTools::lint ... Requires http://cran.r-project.org/web/packages/svTools/
if !exists('g:checksyntax#defs#r#progname')
let g:checksyntax#defs#r#progname = executable('Rterm') ? 'Rterm' : 'R' "{{{2
endif
if !executable(g:checksyntax#defs#r#progname)
throw "Please set g:checksyntax#defs#r#progname to the full filename of Rterm/R first!"
endif
if !exists('g:checksyntax#defs#r#options')
let g:checksyntax#defs#r#options = '--slave --ess --restore --no-save -e "%s" --args' "{{{2
endif
if !exists('g:checksyntax#defs#r#checkUsage_options')
" Optons passed to codetools::checkUsageEnv.
" Must not be empty.
let g:checksyntax#defs#r#checkUsage_options = 'all = TRUE' "{{{2
endif
if !exists('g:checksyntax#defs#r#checkUsage_ignore_undefined_rx')
" A |/\V| regexp pattern of names that should be ignored, when
" codetools::checkUsageEnv reports "no visible global function
" definition".
let g:checksyntax#defs#r#checkUsage_ignore_undefined_rx = '' "{{{2
endif
if !exists('g:checksyntax#defs#r#checkUsage_ignore_functions')
" A list of function names that will be ignored when parsing the
" result list from codetools::checkUsageEnv.
let g:checksyntax#defs#r#checkUsage_ignore_functions = [] "{{{2
endif
if !exists('g:checksyntax#defs#r#checkUsage_search_other_buffers')
" If 2, also search other buffers for patterns returned by
" codetools::checkUsageEnv. This may cause unreponsive behaviour.
"
" If 1, show unidentifiable patterns as is.
"
" If 0, remove unidentifiable patterns.
let g:checksyntax#defs#r#checkUsage_search_other_buffers = 0 "{{{2
endif
call checksyntax#AddChecker('r?',
\ {
\ 'listtype': 'qfl',
\ 'name': 'codetools',
\ 'cmd': g:checksyntax#defs#r#progname .' '.
\ printf(g:checksyntax#defs#r#options, 'try({library(codetools); source(commandArgs(TRUE)); checkUsageEnv(globalenv(),'. g:checksyntax#defs#r#checkUsage_options .')})'),
\ 'efm': '%m (%f:%l), %s : <anonymous>: %m, %s : %m, %s: %m',
\ 'process_list': 'checksyntax#defs#r#CheckUsageEnv'
\ },
\ {
\ 'name': 'lint',
\ 'cmd': g:checksyntax#defs#r#progname .' '.
\ printf(g:checksyntax#defs#r#options, 'try(lint::lint(commandArgs(TRUE)))'),
\ 'efm': 'Lint: %m,%E%f:%l:%c,%Z%\\s\\+%m',
\ 'process_list': 'checksyntax#defs#r#LintLint'
\ },
\ {
\ 'name': 'svTools::lint',
\ 'cmd': g:checksyntax#defs#r#progname .' '.
\ printf(g:checksyntax#defs#r#options, 'try(svTools::lint(commandArgs(TRUE),type=''flat''))'),
\ 'efm': '%t%\\w%\\++++%l+++%c+++%m',
\ }
\ )
" :nodoc:
function! checksyntax#defs#r#LintLint(list) "{{{3
" TLogVAR a:list
let list = []
for issue in a:list
let text = get(issue, 'text', '')
if text =~ ': found on lines \d\+'
let message = matchstr(text, '^.\{-}\ze: found on lines \d\+')
let lines = split(matchstr(text, 'found on lines \zs\d\+.*$'), ', ')
" TLogVAR message, lines
for line in lines
if line[0] =~ '^\d\+'
let issue1 = copy(issue)
let issue1.text = message
let issue1.lnum = str2nr(line)
call add(list, issue1)
endif
endfor
else
call add(list, issue)
endif
endfor
" TLogVAR list
return list
endf
" :nodoc:
function! checksyntax#defs#r#CheckUsageEnv(list) "{{{3
" TLogVAR a:list
let view = winsaveview()
try
let list = map(a:list, 's:CompleteCheckUsageEnvItem(v:val)')
unlet! s:lnum s:bufnr
let list = filter(list, '!empty(v:val)')
finally
call winrestview(view)
endtry
return list
endf
function! s:CompleteCheckUsageEnvItem(item) "{{{3
" TLogVAR a:item
let item = a:item
let pattern = get(item, 'pattern', '')
if !empty(g:checksyntax#defs#r#checkUsage_ignore_functions) && !empty(pattern)
let ignored = filter(copy(g:checksyntax#defs#r#checkUsage_ignore_functions),
\ 'v:val =~ pattern')
if len(ignored) > 0
return {}
endif
endif
if !empty(g:checksyntax#defs#r#checkUsage_ignore_undefined_rx) &&
\ item.text =~ '\C\V\<no visible global function definition for '''. g:checksyntax#defs#r#checkUsage_ignore_undefined_rx .''''
return {}
endif
" TLogVAR bufname(item.bufnr)
if get(item, 'bufnr', 0) == 0 && !empty(pattern)
let pattern = substitute(pattern, '\\\$', '\\>', '')
let s:bufnr = bufnr('%')
" let fn_rx = pattern .'\_s\*<-\_s\*function\_s\*('
let fn_rx = pattern .'\_s\*<-\_s\*'
let s:lnum = search(fn_rx, 'cwn')
if s:lnum == 0 && g:checksyntax#defs#r#checkUsage_search_other_buffers == 2
let bufnr0 = s:bufnr
let view = winsaveview()
try
bufdo! if &ft == 'r' | let s:lnum = search(fn_rx, 'cwn') | if s:lnum > 0 | let s:bufnr = bufnr('%') | throw "ok" | endif | endif
catch /ok/
finally
exec 'buffer' bufnr0
call winrestview(view)
endtry
endif
" TLogVAR pattern, s:lnum
if s:lnum > 0
let item.bufnr = s:bufnr
let item.lnum = s:lnum
let item.pattern = ''
" TLogVAR item
elseif g:checksyntax#defs#r#checkUsage_search_other_buffers == 1
let item.pattern = pattern
else
return {}
endif
elseif bufname(item.bufnr) == '<Text>'
return {}
endif
return item
endf