diff options
Diffstat (limited to 'vim/bundle/syntastic/plugin')
-rw-r--r-- | vim/bundle/syntastic/plugin/syntastic.vim | 729 | ||||
-rw-r--r-- | vim/bundle/syntastic/plugin/syntastic/autoloclist.vim | 38 | ||||
-rw-r--r-- | vim/bundle/syntastic/plugin/syntastic/balloons.vim | 59 | ||||
-rw-r--r-- | vim/bundle/syntastic/plugin/syntastic/checker.vim | 273 | ||||
-rw-r--r-- | vim/bundle/syntastic/plugin/syntastic/cursor.vim | 138 | ||||
-rw-r--r-- | vim/bundle/syntastic/plugin/syntastic/highlighting.vim | 104 | ||||
-rw-r--r-- | vim/bundle/syntastic/plugin/syntastic/loclist.vim | 439 | ||||
-rw-r--r-- | vim/bundle/syntastic/plugin/syntastic/modemap.vim | 117 | ||||
-rw-r--r-- | vim/bundle/syntastic/plugin/syntastic/notifiers.vim | 86 | ||||
-rw-r--r-- | vim/bundle/syntastic/plugin/syntastic/registry.vim | 375 | ||||
-rw-r--r-- | vim/bundle/syntastic/plugin/syntastic/signs.vim | 138 |
11 files changed, 2496 insertions, 0 deletions
diff --git a/vim/bundle/syntastic/plugin/syntastic.vim b/vim/bundle/syntastic/plugin/syntastic.vim new file mode 100644 index 0000000..49b586c --- /dev/null +++ b/vim/bundle/syntastic/plugin/syntastic.vim @@ -0,0 +1,729 @@ +"============================================================================ +"File: syntastic.vim +"Description: Vim plugin for on the fly syntax checking. +"License: This program is free software. It comes without any warranty, +" to the extent permitted by applicable law. You can redistribute +" it and/or modify it under the terms of the Do What The Fuck You +" Want To Public License, Version 2, as published by Sam Hocevar. +" See http://sam.zoy.org/wtfpl/COPYING for more details. +" +"============================================================================ + +if exists('g:loaded_syntastic_plugin') || &compatible + finish +endif +let g:loaded_syntastic_plugin = 1 + +if has('reltime') + let g:_SYNTASTIC_START = reltime() + lockvar! g:_SYNTASTIC_START +endif + +let g:_SYNTASTIC_VERSION = '3.7.0-157' +lockvar g:_SYNTASTIC_VERSION + +" Sanity checks {{{1 + +if v:version < 700 || (v:version == 700 && !has('patch175')) + call syntastic#log#error('need Vim version 7.0.175 or later') + finish +endif + +for s:feature in [ + \ 'autocmd', + \ 'eval', + \ 'file_in_path', + \ 'modify_fname', + \ 'quickfix', + \ 'reltime', + \ 'user_commands' + \ ] + if !has(s:feature) + call syntastic#log#error('need Vim compiled with feature ' . s:feature) + finish + endif +endfor + +let s:_running_windows = syntastic#util#isRunningWindows() +lockvar s:_running_windows + +if !exists('g:syntastic_shell') + let g:syntastic_shell = &shell +endif + +if s:_running_windows + let g:_SYNTASTIC_UNAME = 'Windows' +elseif executable('uname') + try + let g:_SYNTASTIC_UNAME = split(syntastic#util#system('uname'), "\n")[0] + catch /\m^Vim\%((\a\+)\)\=:E484/ + call syntastic#log#error("your shell " . syntastic#util#var('shell') . " can't handle traditional UNIX syntax for redirections") + finish + catch /\m^Vim\%((\a\+)\)\=:E684/ + let g:_SYNTASTIC_UNAME = 'Unknown' + endtry +else + let g:_SYNTASTIC_UNAME = 'Unknown' +endif +lockvar g:_SYNTASTIC_UNAME + +" }}}1 + +" Defaults {{{1 + +let g:_SYNTASTIC_DEFAULTS = { + \ 'aggregate_errors': 0, + \ 'always_populate_loc_list': 0, + \ 'auto_jump': 0, + \ 'auto_loc_list': 2, + \ 'check_on_open': 0, + \ 'check_on_wq': 1, + \ 'cursor_columns': 1, + \ 'debug': 0, + \ 'echo_current_error': 1, + \ 'enable_balloons': 1, + \ 'enable_highlighting': 1, + \ 'enable_signs': 1, + \ 'error_symbol': '>>', + \ 'exit_checks': !(s:_running_windows && syntastic#util#var('shell', &shell) =~? '\m\<cmd\.exe$'), + \ 'filetype_map': {}, + \ 'full_redraws': !(has('gui_running') || has('gui_macvim')), + \ 'id_checkers': 1, + \ 'ignore_extensions': '\c\v^([gx]?z|lzma|bz2)$', + \ 'ignore_files': [], + \ 'loc_list_height': 10, + \ 'nested_autocommands': 0, + \ 'quiet_messages': {}, + \ 'reuse_loc_lists': 1, + \ 'shell': &shell, + \ 'sort_aggregated_errors': 1, + \ 'stl_format': '[Syntax: line:%F (%t)]', + \ 'style_error_symbol': 'S>', + \ 'style_warning_symbol': 'S>', + \ 'warning_symbol': '>>' + \ } +lockvar! g:_SYNTASTIC_DEFAULTS + +for s:key in keys(g:_SYNTASTIC_DEFAULTS) + if !exists('g:syntastic_' . s:key) + let g:syntastic_{s:key} = copy(g:_SYNTASTIC_DEFAULTS[s:key]) + endif +endfor + +if exists('g:syntastic_quiet_warnings') + call syntastic#log#oneTimeWarn("variable g:syntastic_quiet_warnings is deprecated, please use let g:syntastic_quiet_messages = {'level': 'warnings'} instead") + if g:syntastic_quiet_warnings + let s:quiet_warnings = get(g:syntastic_quiet_messages, 'type', []) + if type(s:quiet_warnings) != type([]) + let s:quiet_warnings = [s:quiet_warnings] + endif + call add(s:quiet_warnings, 'warnings') + let g:syntastic_quiet_messages['type'] = s:quiet_warnings + endif +endif + +" }}}1 + +" Debug {{{1 + +let s:_DEBUG_DUMP_OPTIONS = [ + \ 'shell', + \ 'shellcmdflag', + \ 'shellpipe', + \ 'shellquote', + \ 'shellredir', + \ 'shellslash', + \ 'shelltemp', + \ 'shellxquote' + \ ] +if exists('+shellxescape') + call add(s:_DEBUG_DUMP_OPTIONS, 'shellxescape') +endif +lockvar! s:_DEBUG_DUMP_OPTIONS + +" debug constants +let g:_SYNTASTIC_DEBUG_TRACE = 1 +lockvar g:_SYNTASTIC_DEBUG_TRACE +let g:_SYNTASTIC_DEBUG_LOCLIST = 2 +lockvar g:_SYNTASTIC_DEBUG_LOCLIST +let g:_SYNTASTIC_DEBUG_NOTIFICATIONS = 4 +lockvar g:_SYNTASTIC_DEBUG_NOTIFICATIONS +let g:_SYNTASTIC_DEBUG_AUTOCOMMANDS = 8 +lockvar g:_SYNTASTIC_DEBUG_AUTOCOMMANDS +let g:_SYNTASTIC_DEBUG_VARIABLES = 16 +lockvar g:_SYNTASTIC_DEBUG_VARIABLES +let g:_SYNTASTIC_DEBUG_CHECKERS = 32 +lockvar g:_SYNTASTIC_DEBUG_CHECKERS + +" }}}1 + +runtime! plugin/syntastic/*.vim + +let s:registry = g:SyntasticRegistry.Instance() +let s:notifiers = g:SyntasticNotifiers.Instance() +let s:modemap = g:SyntasticModeMap.Instance() + +let s:_quit_pre = [] + +" Commands {{{1 + +" @vimlint(EVL103, 1, a:cursorPos) +" @vimlint(EVL103, 1, a:cmdLine) +" @vimlint(EVL103, 1, a:argLead) +function! s:CompleteCheckerName(argLead, cmdLine, cursorPos) abort " {{{2 + let checker_names = [] + for ft in s:_resolve_filetypes([]) + call extend(checker_names, s:registry.getNamesOfAvailableCheckers(ft)) + endfor + return join(checker_names, "\n") +endfunction " }}}2 +" @vimlint(EVL103, 0, a:cursorPos) +" @vimlint(EVL103, 0, a:cmdLine) +" @vimlint(EVL103, 0, a:argLead) + + +" @vimlint(EVL103, 1, a:cursorPos) +" @vimlint(EVL103, 1, a:cmdLine) +" @vimlint(EVL103, 1, a:argLead) +function! s:CompleteFiletypes(argLead, cmdLine, cursorPos) abort " {{{2 + return join(s:registry.getKnownFiletypes(), "\n") +endfunction " }}}2 +" @vimlint(EVL103, 0, a:cursorPos) +" @vimlint(EVL103, 0, a:cmdLine) +" @vimlint(EVL103, 0, a:argLead) + +command! -bar -nargs=* -complete=custom,s:CompleteCheckerName SyntasticCheck call SyntasticCheck(<f-args>) +command! -bar -nargs=? -complete=custom,s:CompleteFiletypes SyntasticInfo call SyntasticInfo(<f-args>) +command! -bar Errors call SyntasticErrors() +command! -bar SyntasticReset call SyntasticReset() +command! -bar SyntasticToggleMode call SyntasticToggleMode() +command! -bar SyntasticSetLoclist call SyntasticSetLoclist() + +command! SyntasticJavacEditClasspath runtime! syntax_checkers/java/*.vim | SyntasticJavacEditClasspath +command! SyntasticJavacEditConfig runtime! syntax_checkers/java/*.vim | SyntasticJavacEditConfig + +" }}}1 + +" Public API {{{1 + +function! SyntasticCheck(...) abort " {{{2 + call s:UpdateErrors(0, a:000) + call syntastic#util#redraw(g:syntastic_full_redraws) +endfunction " }}}2 + +function! SyntasticInfo(...) abort " {{{2 + call s:modemap.modeInfo(a:000) + call s:registry.echoInfoFor(s:_resolve_filetypes(a:000)) + call s:_explain_skip(a:000) +endfunction " }}}2 + +function! SyntasticErrors() abort " {{{2 + call g:SyntasticLoclist.current().show() +endfunction " }}}2 + +function! SyntasticReset() abort " {{{2 + call s:ClearCache() + call s:notifiers.refresh(g:SyntasticLoclist.New([])) +endfunction " }}}2 + +function! SyntasticToggleMode() abort " {{{2 + call s:modemap.toggleMode() + call s:ClearCache() + call s:notifiers.refresh(g:SyntasticLoclist.New([])) + call s:modemap.echoMode() +endfunction " }}}2 + +function! SyntasticSetLoclist() abort " {{{2 + call g:SyntasticLoclist.current().setloclist() +endfunction " }}}2 + +" }}}1 + +" Autocommands {{{1 + +augroup syntastic + autocmd! + autocmd BufEnter * call s:BufEnterHook() +augroup END + +if g:syntastic_nested_autocommands + augroup syntastic + autocmd BufReadPost * nested call s:BufReadPostHook() + autocmd BufWritePost * nested call s:BufWritePostHook() + augroup END +else + augroup syntastic + autocmd BufReadPost * call s:BufReadPostHook() + autocmd BufWritePost * call s:BufWritePostHook() + augroup END +endif + +if exists('##QuitPre') + " QuitPre was added in Vim 7.3.544 + augroup syntastic + autocmd QuitPre * call s:QuitPreHook(expand('<amatch>', 1)) + augroup END +endif + +function! s:BufReadPostHook() abort " {{{2 + if g:syntastic_check_on_open + call syntastic#log#debug(g:_SYNTASTIC_DEBUG_AUTOCOMMANDS, + \ 'autocmd: BufReadPost, buffer ' . bufnr('') . ' = ' . string(bufname(str2nr(bufnr(''))))) + call s:UpdateErrors(1, []) + endif +endfunction " }}}2 + +function! s:BufWritePostHook() abort " {{{2 + call syntastic#log#debug(g:_SYNTASTIC_DEBUG_AUTOCOMMANDS, + \ 'autocmd: BufWritePost, buffer ' . bufnr('') . ' = ' . string(bufname(str2nr(bufnr(''))))) + call s:UpdateErrors(1, []) +endfunction " }}}2 + +function! s:BufEnterHook() abort " {{{2 + call syntastic#log#debug(g:_SYNTASTIC_DEBUG_AUTOCOMMANDS, + \ 'autocmd: BufEnter, buffer ' . bufnr('') . ' = ' . string(bufname(str2nr(bufnr('')))) . + \ ', &buftype = ' . string(&buftype)) + if &buftype ==# '' + call s:notifiers.refresh(g:SyntasticLoclist.current()) + elseif &buftype ==# 'quickfix' + " TODO: this is needed because in recent versions of Vim lclose + " can no longer be called from BufWinLeave + " TODO: at this point there is no b:syntastic_loclist + let loclist = filter(copy(getloclist(0)), 'v:val["valid"] == 1') + let owner = str2nr(getbufvar(bufnr(''), 'syntastic_owner_buffer')) + let buffers = syntastic#util#unique(map(loclist, 'v:val["bufnr"]') + (owner ? [owner] : [])) + if !empty(get(w:, 'syntastic_loclist_set', [])) && !empty(loclist) && empty(filter( buffers, 'syntastic#util#bufIsActive(v:val)' )) + call SyntasticLoclistHide() + endif + endif +endfunction " }}}2 + +function! s:QuitPreHook(fname) abort " {{{2 + let buf = bufnr(fnameescape(a:fname)) + call syntastic#log#debug(g:_SYNTASTIC_DEBUG_AUTOCOMMANDS, 'autocmd: QuitPre, buffer ' . buf . ' = ' . string(a:fname)) + + if !syntastic#util#var('check_on_wq') + call syntastic#util#setWids() + call add(s:_quit_pre, buf . '_' . getbufvar(buf, 'changetick') . '_' . w:syntastic_wid) + endif + + if !empty(get(w:, 'syntastic_loclist_set', [])) + call SyntasticLoclistHide() + endif +endfunction " }}}2 + +" }}}1 + +" Main {{{1 + +"refresh and redraw all the error info for this buf when saving or reading +function! s:UpdateErrors(auto_invoked, checker_names) abort " {{{2 + call syntastic#log#debugShowVariables(g:_SYNTASTIC_DEBUG_TRACE, 'version') + call syntastic#log#debugShowOptions(g:_SYNTASTIC_DEBUG_TRACE, s:_DEBUG_DUMP_OPTIONS) + call syntastic#log#debugDump(g:_SYNTASTIC_DEBUG_VARIABLES) + call syntastic#log#debug(g:_SYNTASTIC_DEBUG_TRACE, 'UpdateErrors' . (a:auto_invoked ? ' (auto)' : '') . + \ ': ' . (len(a:checker_names) ? join(a:checker_names) : 'default checkers')) + + call s:modemap.synch() + + if s:_skip_file() + return + endif + + let run_checks = !a:auto_invoked || s:modemap.doAutoChecking() + if run_checks + call s:CacheErrors(a:checker_names) + call syntastic#util#setChangedtick() + else + if a:auto_invoked + return + endif + endif + + let loclist = g:SyntasticLoclist.current() + + if exists('*SyntasticCheckHook') + call SyntasticCheckHook(loclist.getRaw()) + endif + + " populate loclist and jump {{{3 + let do_jump = syntastic#util#var('auto_jump') + 0 + if do_jump == 2 + let do_jump = loclist.getFirstError(1) + elseif do_jump == 3 + let do_jump = loclist.getFirstError() + elseif 0 > do_jump || do_jump > 3 + let do_jump = 0 + endif + + let w:syntastic_loclist_set = [] + if syntastic#util#var('always_populate_loc_list') || do_jump + call syntastic#log#debug(g:_SYNTASTIC_DEBUG_NOTIFICATIONS, 'loclist: setloclist (new)') + call setloclist(0, loclist.getRaw()) + if !exists('b:syntastic_changedtick') + call syntastic#util#setChangedtick() + endif + let w:syntastic_loclist_set = [bufnr(''), b:syntastic_changedtick] + if run_checks && do_jump && !loclist.isEmpty() + call syntastic#log#debug(g:_SYNTASTIC_DEBUG_NOTIFICATIONS, 'loclist: jump') + execute 'silent! lrewind ' . do_jump + + " XXX: Vim doesn't call autocmd commands in a predictible + " order, which can lead to missing filetype when jumping + " to a new file; the following is a workaround for the + " resulting brain damage + if &filetype ==# '' + silent! filetype detect + endif + endif + endif + " }}}3 + + call s:notifiers.refresh(loclist) +endfunction " }}}2 + +"clear the loc list for the buffer +function! s:ClearCache() abort " {{{2 + call s:notifiers.reset(g:SyntasticLoclist.current()) + call b:syntastic_loclist.destroy() +endfunction " }}}2 + +"detect and cache all syntax errors in this buffer +function! s:CacheErrors(checker_names) abort " {{{2 + call syntastic#log#debug(g:_SYNTASTIC_DEBUG_TRACE, 'CacheErrors: ' . + \ (len(a:checker_names) ? join(a:checker_names) : 'default checkers')) + call s:ClearCache() + let newLoclist = g:SyntasticLoclist.New([]) + + if !s:_skip_file() + " debug logging {{{3 + call syntastic#log#debugShowVariables(g:_SYNTASTIC_DEBUG_TRACE, 'aggregate_errors') + call syntastic#log#debug(g:_SYNTASTIC_DEBUG_CHECKERS, '$PATH = ' . string($PATH)) + call syntastic#log#debug(g:_SYNTASTIC_DEBUG_TRACE, 'getcwd() = ' . string(getcwd())) + " }}}3 + + let filetypes = s:_resolve_filetypes([]) + let aggregate_errors = syntastic#util#var('aggregate_errors') || len(filetypes) > 1 + let decorate_errors = aggregate_errors && syntastic#util#var('id_checkers') + let sort_aggregated_errors = aggregate_errors && syntastic#util#var('sort_aggregated_errors') + + let clist = [] + for type in filetypes + call extend(clist, s:registry.getCheckers(type, a:checker_names)) + endfor + + let names = [] + let unavailable_checkers = 0 + for checker in clist + let cname = checker.getFiletype() . '/' . checker.getName() + if !checker.isAvailable() + call syntastic#log#debug(g:_SYNTASTIC_DEBUG_TRACE, 'CacheErrors: Checker ' . cname . ' is not available') + let unavailable_checkers += 1 + continue + endif + + call syntastic#log#debug(g:_SYNTASTIC_DEBUG_TRACE, 'CacheErrors: Invoking checker: ' . cname) + + let loclist = checker.getLocList() + + if !loclist.isEmpty() + if decorate_errors + call loclist.decorate(cname) + endif + call add(names, cname) + if checker.wantSort() && !sort_aggregated_errors + call loclist.sort() + call syntastic#log#debug(g:_SYNTASTIC_DEBUG_LOCLIST, 'sorted:', loclist) + endif + + let newLoclist = newLoclist.extend(loclist) + + if !aggregate_errors + break + endif + endif + endfor + + " set names {{{3 + if !empty(names) + if len(syntastic#util#unique(map( copy(names), 'substitute(v:val, "\\m/.*", "", "")' ))) == 1 + let type = substitute(names[0], '\m/.*', '', '') + let name = join(map( names, 'substitute(v:val, "\\m.\\{-}/", "", "")' ), ', ') + call newLoclist.setName( name . ' ('. type . ')' ) + else + " checkers from mixed types + call newLoclist.setName(join(names, ', ')) + endif + endif + " }}}3 + + " issue warning about no active checkers {{{3 + if len(clist) == unavailable_checkers + if !empty(a:checker_names) + if len(a:checker_names) == 1 + call syntastic#log#warn('checker ' . a:checker_names[0] . ' is not available') + else + call syntastic#log#warn('checkers ' . join(a:checker_names, ', ') . ' are not available') + endif + else + call syntastic#log#debug(g:_SYNTASTIC_DEBUG_TRACE, 'CacheErrors: no checkers available for ' . &filetype) + endif + endif + " }}}3 + + call syntastic#log#debug(g:_SYNTASTIC_DEBUG_LOCLIST, 'aggregated:', newLoclist) + if sort_aggregated_errors + call newLoclist.sort() + call syntastic#log#debug(g:_SYNTASTIC_DEBUG_LOCLIST, 'sorted:', newLoclist) + endif + endif + + call newLoclist.deploy() +endfunction " }}}2 + +"Emulates the :lmake command. Sets up the make environment according to the +"options given, runs make, resets the environment, returns the location list +" +"a:options can contain the following keys: +" 'makeprg' +" 'errorformat' +" +"The corresponding options are set for the duration of the function call. They +"are set with :let, so dont escape spaces. +" +"a:options may also contain: +" 'defaults' - a dict containing default values for the returned errors +" 'subtype' - all errors will be assigned the given subtype +" 'preprocess' - a function to be applied to the error file before parsing errors +" 'postprocess' - a list of functions to be applied to the error list +" 'cwd' - change directory to the given path before running the checker +" 'env' - environment variables to set before running the checker +" 'returns' - a list of valid exit codes for the checker +" @vimlint(EVL102, 1, l:env_save) +function! SyntasticMake(options) abort " {{{2 + call syntastic#log#debug(g:_SYNTASTIC_DEBUG_TRACE, 'SyntasticMake: called with options:', a:options) + + " save options and locale env variables {{{3 + let old_local_errorformat = &l:errorformat + let old_errorformat = &errorformat + let old_cwd = getcwd() + " }}}3 + + if has_key(a:options, 'errorformat') + let &errorformat = a:options['errorformat'] + set errorformat< + endif + + if has_key(a:options, 'cwd') + execute 'lcd ' . fnameescape(a:options['cwd']) + endif + + " set environment variables {{{3 + let env_save = {} + if has_key(a:options, 'env') && len(a:options['env']) + for key in keys(a:options['env']) + if key =~? '\m^[a-z_][a-z0-9_]*$' + execute 'let env_save[' . string(key) . '] = $' . key + execute 'let $' . key . ' = ' . string(a:options['env'][key]) + endif + endfor + endif + " }}}3 + + let err_lines = split(syntastic#util#system(a:options['makeprg']), "\n", 1) + + " restore environment variables {{{3 + if len(env_save) + for key in keys(env_save) + execute 'let $' . key . ' = ' . string(env_save[key]) + endfor + endif + " }}}3 + + call syntastic#log#debug(g:_SYNTASTIC_DEBUG_LOCLIST, 'checker output:', err_lines) + + " Does it still make sense to go on? + let bailout = + \ syntastic#util#var('exit_checks') && + \ has_key(a:options, 'returns') && + \ index(a:options['returns'], v:shell_error) == -1 + + if !bailout + if has_key(a:options, 'Preprocess') + let err_lines = call(a:options['Preprocess'], [err_lines]) + call syntastic#log#debug(g:_SYNTASTIC_DEBUG_LOCLIST, 'preprocess (external):', err_lines) + elseif has_key(a:options, 'preprocess') + let err_lines = call('syntastic#preprocess#' . a:options['preprocess'], [err_lines]) + call syntastic#log#debug(g:_SYNTASTIC_DEBUG_LOCLIST, 'preprocess:', err_lines) + endif + lgetexpr err_lines + + let errors = deepcopy(getloclist(0)) + + if has_key(a:options, 'cwd') + execute 'lcd ' . fnameescape(old_cwd) + endif + + try + silent lolder + catch /\m^Vim\%((\a\+)\)\=:E380/ + " E380: At bottom of quickfix stack + call setloclist(0, [], 'r') + catch /\m^Vim\%((\a\+)\)\=:E776/ + " E776: No location list + " do nothing + endtry + else + let errors = [] + endif + + " restore options {{{3 + let &errorformat = old_errorformat + let &l:errorformat = old_local_errorformat + " }}}3 + + if !s:_running_windows && (s:_os_name() =~? 'FreeBSD' || s:_os_name() =~? 'OpenBSD') + call syntastic#util#redraw(g:syntastic_full_redraws) + endif + + if bailout + call syntastic#log#ndebug(g:_SYNTASTIC_DEBUG_LOCLIST, 'checker output:', err_lines) + throw 'Syntastic: checker error' + endif + + call syntastic#log#debug(g:_SYNTASTIC_DEBUG_LOCLIST, 'raw loclist:', errors) + + if has_key(a:options, 'defaults') + call s:_add_to_errors(errors, a:options['defaults']) + endif + + " Add subtype info if present. + if has_key(a:options, 'subtype') + call s:_add_to_errors(errors, { 'subtype': a:options['subtype'] }) + endif + + if has_key(a:options, 'Postprocess') && !empty(a:options['Postprocess']) + for rule in a:options['Postprocess'] + let errors = call(rule, [errors]) + endfor + call syntastic#log#debug(g:_SYNTASTIC_DEBUG_LOCLIST, 'postprocess (external):', errors) + elseif has_key(a:options, 'postprocess') && !empty(a:options['postprocess']) + for rule in a:options['postprocess'] + let errors = call('syntastic#postprocess#' . rule, [errors]) + endfor + call syntastic#log#debug(g:_SYNTASTIC_DEBUG_LOCLIST, 'postprocess:', errors) + endif + + return errors +endfunction " }}}2 +" @vimlint(EVL102, 0, l:env_save) + +"return a string representing the state of buffer according to +"g:syntastic_stl_format +" +"return '' if no errors are cached for the buffer +function! SyntasticStatuslineFlag() abort " {{{2 + return g:SyntasticLoclist.current().getStatuslineFlag() +endfunction " }}}2 + +" }}}1 + +" Utilities {{{1 + +function! s:_resolve_filetypes(filetypes) abort " {{{2 + let type = len(a:filetypes) ? a:filetypes[0] : &filetype + return split( get(g:syntastic_filetype_map, type, type), '\m\.' ) +endfunction " }}}2 + +function! s:_ignore_file(filename) abort " {{{2 + let fname = fnamemodify(a:filename, ':p') + for pattern in g:syntastic_ignore_files + if fname =~# pattern + return 1 + endif + endfor + return 0 +endfunction " }}}2 + +function! s:_is_quitting(buf) abort " {{{2 + let quitting = 0 + if exists('w:syntastic_wid') + let key = a:buf . '_' . getbufvar(a:buf, 'changetick') . '_' . w:syntastic_wid + let idx = index(s:_quit_pre, key) + if idx >= 0 + call remove(s:_quit_pre, idx) + let quitting = 1 + endif + endif + + return quitting +endfunction " }}}2 + +" Skip running in special buffers +function! s:_skip_file() abort " {{{2 + let fname = expand('%', 1) + let skip = s:_is_quitting(bufnr('%')) || get(b:, 'syntastic_skip_checks', 0) || + \ (&buftype !=# '') || !filereadable(fname) || getwinvar(0, '&diff') || + \ getwinvar(0, '&previewwindow') || s:_ignore_file(fname) || + \ fnamemodify(fname, ':e') =~? g:syntastic_ignore_extensions + if skip + call syntastic#log#debug(g:_SYNTASTIC_DEBUG_TRACE, '_skip_file: skipping checks') + endif + return skip +endfunction " }}}2 + +" Explain why checks will be skipped for the current file +function! s:_explain_skip(filetypes) abort " {{{2 + if empty(a:filetypes) && s:_skip_file() + let why = [] + let fname = expand('%', 1) + + if s:_is_quitting(bufnr('%')) + call add(why, 'quitting buffer') + endif + if get(b:, 'syntastic_skip_checks', 0) + call add(why, 'b:syntastic_skip_checks set') + endif + if &buftype !=# '' + call add(why, 'buftype = ' . string(&buftype)) + endif + if !filereadable(fname) + call add(why, 'file not readable / not local') + endif + if getwinvar(0, '&diff') + call add(why, 'diff mode') + endif + if getwinvar(0, '&previewwindow') + call add(why, 'preview window') + endif + if s:_ignore_file(fname) + call add(why, 'filename matching g:syntastic_ignore_files') + endif + if fnamemodify(fname, ':e') =~? g:syntastic_ignore_extensions + call add(why, 'extension matching g:syntastic_ignore_extensions') + endif + + echomsg 'The current file will not be checked (' . join(why, ', ') . ')' + endif +endfunction " }}}2 + +" Take a list of errors and add default values to them from a:options +function! s:_add_to_errors(errors, options) abort " {{{2 + for err in a:errors + for key in keys(a:options) + if !has_key(err, key) || empty(err[key]) + let err[key] = a:options[key] + endif + endfor + endfor + + return a:errors +endfunction " }}}2 + +function! s:_os_name() abort " {{{2 + return g:_SYNTASTIC_UNAME +endfunction " }}}2 + +" }}}1 + +" vim: set sw=4 sts=4 et fdm=marker: diff --git a/vim/bundle/syntastic/plugin/syntastic/autoloclist.vim b/vim/bundle/syntastic/plugin/syntastic/autoloclist.vim new file mode 100644 index 0000000..153b0bc --- /dev/null +++ b/vim/bundle/syntastic/plugin/syntastic/autoloclist.vim @@ -0,0 +1,38 @@ +if exists('g:loaded_syntastic_notifier_autoloclist') || !exists('g:loaded_syntastic_plugin') + finish +endif +let g:loaded_syntastic_notifier_autoloclist = 1 + +let g:SyntasticAutoloclistNotifier = {} + +" Public methods {{{1 +" +function! g:SyntasticAutoloclistNotifier.New() abort " {{{2 + let newObj = copy(self) + return newObj +endfunction " }}}2 + +function! g:SyntasticAutoloclistNotifier.refresh(loclist) abort " {{{2 + call syntastic#log#debug(g:_SYNTASTIC_DEBUG_NOTIFICATIONS, 'autoloclist: refresh') + call g:SyntasticAutoloclistNotifier.AutoToggle(a:loclist) +endfunction " }}}2 + +function! g:SyntasticAutoloclistNotifier.AutoToggle(loclist) abort " {{{2 + call syntastic#log#debug(g:_SYNTASTIC_DEBUG_NOTIFICATIONS, 'autoloclist: toggle') + let auto_loc_list = syntastic#util#var('auto_loc_list') + if !a:loclist.isEmpty() + if auto_loc_list == 1 || auto_loc_list == 3 + call a:loclist.show() + endif + else + if auto_loc_list == 1 || auto_loc_list == 2 + "TODO: this will close the loc list window if one was opened by + "something other than syntastic + lclose + endif + endif +endfunction " }}}2 + +" }}}1 + +" vim: set sw=4 sts=4 et fdm=marker: diff --git a/vim/bundle/syntastic/plugin/syntastic/balloons.vim b/vim/bundle/syntastic/plugin/syntastic/balloons.vim new file mode 100644 index 0000000..fdd70bf --- /dev/null +++ b/vim/bundle/syntastic/plugin/syntastic/balloons.vim @@ -0,0 +1,59 @@ +if exists('g:loaded_syntastic_notifier_balloons') || !exists('g:loaded_syntastic_plugin') + finish +endif +let g:loaded_syntastic_notifier_balloons = 1 + +if !has('balloon_eval') + let g:syntastic_enable_balloons = 0 +endif + +let g:SyntasticBalloonsNotifier = {} + +" Public methods {{{1 + +function! g:SyntasticBalloonsNotifier.New() abort " {{{2 + let newObj = copy(self) + return newObj +endfunction " }}}2 + +function! g:SyntasticBalloonsNotifier.enabled() abort " {{{2 + return has('balloon_eval') && syntastic#util#var('enable_balloons') +endfunction " }}}2 + +" Update the error balloons +function! g:SyntasticBalloonsNotifier.refresh(loclist) abort " {{{2 + unlet! b:syntastic_private_balloons + if self.enabled() && !a:loclist.isEmpty() + let b:syntastic_private_balloons = a:loclist.balloons() + if !empty(b:syntastic_private_balloons) + set ballooneval balloonexpr=SyntasticBalloonsExprNotifier() + endif + endif +endfunction " }}}2 + +" Reset the error balloons +" @vimlint(EVL103, 1, a:loclist) +function! g:SyntasticBalloonsNotifier.reset(loclist) abort " {{{2 + let b:syntastic_private_balloons = {} + if has('balloon_eval') + call syntastic#log#debug(g:_SYNTASTIC_DEBUG_NOTIFICATIONS, 'balloons: reset') + unlet! b:syntastic_private_balloons + set noballooneval + endif +endfunction " }}}2 +" @vimlint(EVL103, 0, a:loclist) + +" }}}1 + +" Private functions {{{1 + +function! SyntasticBalloonsExprNotifier() abort " {{{2 + if !exists('b:syntastic_private_balloons') + return '' + endif + return get(b:syntastic_private_balloons, v:beval_lnum, '') +endfunction " }}}2 + +" }}}1 + +" vim: set sw=4 sts=4 et fdm=marker: diff --git a/vim/bundle/syntastic/plugin/syntastic/checker.vim b/vim/bundle/syntastic/plugin/syntastic/checker.vim new file mode 100644 index 0000000..22ad820 --- /dev/null +++ b/vim/bundle/syntastic/plugin/syntastic/checker.vim @@ -0,0 +1,273 @@ +if exists('g:loaded_syntastic_checker') || !exists('g:loaded_syntastic_plugin') + finish +endif +let g:loaded_syntastic_checker = 1 + +let g:SyntasticChecker = {} + +" Public methods {{{1 + +function! g:SyntasticChecker.New(args, ...) abort " {{{2 + let newObj = copy(self) + + let newObj._filetype = a:args['filetype'] + let newObj._name = a:args['name'] + + if a:0 + " redirected checker + let newObj._exec = get(a:args, 'exec', a:1['_exec']) + + let filetype = a:1['_filetype'] + let name = a:1['_name'] + let prefix = 'SyntaxCheckers_' . filetype . '_' . name . '_' + + if exists('g:syntastic_' . filetype . '_' . name . '_sort') && !exists('g:syntastic_' . newObj._filetype . '_' . newObj._name . '_sort') + let g:syntastic_{newObj._filetype}_{newObj._name}_sort = g:syntastic_{filetype}_{name}_sort + endif + + if has_key(a:args, 'enable') + let newObj._enable = a:args['enable'] + elseif has_key(a:1, '_enable') + let newObj._enable = a:1['_enable'] + endif + else + let newObj._exec = get(a:args, 'exec', newObj._name) + let prefix = 'SyntaxCheckers_' . newObj._filetype . '_' . newObj._name . '_' + + if has_key(a:args, 'enable') + let newObj._enable = a:args['enable'] + endif + endif + + let newObj._locListFunc = function(prefix . 'GetLocList') + + if exists('*' . prefix . 'IsAvailable') + let newObj._isAvailableFunc = function(prefix . 'IsAvailable') + else + let newObj._isAvailableFunc = function('s:_isAvailableDefault') + endif + + if exists('*' . prefix . 'GetHighlightRegex') + let newObj._highlightRegexFunc = function(prefix . 'GetHighlightRegex') + endif + + return newObj +endfunction " }}}2 + +function! g:SyntasticChecker.getFiletype() abort " {{{2 + return self._filetype +endfunction " }}}2 + +function! g:SyntasticChecker.getName() abort " {{{2 + return self._name +endfunction " }}}2 + +" Synchronise _exec with user's setting. Force re-validation if needed. +" +" XXX: This function must be called at least once before calling either +" getExec() or getExecEscaped(). Normally isAvailable() does that for you +" automatically, but you should keep still this in mind if you change the +" current checker workflow. +function! g:SyntasticChecker.syncExec() abort " {{{2 + let user_exec = + \ expand( exists('b:syntastic_' . self._name . '_exec') ? b:syntastic_{self._name}_exec : + \ syntastic#util#var(self._filetype . '_' . self._name . '_exec'), 1 ) + + if user_exec !=# '' && user_exec !=# self._exec + let self._exec = user_exec + if has_key(self, '_available') + " we have a new _exec on the block, it has to be validated + call remove(self, '_available') + endif + endif +endfunction " }}}2 + +function! g:SyntasticChecker.getExec() abort " {{{2 + return self._exec +endfunction " }}}2 + +function! g:SyntasticChecker.getExecEscaped() abort " {{{2 + return syntastic#util#shescape(self._exec) +endfunction " }}}2 + +function! g:SyntasticChecker.getLocListRaw() abort " {{{2 + let checker_start = reltime() + let name = self._filetype . '/' . self._name + + if has_key(self, '_enable') + let status = syntastic#util#var(self._enable, -1) + if type(status) != type(0) + call syntastic#log#error('checker ' . name . ': invalid value ' . strtrans(string(status)) . + \ ' for g:syntastic_' . self._enable . '; try 0 or 1 instead') + return [] + endif + if status < 0 + call syntastic#log#error('checker ' . name . ': checks disabled for security reasons; ' . + \ 'set g:syntastic_' . self._enable . ' to 1 to override') + endif + if status <= 0 + call syntastic#log#debug(g:_SYNTASTIC_DEBUG_TRACE, 'getLocList: checker ' . name . ' enabled but not forced') + return [] + else + call syntastic#log#debug(g:_SYNTASTIC_DEBUG_TRACE, 'getLocList: checker ' . name . ' forced') + endif + endif + + try + let list = self._locListFunc() + if self._exec !=# '' + call syntastic#log#debug(g:_SYNTASTIC_DEBUG_TRACE, 'getLocList: checker ' . name . ' returned ' . v:shell_error) + endif + catch /\m\C^Syntastic: checker error$/ + let list = [] + if self._exec !=# '' + call syntastic#log#error('checker ' . name . ' returned abnormal status ' . v:shell_error) + else + call syntastic#log#error('checker ' . name . ' aborted') + endif + endtry + call self._populateHighlightRegexes(list) + call syntastic#log#debug(g:_SYNTASTIC_DEBUG_LOCLIST, name . ' raw:', list) + call self._quietMessages(list) + call syntastic#log#debug(g:_SYNTASTIC_DEBUG_TRACE, + \ 'getLocList: checker ' . name . ' run in ' . split(reltimestr(reltime(checker_start)))[0] . 's') + return list +endfunction " }}}2 + +function! g:SyntasticChecker.getLocList() abort " {{{2 + return g:SyntasticLoclist.New(self.getLocListRaw()) +endfunction " }}}2 + +function! g:SyntasticChecker.getVersion(...) abort " {{{2 + if !exists('self._version') + let command = a:0 ? a:1 : self.getExecEscaped() . ' --version' + let version_output = syntastic#util#system(command) + call self.log('getVersion: ' . string(command) . ': ' . + \ string(split(version_output, "\n", 1)) . + \ (v:shell_error ? ' (exit code ' . v:shell_error . ')' : '') ) + let parsed_ver = syntastic#util#parseVersion(version_output) + if len(parsed_ver) + call self.setVersion(parsed_ver) + else + call syntastic#log#ndebug(g:_SYNTASTIC_DEBUG_LOCLIST, 'checker output:', split(version_output, "\n", 1)) + call syntastic#log#error("checker " . self._filetype . "/" . self._name . ": can't parse version string (abnormal termination?)") + endif + endif + return get(self, '_version', []) +endfunction " }}}2 + +function! g:SyntasticChecker.setVersion(version) abort " {{{2 + if len(a:version) + let self._version = copy(a:version) + call self.log(self.getExec() . ' version =', a:version) + endif +endfunction " }}}2 + +function! g:SyntasticChecker.log(msg, ...) abort " {{{2 + let leader = self._filetype . '/' . self._name . ': ' + if a:0 > 0 + call syntastic#log#debug(g:_SYNTASTIC_DEBUG_CHECKERS, leader . a:msg, a:1) + else + call syntastic#log#debug(g:_SYNTASTIC_DEBUG_CHECKERS, leader . a:msg) + endif +endfunction " }}}2 + +function! g:SyntasticChecker.makeprgBuild(opts) abort " {{{2 + let basename = self._filetype . '_' . self._name . '_' + + let parts = [] + call extend(parts, self._getOpt(a:opts, basename, 'exe', self.getExecEscaped())) + call extend(parts, self._getOpt(a:opts, basename, 'args', '')) + call extend(parts, self._getOpt(a:opts, basename, 'fname', syntastic#util#shexpand('%'))) + call extend(parts, self._getOpt(a:opts, basename, 'post_args', '')) + call extend(parts, self._getOpt(a:opts, basename, 'tail', '')) + + return join(parts) +endfunction " }}}2 + +function! g:SyntasticChecker.isAvailable() abort " {{{2 + call self.syncExec() + if !has_key(self, '_available') + let self._available = self._isAvailableFunc() + endif + return self._available +endfunction " }}}2 + +function! g:SyntasticChecker.isDisabled() abort " {{{2 + return has_key(self, '_enable') && syntastic#util#var(self._enable, -1) <= 0 +endfunction " }}}2 + +function! g:SyntasticChecker.wantSort() abort " {{{2 + return syntastic#util#var(self._filetype . '_' . self._name . '_sort', 0) +endfunction " }}}2 + +" This method is no longer used by syntastic. It's here only to maintain +" backwards compatibility with external checkers which might depend on it. +function! g:SyntasticChecker.setWantSort(val) abort " {{{2 + if !exists('g:syntastic_' . self._filetype . '_' . self._name . '_sort') + let g:syntastic_{self._filetype}_{self._name}_sort = a:val + endif +endfunction " }}}2 + +" }}}1 + +" Private methods {{{1 + +function! g:SyntasticChecker._quietMessages(errors) abort " {{{2 + " wildcard quiet_messages + let quiet_filters = copy(syntastic#util#var('quiet_messages', {})) + if type(quiet_filters) != type({}) + call syntastic#log#warn('ignoring invalid syntastic_quiet_messages') + unlet quiet_filters + let quiet_filters = {} + endif + + " per checker quiet_messages + let name = self._filetype . '_' . self._name + try + call extend( quiet_filters, copy(syntastic#util#var(name . '_quiet_messages', {})), 'force' ) + catch /\m^Vim\%((\a\+)\)\=:E712/ + call syntastic#log#warn('ignoring invalid syntastic_' . name . '_quiet_messages') + endtry + + call syntastic#log#debug(g:_SYNTASTIC_DEBUG_LOCLIST, 'quiet_messages filter:', quiet_filters) + + if !empty(quiet_filters) + call syntastic#util#dictFilter(a:errors, quiet_filters) + call syntastic#log#debug(g:_SYNTASTIC_DEBUG_LOCLIST, 'filtered by quiet_messages:', a:errors) + endif +endfunction " }}}2 + +function! g:SyntasticChecker._populateHighlightRegexes(errors) abort " {{{2 + if has_key(self, '_highlightRegexFunc') + for e in a:errors + if e['valid'] + let term = self._highlightRegexFunc(e) + if term !=# '' + let e['hl'] = term + endif + endif + endfor + endif +endfunction " }}}2 + +function! g:SyntasticChecker._getOpt(opts, basename, name, default) abort " {{{2 + let ret = [] + call extend( ret, syntastic#util#argsescape(get(a:opts, a:name . '_before', '')) ) + call extend( ret, syntastic#util#argsescape(syntastic#util#var( a:basename . a:name, get(a:opts, a:name, a:default) )) ) + call extend( ret, syntastic#util#argsescape(get(a:opts, a:name . '_after', '')) ) + + return ret +endfunction " }}}2 + +" }}}1 + +" Private functions {{{1 + +function! s:_isAvailableDefault() dict " {{{2 + return executable(self.getExec()) +endfunction " }}}2 + +" }}}1 + +" vim: set sw=4 sts=4 et fdm=marker: diff --git a/vim/bundle/syntastic/plugin/syntastic/cursor.vim b/vim/bundle/syntastic/plugin/syntastic/cursor.vim new file mode 100644 index 0000000..f59d87b --- /dev/null +++ b/vim/bundle/syntastic/plugin/syntastic/cursor.vim @@ -0,0 +1,138 @@ +if exists('g:loaded_syntastic_notifier_cursor') || !exists('g:loaded_syntastic_plugin') + finish +endif +let g:loaded_syntastic_notifier_cursor = 1 + +let g:SyntasticCursorNotifier = {} + +" Public methods {{{1 + +function! g:SyntasticCursorNotifier.New() abort " {{{2 + let newObj = copy(self) + return newObj +endfunction " }}}2 + +function! g:SyntasticCursorNotifier.enabled() abort " {{{2 + return syntastic#util#var('echo_current_error') +endfunction " }}}2 + +function! g:SyntasticCursorNotifier.refresh(loclist) abort " {{{2 + if self.enabled() && !a:loclist.isEmpty() + call syntastic#log#debug(g:_SYNTASTIC_DEBUG_NOTIFICATIONS, 'cursor: refresh') + let b:syntastic_private_messages = copy(a:loclist.messages(bufnr(''))) + let b:syntastic_private_line = -1 + let b:syntastic_cursor_columns = a:loclist.getCursorColumns() + autocmd! syntastic CursorMoved + autocmd syntastic CursorMoved * call SyntasticRefreshCursor() + endif +endfunction " }}}2 + +" @vimlint(EVL103, 1, a:loclist) +function! g:SyntasticCursorNotifier.reset(loclist) abort " {{{2 + call syntastic#log#debug(g:_SYNTASTIC_DEBUG_NOTIFICATIONS, 'cursor: reset') + autocmd! syntastic CursorMoved + unlet! b:syntastic_private_messages + let b:syntastic_private_line = -1 +endfunction " }}}2 +" @vimlint(EVL103, 0, a:loclist) + +" }}}1 + +" Private functions {{{1 + +function! SyntasticRefreshCursor() abort " {{{2 + if !exists('b:syntastic_private_messages') || empty(b:syntastic_private_messages) + " file not checked + return + endif + + if !exists('b:syntastic_private_line') + let b:syntastic_private_line = -1 + endif + let l = line('.') + let current_messages = get(b:syntastic_private_messages, l, {}) + + if !exists('b:syntastic_cursor_columns') + let b:syntastic_cursor_columns = g:syntastic_cursor_columns + endif + + if b:syntastic_cursor_columns + let c = virtcol('.') + if !exists('b:syntastic_private_idx') + let b:syntastic_private_idx = -1 + endif + + if s:_is_same_index(l, b:syntastic_private_line, c, b:syntastic_private_idx, current_messages) + return + else + let b:syntastic_private_line = l + endif + + if !empty(current_messages) + let b:syntastic_private_idx = s:_find_index(c, current_messages) + call syntastic#util#wideMsg(current_messages[b:syntastic_private_idx].text) + else + let b:syntastic_private_idx = -1 + echo + endif + else + if l == b:syntastic_private_line + return + endif + let b:syntastic_private_line = l + + if !empty(current_messages) + call syntastic#util#wideMsg(current_messages[0].text) + else + echo + endif + endif +endfunction " }}}2 + +" }}}1 + +" Utilities {{{1 + +function! s:_is_same_index(line, old_line, column, idx, messages) abort " {{{2 + if a:old_line >= 0 && a:line == a:old_line && a:idx >= 0 + if len(a:messages) <= 1 + return 1 + endif + + if a:messages[a:idx].scol <= a:column || a:idx == 0 + if a:idx == len(a:messages) - 1 || a:column < a:messages[a:idx + 1].scol + return 1 + else + return 0 + endif + else + return 0 + endif + else + return 0 + endif +endfunction " }}}2 + +function! s:_find_index(column, messages) abort " {{{2 + let max = len(a:messages) - 1 + if max == 0 + return 0 + endif + let min = 0 + + " modified binary search: assign index 0 to columns to the left of the first error + while min < max - 1 + let mid = (min + max) / 2 + if a:column < a:messages[mid].scol + let max = mid + else + let min = mid + endif + endwhile + + return a:column < a:messages[max].scol ? min : max +endfunction " }}}2 + +" }}}1 + +" vim: set sw=4 sts=4 et fdm=marker: diff --git a/vim/bundle/syntastic/plugin/syntastic/highlighting.vim b/vim/bundle/syntastic/plugin/syntastic/highlighting.vim new file mode 100644 index 0000000..a9e1a08 --- /dev/null +++ b/vim/bundle/syntastic/plugin/syntastic/highlighting.vim @@ -0,0 +1,104 @@ +if exists('g:loaded_syntastic_notifier_highlighting') || !exists('g:loaded_syntastic_plugin') + finish +endif +let g:loaded_syntastic_notifier_highlighting = 1 + +" Highlighting requires getmatches introduced in 7.1.040 +let s:has_highlighting = v:version > 701 || (v:version == 701 && has('patch040')) +lockvar s:has_highlighting + +let g:SyntasticHighlightingNotifier = {} + +let s:setup_done = 0 + +" Public methods {{{1 + +function! g:SyntasticHighlightingNotifier.New() abort " {{{2 + let newObj = copy(self) + + if !s:setup_done + call self._setup() + let s:setup_done = 1 + lockvar s:setup_done + endif + + return newObj +endfunction " }}}2 + +function! g:SyntasticHighlightingNotifier.enabled() abort " {{{2 + return s:has_highlighting && syntastic#util#var('enable_highlighting') +endfunction " }}}2 + +" Sets error highlights in the current window +function! g:SyntasticHighlightingNotifier.refresh(loclist) abort " {{{2 + if self.enabled() + call syntastic#log#debug(g:_SYNTASTIC_DEBUG_NOTIFICATIONS, 'highlighting: refresh') + call self._reset() + let buf = bufnr('') + let issues = filter(a:loclist.copyRaw(), 'v:val["bufnr"] == buf') + for item in issues + let group = 'Syntastic' . get(item, 'subtype', '') . ( item['type'] ==? 'E' ? 'Error' : 'Warning' ) + + " The function `Syntastic_{filetype}_{checker}_GetHighlightRegex` is + " used to override default highlighting. + if has_key(item, 'hl') + call matchadd(group, '\%' . item['lnum'] . 'l' . item['hl']) + elseif get(item, 'col', 0) + if get(item, 'vcol', 0) + let lastcol = virtcol([item['lnum'], '$']) + let coltype = 'v' + else + let lastcol = col([item['lnum'], '$']) + let coltype = 'c' + endif + let lcol = min([lastcol, item['col']]) + + call matchadd(group, '\%' . item['lnum'] . 'l\%' . lcol . coltype) + endif + endfor + endif +endfunction " }}}2 + +" Remove all error highlights from the window +" @vimlint(EVL103, 1, a:loclist) +function! g:SyntasticHighlightingNotifier.reset(loclist) abort " {{{2 + if s:has_highlighting + call syntastic#log#debug(g:_SYNTASTIC_DEBUG_NOTIFICATIONS, 'highlighting: reset') + call self._reset() + endif +endfunction " }}}2 +" @vimlint(EVL103, 0, a:loclist) + +" }}}1 + +" Private methods {{{1 + +" One time setup: define our own highlighting +function! g:SyntasticHighlightingNotifier._setup() abort " {{{2 + if s:has_highlighting + if !hlexists('SyntasticError') + highlight link SyntasticError SpellBad + endif + if !hlexists('SyntasticWarning') + highlight link SyntasticWarning SpellCap + endif + if !hlexists('SyntasticStyleError') + highlight link SyntasticStyleError SyntasticError + endif + if !hlexists('SyntasticStyleWarning') + highlight link SyntasticStyleWarning SyntasticWarning + endif + endif +endfunction " }}}2 + +function! g:SyntasticHighlightingNotifier._reset() abort " {{{2 + for match in getmatches() + if stridx(match['group'], 'Syntastic') == 0 + call matchdelete(match['id']) + endif + endfor +endfunction " }}}2 + +" }}}1 + +" vim: set sw=4 sts=4 et fdm=marker: diff --git a/vim/bundle/syntastic/plugin/syntastic/loclist.vim b/vim/bundle/syntastic/plugin/syntastic/loclist.vim new file mode 100644 index 0000000..3e9528b --- /dev/null +++ b/vim/bundle/syntastic/plugin/syntastic/loclist.vim @@ -0,0 +1,439 @@ +if exists('g:loaded_syntastic_loclist') || !exists('g:loaded_syntastic_plugin') + finish +endif +let g:loaded_syntastic_loclist = 1 + +let g:SyntasticLoclist = {} + +" Public methods {{{1 + +function! g:SyntasticLoclist.New(rawLoclist) abort " {{{2 + let newObj = copy(self) + + let llist = filter(copy(a:rawLoclist), 'v:val["valid"] == 1') + + for e in llist + if get(e, 'type', '') ==# '' + let e['type'] = 'E' + endif + endfor + + let newObj._rawLoclist = llist + let newObj._name = '' + let newObj._owner = bufnr('') + let newObj._sorted = 0 + let newObj._columns = g:syntastic_cursor_columns + + return newObj +endfunction " }}}2 + +function! g:SyntasticLoclist.current() abort " {{{2 + if !exists('b:syntastic_loclist') || empty(b:syntastic_loclist) + let b:syntastic_loclist = g:SyntasticLoclist.New([]) + endif + return b:syntastic_loclist +endfunction " }}}2 + +function! g:SyntasticLoclist.extend(other) abort " {{{2 + let list = self.copyRaw() + call extend(list, a:other.copyRaw()) + return g:SyntasticLoclist.New(list) +endfunction " }}}2 + +function! g:SyntasticLoclist.sort() abort " {{{2 + if !self._sorted + for e in self._rawLoclist + call s:_set_screen_column(e) + endfor + + call sort(self._rawLoclist, self._columns ? 's:_compare_error_items_by_columns' : 's:_compare_error_items_by_lines') + + let self._sorted = 1 + endif +endfunction " }}}2 + +function! g:SyntasticLoclist.isEmpty() abort " {{{2 + return empty(self._rawLoclist) +endfunction " }}}2 + +function! g:SyntasticLoclist.isNewerThan(stamp) abort " {{{2 + if !exists('self._stamp') + let self._stamp = [] + return 0 + endif + return syntastic#util#compareLexi(self._stamp, a:stamp) > 0 +endfunction " }}}2 + +function! g:SyntasticLoclist.copyRaw() abort " {{{2 + return copy(self._rawLoclist) +endfunction " }}}2 + +function! g:SyntasticLoclist.getRaw() abort " {{{2 + return self._rawLoclist +endfunction " }}}2 + +function! g:SyntasticLoclist.getBuffers() abort " {{{2 + return syntastic#util#unique(map(copy(self._rawLoclist), 'str2nr(v:val["bufnr"])') + [self._owner]) +endfunction " }}}2 + +function! g:SyntasticLoclist.getCursorColumns() abort " {{{2 + return self._columns +endfunction " }}}2 + +function! g:SyntasticLoclist.getStatuslineFlag() abort " {{{2 + if !exists('self._stl_format') + let self._stl_format = '' + endif + if !exists('self._stl_flag') + let self._stl_flag = '' + endif + + if g:syntastic_stl_format !=# self._stl_format + let self._stl_format = g:syntastic_stl_format + + if !empty(self._rawLoclist) + let errors = self.errors() + let warnings = self.warnings() + + let num_errors = len(errors) + let num_warnings = len(warnings) + let num_issues = len(self._rawLoclist) + + let output = self._stl_format + + "hide stuff wrapped in %E(...) unless there are errors + let output = substitute(output, '\m\C%E{\([^}]*\)}', num_errors ? '\1' : '' , 'g') + + "hide stuff wrapped in %W(...) unless there are warnings + let output = substitute(output, '\m\C%W{\([^}]*\)}', num_warnings ? '\1' : '' , 'g') + + "hide stuff wrapped in %B(...) unless there are both errors and warnings + let output = substitute(output, '\m\C%B{\([^}]*\)}', (num_warnings && num_errors) ? '\1' : '' , 'g') + + let flags = { + \ '%': '%', + \ 't': num_issues, + \ 'e': num_errors, + \ 'w': num_warnings, + \ 'N': (num_issues ? fnamemodify( bufname(self._rawLoclist[0]['bufnr']), ':t') : ''), + \ 'P': (num_issues ? fnamemodify( bufname(self._rawLoclist[0]['bufnr']), ':p:~:.') : ''), + \ 'F': (num_issues ? self._rawLoclist[0]['lnum'] : ''), + \ 'ne': (num_errors ? fnamemodify( bufname(errors[0]['bufnr']), ':t') : ''), + \ 'pe': (num_errors ? fnamemodify( bufname(errors[0]['bufnr']), ':p:~:.') : ''), + \ 'fe': (num_errors ? errors[0]['lnum'] : ''), + \ 'nw': (num_warnings ? fnamemodify( bufname(warnings[0]['bufnr']), ':t') : ''), + \ 'pw': (num_warnings ? fnamemodify( bufname(warnings[0]['bufnr']), ':p:~:.') : ''), + \ 'fw': (num_warnings ? warnings[0]['lnum'] : '') } + let output = substitute(output, '\v\C\%(-?\d*%(\.\d+)?)([npf][ew]|[NPFtew%])', '\=syntastic#util#wformat(submatch(1), flags[submatch(2)])', 'g') + + let self._stl_flag = output + else + let self._stl_flag = '' + endif + endif + + return self._stl_flag +endfunction " }}}2 + +function! g:SyntasticLoclist.getFirstError(...) abort " {{{2 + let max_issues = len(self._rawLoclist) + if a:0 && a:1 < max_issues + let max_issues = a:1 + endif + + for idx in range(max_issues) + if get(self._rawLoclist[idx], 'type', '') ==? 'E' + return idx + 1 + endif + endfor + + return 0 +endfunction " }}}2 + +function! g:SyntasticLoclist.getName() abort " {{{2 + return len(self._name) +endfunction " }}}2 + +function! g:SyntasticLoclist.setName(name) abort " {{{2 + let self._name = a:name +endfunction " }}}2 + +function! g:SyntasticLoclist.getOwner() abort " {{{2 + return self._owner +endfunction " }}}2 + +function! g:SyntasticLoclist.setOwner(buffer) abort " {{{2 + let self._owner = type(a:buffer) == type(0) ? a:buffer : str2nr(a:buffer) +endfunction " }}}2 + +function! g:SyntasticLoclist.deploy() abort " {{{2 + call self.setOwner(bufnr('')) + let self._stamp = syntastic#util#stamp() + for buf in self.getBuffers() + call setbufvar(buf, 'syntastic_loclist', self) + endfor +endfunction " }}}2 + +function! g:SyntasticLoclist.destroy() abort " {{{2 + for buf in self.getBuffers() + call setbufvar(buf, 'syntastic_loclist', {}) + endfor +endfunction " }}}2 + +function! g:SyntasticLoclist.decorate(tag) abort " {{{2 + for e in self._rawLoclist + let e['text'] .= ' [' . a:tag . ']' + endfor +endfunction " }}}2 + +function! g:SyntasticLoclist.balloons() abort " {{{2 + if !exists('self._cachedBalloons') + let sep = has('balloon_multiline') ? "\n" : ' | ' + + let self._cachedBalloons = {} + for e in self._rawLoclist + let buf = e['bufnr'] + + if !has_key(self._cachedBalloons, buf) + let self._cachedBalloons[buf] = {} + endif + + if has_key(self._cachedBalloons[buf], e['lnum']) + let self._cachedBalloons[buf][e['lnum']] .= sep . e['text'] + else + let self._cachedBalloons[buf][e['lnum']] = e['text'] + endif + endfor + endif + + return get(self._cachedBalloons, bufnr(''), {}) +endfunction " }}}2 + +function! g:SyntasticLoclist.errors() abort " {{{2 + if !exists('self._cachedErrors') + let self._cachedErrors = self.filter({'type': 'E'}) + endif + return self._cachedErrors +endfunction " }}}2 + +function! g:SyntasticLoclist.warnings() abort " {{{2 + if !exists('self._cachedWarnings') + let self._cachedWarnings = self.filter({'type': 'W'}) + endif + return self._cachedWarnings +endfunction " }}}2 + +" Legacy function. Syntastic no longer calls it, but we keep it +" around because other plugins (f.i. powerline) depend on it. +function! g:SyntasticLoclist.hasErrorsOrWarningsToDisplay() abort " {{{2 + return !self.isEmpty() +endfunction " }}}2 + +" cache used by EchoCurrentError() +function! g:SyntasticLoclist.messages(buf) abort " {{{2 + if !exists('self._cachedMessages') + let self._cachedMessages = {} + + let errors = self.errors() + self.warnings() + for e in errors + let b = e['bufnr'] + let l = e['lnum'] + + if !has_key(self._cachedMessages, b) + let self._cachedMessages[b] = {} + endif + + if !has_key(self._cachedMessages[b], l) + let self._cachedMessages[b][l] = [e] + elseif self._columns + call add(self._cachedMessages[b][l], e) + endif + endfor + + if self._columns + if !self._sorted + for b in keys(self._cachedMessages) + for l in keys(self._cachedMessages[b]) + if len(self._cachedMessages[b][l]) > 1 + for e in self._cachedMessages[b][l] + call s:_set_screen_column(e) + endfor + call sort(self._cachedMessages[b][l], 's:_compare_error_items_by_columns') + endif + endfor + endfor + endif + + for b in keys(self._cachedMessages) + for l in keys(self._cachedMessages[b]) + call s:_remove_shadowed_items(self._cachedMessages[b][l]) + endfor + endfor + endif + endif + + return get(self._cachedMessages, a:buf, {}) +endfunction " }}}2 + +"Filter the list and return new native loclist +"e.g. +" .filter({'bufnr': 10, 'type': 'e'}) +" +"would return all errors for buffer 10. +" +"Note that all comparisons are done with ==? +function! g:SyntasticLoclist.filter(filters) abort " {{{2 + let conditions = values(map(copy(a:filters), 's:_translate(v:key, v:val)')) + let filter = len(conditions) == 1 ? + \ conditions[0] : join(map(conditions, '"(" . v:val . ")"'), ' && ') + return filter(copy(self._rawLoclist), filter) +endfunction " }}}2 + +function! g:SyntasticLoclist.setloclist() abort " {{{2 + if !exists('w:syntastic_loclist_set') + let w:syntastic_loclist_set = [] + endif + if empty(w:syntastic_loclist_set) || w:syntastic_loclist_set != [bufnr(''), b:changedtick] + let replace = g:syntastic_reuse_loc_lists && !empty(w:syntastic_loclist_set) + call syntastic#log#debug(g:_SYNTASTIC_DEBUG_NOTIFICATIONS, 'loclist: setloclist ' . (replace ? '(replace)' : '(new)')) + call setloclist(0, self.getRaw(), replace ? 'r' : ' ') + call syntastic#util#setChangedtick() + let w:syntastic_loclist_set = [bufnr(''), b:syntastic_changedtick] + endif +endfunction " }}}2 + +"display the cached errors for this buf in the location list +function! g:SyntasticLoclist.show() abort " {{{2 + call syntastic#log#debug(g:_SYNTASTIC_DEBUG_NOTIFICATIONS, 'loclist: show') + call self.setloclist() + + if !self.isEmpty() + let num = winnr() + execute 'lopen ' . syntastic#util#var('loc_list_height') + if num != winnr() + execute num . 'wincmd w' + endif + + " try to find the loclist window and set w:quickfix_title + let errors = getloclist(0) + for buf in tabpagebuflist() + if buflisted(buf) && bufloaded(buf) && getbufvar(buf, '&buftype') ==# 'quickfix' + let win = bufwinnr(buf) + let title = getwinvar(win, 'quickfix_title') + + " TODO: try to make sure we actually own this window; sadly, + " errors == getloclist(0) is the only somewhat safe way to + " achieve that + if strpart(title, 0, 16) ==# ':SyntasticCheck ' || + \ ( (title ==# '' || title ==# ':setloclist()') && errors == getloclist(0) ) + call setwinvar(win, 'quickfix_title', ':SyntasticCheck ' . self._name) + call setbufvar(buf, 'syntastic_owner_buffer', self._owner) + endif + endif + endfor + endif +endfunction " }}}2 + +" }}}1 + +" Public functions {{{1 + +function! SyntasticLoclistHide() abort " {{{2 + call syntastic#log#debug(g:_SYNTASTIC_DEBUG_NOTIFICATIONS, 'loclist: hide') + silent! lclose +endfunction " }}}2 + +" }}}1 + +" Utilities {{{1 + +function! s:_translate(key, val) abort " {{{2 + return 'get(v:val, ' . string(a:key) . ', "") ==? ' . string(a:val) +endfunction " }}}2 + +function! s:_set_screen_column(item) abort " {{{2 + if !has_key(a:item, 'scol') + let col = get(a:item, 'col', 0) + if col != 0 && get(a:item, 'vcol', 0) == 0 + let buf = str2nr(a:item['bufnr']) + try + let line = getbufline(buf, a:item['lnum'])[0] + catch /\m^Vim\%((\a\+)\)\=:E684/ + let line = '' + endtry + let a:item['scol'] = syntastic#util#screenWidth(strpart(line, 0, col), getbufvar(buf, '&tabstop')) + else + let a:item['scol'] = col + endif + endif +endfunction " }}}2 + +function! s:_remove_shadowed_items(errors) abort " {{{2 + " keep only the first message at a given column + let i = 0 + while i < len(a:errors) - 1 + let j = i + 1 + let dupes = 0 + while j < len(a:errors) && a:errors[j].scol == a:errors[i].scol + let dupes = 1 + let j += 1 + endwhile + if dupes + call remove(a:errors, i + 1, j - 1) + endif + let i += 1 + endwhile + + " merge messages with the same text + let i = 0 + while i < len(a:errors) - 1 + let j = i + 1 + let dupes = 0 + while j < len(a:errors) && a:errors[j].text == a:errors[i].text + let dupes = 1 + let j += 1 + endwhile + if dupes + call remove(a:errors, i + 1, j - 1) + endif + let i += 1 + endwhile +endfunction " }}}2 + +function! s:_compare_error_items_by_columns(a, b) abort " {{{2 + if a:a['bufnr'] != a:b['bufnr'] + " group by file + return a:a['bufnr'] - a:b['bufnr'] + elseif a:a['lnum'] != a:b['lnum'] + " sort by line + return a:a['lnum'] - a:b['lnum'] + elseif a:a['scol'] != a:b['scol'] + " sort by screen column + return a:a['scol'] - a:b['scol'] + elseif a:a['type'] !=? a:b['type'] + " errors take precedence over warnings + return a:a['type'] ==? 'E' ? -1 : 1 + else + return 0 + endif +endfunction " }}}2 + +function! s:_compare_error_items_by_lines(a, b) abort " {{{2 + if a:a['bufnr'] != a:b['bufnr'] + " group by file + return a:a['bufnr'] - a:b['bufnr'] + elseif a:a['lnum'] != a:b['lnum'] + " sort by line + return a:a['lnum'] - a:b['lnum'] + elseif a:a['type'] !=? a:b['type'] + " errors take precedence over warnings + return a:a['type'] ==? 'E' ? -1 : 1 + else + " sort by screen column + return a:a['scol'] - a:b['scol'] + endif +endfunction " }}}2 + +" }}}1 + +" vim: set sw=4 sts=4 et fdm=marker: diff --git a/vim/bundle/syntastic/plugin/syntastic/modemap.vim b/vim/bundle/syntastic/plugin/syntastic/modemap.vim new file mode 100644 index 0000000..501c82b --- /dev/null +++ b/vim/bundle/syntastic/plugin/syntastic/modemap.vim @@ -0,0 +1,117 @@ +if exists('g:loaded_syntastic_modemap') || !exists('g:loaded_syntastic_plugin') + finish +endif +let g:loaded_syntastic_modemap = 1 + +let g:SyntasticModeMap = {} + +" Public methods {{{1 + +function! g:SyntasticModeMap.Instance() abort " {{{2 + if !exists('s:SyntasticModeMapInstance') + let s:SyntasticModeMapInstance = copy(self) + call s:SyntasticModeMapInstance.synch() + endif + + return s:SyntasticModeMapInstance +endfunction " }}}2 + +function! g:SyntasticModeMap.synch() abort " {{{2 + if exists('g:syntastic_mode_map') + let self._mode = get(g:syntastic_mode_map, 'mode', 'active') + let self._activeFiletypes = copy(get(g:syntastic_mode_map, 'active_filetypes', [])) + let self._passiveFiletypes = copy(get(g:syntastic_mode_map, 'passive_filetypes', [])) + else + let self._mode = 'active' + let self._activeFiletypes = [] + let self._passiveFiletypes = [] + endif +endfunction " }}}2 + +function! g:SyntasticModeMap.allowsAutoChecking(filetype) abort " {{{2 + let fts = split(a:filetype, '\m\.') + + if self.isPassive() + return self._isOneFiletypeActive(fts) + else + return self._noFiletypesArePassive(fts) + endif +endfunction " }}}2 + +function! g:SyntasticModeMap.doAutoChecking() abort " {{{2 + let local_mode = get(b:, 'syntastic_mode', '') + if local_mode ==# 'active' || local_mode ==# 'passive' + return local_mode ==# 'active' + endif + + return self.allowsAutoChecking(&filetype) +endfunction " }}}2 + +function! g:SyntasticModeMap.isPassive() abort " {{{2 + return self._mode ==# 'passive' +endfunction " }}}2 + +function! g:SyntasticModeMap.toggleMode() abort " {{{2 + call self.synch() + + if self._mode ==# 'active' + let self._mode = 'passive' + else + let self._mode = 'active' + endif + + "XXX Changing a global variable. Tsk, tsk... + if !exists('g:syntastic_mode_map') + let g:syntastic_mode_map = {} + endif + let g:syntastic_mode_map['mode'] = self._mode +endfunction " }}}2 + +function! g:SyntasticModeMap.echoMode() abort " {{{2 + echo 'Syntastic: ' . self._mode . ' mode enabled' +endfunction " }}}2 + +function! g:SyntasticModeMap.modeInfo(filetypes) abort " {{{2 + echomsg 'Syntastic version: ' . g:_SYNTASTIC_VERSION . ' (Vim ' . v:version . ', ' . g:_SYNTASTIC_UNAME . ')' + let type = len(a:filetypes) ? a:filetypes[0] : &filetype + echomsg 'Info for filetype: ' . type + + call self.synch() + echomsg 'Global mode: ' . self._mode + if self._mode ==# 'active' + if len(self._passiveFiletypes) + let plural = len(self._passiveFiletypes) != 1 ? 's' : '' + echomsg 'Passive filetype' . plural . ': ' . join(sort(copy(self._passiveFiletypes))) + endif + else + if len(self._activeFiletypes) + let plural = len(self._activeFiletypes) != 1 ? 's' : '' + echomsg 'Active filetype' . plural . ': ' . join(sort(copy(self._activeFiletypes))) + endif + endif + echomsg 'Filetype ' . type . ' is ' . (self.allowsAutoChecking(type) ? 'active' : 'passive') + + if !len(a:filetypes) + if exists('b:syntastic_mode') && (b:syntastic_mode ==# 'active' || b:syntastic_mode ==# 'passive') + echomsg 'Local mode: ' . b:syntastic_mode + endif + + echomsg 'The current file will ' . (self.doAutoChecking() ? '' : 'not ') . 'be checked automatically' + endif +endfunction " }}}2 + +" }}}1 + +" Private methods {{{1 + +function! g:SyntasticModeMap._isOneFiletypeActive(filetypes) abort " {{{2 + return !empty(filter(copy(a:filetypes), 'index(self._activeFiletypes, v:val) != -1')) +endfunction " }}}2 + +function! g:SyntasticModeMap._noFiletypesArePassive(filetypes) abort " {{{2 + return empty(filter(copy(a:filetypes), 'index(self._passiveFiletypes, v:val) != -1')) +endfunction " }}}2 + +" }}}1 + +" vim: set sw=4 sts=4 et fdm=marker: diff --git a/vim/bundle/syntastic/plugin/syntastic/notifiers.vim b/vim/bundle/syntastic/plugin/syntastic/notifiers.vim new file mode 100644 index 0000000..fe158ca --- /dev/null +++ b/vim/bundle/syntastic/plugin/syntastic/notifiers.vim @@ -0,0 +1,86 @@ +if exists('g:loaded_syntastic_notifiers') || !exists('g:loaded_syntastic_plugin') + finish +endif +let g:loaded_syntastic_notifiers = 1 + +let g:SyntasticNotifiers = {} + +let s:_NOTIFIER_TYPES = ['signs', 'balloons', 'highlighting', 'cursor', 'autoloclist'] +lockvar! s:_NOTIFIER_TYPES + +let s:_PERSISTENT_NOTIFIERS = ['signs', 'balloons'] +lockvar! s:_PERSISTENT_NOTIFIERS + +" Public methods {{{1 + +function! g:SyntasticNotifiers.Instance() abort " {{{2 + if !exists('s:SyntasticNotifiersInstance') + let s:SyntasticNotifiersInstance = copy(self) + call s:SyntasticNotifiersInstance._initNotifiers() + endif + + return s:SyntasticNotifiersInstance +endfunction " }}}2 + +function! g:SyntasticNotifiers.refresh(loclist) abort " {{{2 + if !a:loclist.isEmpty() && !a:loclist.isNewerThan([]) + " loclist not fully constructed yet + return + endif + + call syntastic#log#debug(g:_SYNTASTIC_DEBUG_NOTIFICATIONS, 'notifiers: refresh') + for type in self._enabled_types + let class = substitute(type, '\m.*', 'Syntastic\u&Notifier', '') + if !has_key(g:{class}, 'enabled') || self._notifier[type].enabled() + if index(s:_PERSISTENT_NOTIFIERS, type) > -1 + " refresh only if loclist has changed since last call + if !exists('b:syntastic_private_' . type . '_stamp') + let b:syntastic_private_{type}_stamp = [] + endif + if a:loclist.isNewerThan(b:syntastic_private_{type}_stamp) || a:loclist.isEmpty() + call self._notifier[type].refresh(a:loclist) + let b:syntastic_private_{type}_stamp = syntastic#util#stamp() + endif + else + call self._notifier[type].refresh(a:loclist) + endif + endif + endfor +endfunction " }}}2 + +function! g:SyntasticNotifiers.reset(loclist) abort " {{{2 + call syntastic#log#debug(g:_SYNTASTIC_DEBUG_NOTIFICATIONS, 'notifiers: reset') + for type in self._enabled_types + let class = substitute(type, '\m.*', 'Syntastic\u&Notifier', '') + + " reset notifiers regardless if they are enabled or not, since + " the user might have disabled them since the last refresh(); + " notifiers MUST be prepared to deal with reset() when disabled + if has_key(g:{class}, 'reset') + call self._notifier[type].reset(a:loclist) + endif + + " also reset stamps + if index(s:_PERSISTENT_NOTIFIERS, type) > -1 + let b:syntastic_private_{type}_stamp = [] + endif + endfor +endfunction " }}}2 + +" }}}1 + +" Private methods {{{1 + +function! g:SyntasticNotifiers._initNotifiers() abort " {{{2 + let self._notifier = {} + for type in s:_NOTIFIER_TYPES + let class = substitute(type, '\m.*', 'Syntastic\u&Notifier', '') + let self._notifier[type] = g:{class}.New() + endfor + + let self._enabled_types = copy(s:_NOTIFIER_TYPES) +endfunction " }}}2 + +" }}}1 + +" vim: set sw=4 sts=4 et fdm=marker: diff --git a/vim/bundle/syntastic/plugin/syntastic/registry.vim b/vim/bundle/syntastic/plugin/syntastic/registry.vim new file mode 100644 index 0000000..0c2d261 --- /dev/null +++ b/vim/bundle/syntastic/plugin/syntastic/registry.vim @@ -0,0 +1,375 @@ +if exists('g:loaded_syntastic_registry') || !exists('g:loaded_syntastic_plugin') + finish +endif +let g:loaded_syntastic_registry = 1 + +" Initialisation {{{1 + +let s:_DEFAULT_CHECKERS = { + \ 'actionscript': ['mxmlc'], + \ 'ada': ['gcc'], + \ 'ansible': ['ansible_lint'], + \ 'apiblueprint': ['drafter'], + \ 'applescript': ['osacompile'], + \ 'asciidoc': ['asciidoc'], + \ 'asm': ['gcc'], + \ 'bro': ['bro'], + \ 'bemhtml': ['bemhtmllint'], + \ 'c': ['gcc'], + \ 'cabal': ['cabal'], + \ 'chef': ['foodcritic'], + \ 'co': ['coco'], + \ 'cobol': ['cobc'], + \ 'coffee': ['coffee', 'coffeelint'], + \ 'coq': ['coqtop'], + \ 'cpp': ['gcc'], + \ 'cs': ['mcs'], + \ 'css': ['csslint'], + \ 'cucumber': ['cucumber'], + \ 'cuda': ['nvcc'], + \ 'd': ['dmd'], + \ 'dart': ['dartanalyzer'], + \ 'docbk': ['xmllint'], + \ 'dockerfile': ['dockerfile_lint'], + \ 'dustjs': ['swiffer'], + \ 'elixir': [], + \ 'erlang': ['escript'], + \ 'eruby': ['ruby'], + \ 'fortran': ['gfortran'], + \ 'glsl': ['cgc'], + \ 'go': [], + \ 'haml': ['haml'], + \ 'handlebars': ['handlebars'], + \ 'haskell': ['hdevtools', 'hlint'], + \ 'haxe': ['haxe'], + \ 'hss': ['hss'], + \ 'html': ['tidy'], + \ 'jade': ['jade_lint'], + \ 'java': ['javac'], + \ 'javascript': ['jshint', 'jslint'], + \ 'json': ['jsonlint', 'jsonval'], + \ 'less': ['lessc'], + \ 'lex': ['flex'], + \ 'limbo': ['limbo'], + \ 'lisp': ['clisp'], + \ 'llvm': ['llvm'], + \ 'lua': ['luac'], + \ 'markdown': ['mdl'], + \ 'matlab': ['mlint'], + \ 'mercury': ['mmc'], + \ 'nasm': ['nasm'], + \ 'nix': ['nix'], + \ 'nroff': ['mandoc'], + \ 'objc': ['gcc'], + \ 'objcpp': ['gcc'], + \ 'ocaml': ['camlp4o'], + \ 'perl': ['perlcritic'], + \ 'php': ['php', 'phpcs', 'phpmd'], + \ 'po': ['msgfmt'], + \ 'pod': ['podchecker'], + \ 'puppet': ['puppet', 'puppetlint'], + \ 'pug': ['pug_lint'], + \ 'python': ['python', 'flake8', 'pylint'], + \ 'qml': ['qmllint'], + \ 'r': [], + \ 'rmd': [], + \ 'racket': ['racket'], + \ 'rnc': ['rnv'], + \ 'rst': ['rst2pseudoxml'], + \ 'ruby': ['mri'], + \ 'sass': ['sass'], + \ 'scala': ['fsc', 'scalac'], + \ 'scss': ['sass', 'scss_lint'], + \ 'sh': ['sh', 'shellcheck'], + \ 'slim': ['slimrb'], + \ 'sml': ['smlnj'], + \ 'spec': ['rpmlint'], + \ 'sql': ['sqlint'], + \ 'stylus': ['stylint'], + \ 'tcl': ['nagelfar'], + \ 'tex': ['lacheck', 'chktex'], + \ 'texinfo': ['makeinfo'], + \ 'text': [], + \ 'trig': ['rapper'], + \ 'turtle': ['rapper'], + \ 'twig': ['twiglint'], + \ 'typescript': ['tsc'], + \ 'vala': ['valac'], + \ 'verilog': ['verilator'], + \ 'vhdl': ['ghdl'], + \ 'vim': ['vimlint'], + \ 'xhtml': ['tidy'], + \ 'xml': ['xmllint'], + \ 'xslt': ['xmllint'], + \ 'xquery': ['basex'], + \ 'yacc': ['bison'], + \ 'yaml': ['jsyaml'], + \ 'yang': ['pyang'], + \ 'z80': ['z80syntaxchecker'], + \ 'zpt': ['zptlint'], + \ 'zsh': ['zsh'], + \ } +lockvar! s:_DEFAULT_CHECKERS + +let s:_DEFAULT_FILETYPE_MAP = { + \ 'gentoo-metadata': 'xml', + \ 'groff': 'nroff', + \ 'lhaskell': 'haskell', + \ 'litcoffee': 'coffee', + \ 'mail': 'text', + \ 'mkd': 'markdown', + \ 'pe-puppet': 'puppet', + \ 'sgml': 'docbk', + \ 'sgmllnx': 'docbk', + \ } +lockvar! s:_DEFAULT_FILETYPE_MAP + +let s:_ECLIM_TYPES = [ + \ 'c', + \ 'cpp', + \ 'html', + \ 'java', + \ 'php', + \ 'python', + \ 'ruby', + \ ] +lockvar! s:_ECLIM_TYPES + +let s:_YCM_TYPES = [ + \ 'c', + \ 'cpp', + \ 'objc', + \ 'objcpp', + \ ] +lockvar! s:_YCM_TYPES + +let g:SyntasticRegistry = {} + +" }}}1 + +" Public methods {{{1 + +" Note: Handling of filetype aliases: all public methods take aliases as +" parameters, all private methods take normalized filetypes. Public methods +" are thus supposed to normalize filetypes before calling private methods. + +function! g:SyntasticRegistry.Instance() abort " {{{2 + if !exists('s:SyntasticRegistryInstance') + let s:SyntasticRegistryInstance = copy(self) + let s:SyntasticRegistryInstance._checkerMap = {} + endif + + return s:SyntasticRegistryInstance +endfunction " }}}2 + +function! g:SyntasticRegistry.CreateAndRegisterChecker(args) abort " {{{2 + let registry = g:SyntasticRegistry.Instance() + + if has_key(a:args, 'redirect') + let [ft, name] = split(a:args['redirect'], '/') + call registry._loadCheckersFor(ft, 1) + + let clone = get(registry._checkerMap[ft], name, {}) + if empty(clone) + throw 'Syntastic: Checker ' . a:args['redirect'] . ' redirects to unregistered checker ' . ft . '/' . name + endif + + let checker = g:SyntasticChecker.New(a:args, clone) + else + let checker = g:SyntasticChecker.New(a:args) + endif + call registry._registerChecker(checker) +endfunction " }}}2 + +" Given a list of checker names hints_list, return a map name --> checker. +" If hints_list is empty, user settings are are used instead. Checkers are +" not checked for availability (that is, the corresponding IsAvailable() are +" not run). +function! g:SyntasticRegistry.getCheckers(ftalias, hints_list) abort " {{{2 + let ft = s:_normalise_filetype(a:ftalias) + call self._loadCheckersFor(ft, 0) + + let checkers_map = self._checkerMap[ft] + if empty(checkers_map) + return [] + endif + + call self._checkDeprecation(ft) + + let names = + \ !empty(a:hints_list) ? syntastic#util#unique(a:hints_list) : + \ exists('b:syntastic_checkers') ? b:syntastic_checkers : + \ exists('g:syntastic_' . ft . '_checkers') ? g:syntastic_{ft}_checkers : + \ get(s:_DEFAULT_CHECKERS, ft, 0) + + return type(names) == type([]) ? + \ self._filterCheckersByName(checkers_map, names) : [checkers_map[keys(checkers_map)[0]]] +endfunction " }}}2 + +" Same as getCheckers(), but keep only the available checkers. This runs the +" corresponding IsAvailable() functions for all checkers. +function! g:SyntasticRegistry.getCheckersAvailable(ftalias, hints_list) abort " {{{2 + return filter(self.getCheckers(a:ftalias, a:hints_list), 'v:val.isAvailable()') +endfunction " }}}2 + +" Same as getCheckers(), but keep only the checkers that are available and +" disabled. This runs the corresponding IsAvailable() functions for all checkers. +function! g:SyntasticRegistry.getCheckersDisabled(ftalias, hints_list) abort " {{{2 + return filter(self.getCheckers(a:ftalias, a:hints_list), 'v:val.isDisabled() && v:val.isAvailable()') +endfunction " }}}2 + +function! g:SyntasticRegistry.getKnownFiletypes() abort " {{{2 + let types = keys(s:_DEFAULT_CHECKERS) + + call extend(types, keys(s:_DEFAULT_FILETYPE_MAP)) + + if exists('g:syntastic_filetype_map') + call extend(types, keys(g:syntastic_filetype_map)) + endif + + if exists('g:syntastic_extra_filetypes') && type(g:syntastic_extra_filetypes) == type([]) + call extend(types, g:syntastic_extra_filetypes) + endif + + return syntastic#util#unique(types) +endfunction " }}}2 + +function! g:SyntasticRegistry.getNamesOfAvailableCheckers(ftalias) abort " {{{2 + let ft = s:_normalise_filetype(a:ftalias) + call self._loadCheckersFor(ft, 0) + return keys(filter( copy(self._checkerMap[ft]), 'v:val.isAvailable()' )) +endfunction " }}}2 + +function! g:SyntasticRegistry.echoInfoFor(ftalias_list) abort " {{{2 + let ft_list = syntastic#util#unique(map( copy(a:ftalias_list), 's:_normalise_filetype(v:val)' )) + if len(ft_list) != 1 + let available = [] + let active = [] + let disabled = [] + + for ft in ft_list + call extend(available, map( self.getNamesOfAvailableCheckers(ft), 'ft . "/" . v:val' )) + call extend(active, map( self.getCheckersAvailable(ft, []), 'ft . "/" . v:val.getName()' )) + call extend(disabled, map( self.getCheckersDisabled(ft, []), 'ft . "/" . v:val.getName()' )) + endfor + else + let ft = ft_list[0] + let available = self.getNamesOfAvailableCheckers(ft) + let active = map(self.getCheckersAvailable(ft, []), 'v:val.getName()') + let disabled = map(self.getCheckersDisabled(ft, []), 'v:val.getName()') + endif + + let cnt = len(available) + let plural = cnt != 1 ? 's' : '' + let cklist = cnt ? join(sort(available)) : '-' + echomsg 'Available checker' . plural . ': ' . cklist + + let cnt = len(active) + let plural = cnt != 1 ? 's' : '' + let cklist = cnt ? join(active) : '-' + echomsg 'Currently enabled checker' . plural . ': ' . cklist + + let cnt = len(disabled) + let plural = cnt != 1 ? 's' : '' + if len(disabled) + let cklist = join(sort(disabled)) + echomsg 'Checker' . plural . ' disabled for security reasons: ' . cklist + endif + + " Eclim feels entitled to mess with syntastic's variables {{{3 + if exists(':EclimValidate') && get(g:, 'EclimFileTypeValidate', 1) + let disabled = filter(copy(ft_list), 's:_disabled_by_eclim(v:val)') + let cnt = len(disabled) + if cnt + let plural = cnt != 1 ? 's' : '' + let cklist = join(disabled, ', ') + echomsg 'Checkers for filetype' . plural . ' ' . cklist . ' possibly disabled by Eclim' + endif + endif + " }}}3 + + " So does YouCompleteMe {{{3 + if exists('g:loaded_youcompleteme') && get(g:, 'ycm_show_diagnostics_ui', get(g:, 'ycm_register_as_syntastic_checker', 1)) + let disabled = filter(copy(ft_list), 's:_disabled_by_ycm(v:val)') + let cnt = len(disabled) + if cnt + let plural = cnt != 1 ? 's' : '' + let cklist = join(disabled, ', ') + echomsg 'Checkers for filetype' . plural . ' ' . cklist . ' possibly disabled by YouCompleteMe' + endif + endif + " }}}3 +endfunction " }}}2 + +" }}}1 + +" Private methods {{{1 + +function! g:SyntasticRegistry._registerChecker(checker) abort " {{{2 + let ft = a:checker.getFiletype() + if !has_key(self._checkerMap, ft) + let self._checkerMap[ft] = {} + endif + + let name = a:checker.getName() + if has_key(self._checkerMap[ft], name) + throw 'Syntastic: Duplicate syntax checker name: ' . ft . '/' . name + endif + + let self._checkerMap[ft][name] = a:checker +endfunction " }}}2 + +function! g:SyntasticRegistry._filterCheckersByName(checkers_map, list) abort " {{{2 + return filter( map(copy(a:list), 'get(a:checkers_map, v:val, {})'), '!empty(v:val)' ) +endfunction " }}}2 + +function! g:SyntasticRegistry._loadCheckersFor(filetype, force) abort " {{{2 + if !a:force && has_key(self._checkerMap, a:filetype) + return + endif + + execute 'runtime! syntax_checkers/' . a:filetype . '/*.vim' + + if !has_key(self._checkerMap, a:filetype) + let self._checkerMap[a:filetype] = {} + endif +endfunction " }}}2 + +" Check for obsolete variable g:syntastic_<filetype>_checker +function! g:SyntasticRegistry._checkDeprecation(filetype) abort " {{{2 + if exists('g:syntastic_' . a:filetype . '_checker') && !exists('g:syntastic_' . a:filetype . '_checkers') + let g:syntastic_{a:filetype}_checkers = [g:syntastic_{a:filetype}_checker] + call syntastic#log#oneTimeWarn('variable g:syntastic_' . a:filetype . '_checker is deprecated') + endif +endfunction " }}}2 + +" }}}1 + +" Utilities {{{1 + +"resolve filetype aliases, and replace - with _ otherwise we cant name +"syntax checker functions legally for filetypes like "gentoo-metadata" +function! s:_normalise_filetype(ftalias) abort " {{{2 + let ft = get(s:_DEFAULT_FILETYPE_MAP, a:ftalias, a:ftalias) + let ft = get(g:syntastic_filetype_map, ft, ft) + let ft = substitute(ft, '\m-', '_', 'g') + return ft +endfunction " }}}2 + +function! s:_disabled_by_eclim(filetype) abort " {{{2 + if index(s:_ECLIM_TYPES, a:filetype) >= 0 + let lang = toupper(a:filetype[0]) . a:filetype[1:] + let ft = a:filetype !=# 'cpp' ? lang : 'C' + return get(g:, 'Eclim' . lang . 'Validate', 1) && !get(g:, 'Eclim' . ft . 'SyntasticEnabled', 0) + endif + + return 0 +endfunction " }}}2 + +function! s:_disabled_by_ycm(filetype) abort " {{{2 + return index(s:_YCM_TYPES, a:filetype) >= 0 +endfunction " }}}2 + +" }}}1 + +" vim: set sw=4 sts=4 et fdm=marker: diff --git a/vim/bundle/syntastic/plugin/syntastic/signs.vim b/vim/bundle/syntastic/plugin/syntastic/signs.vim new file mode 100644 index 0000000..e3bafa0 --- /dev/null +++ b/vim/bundle/syntastic/plugin/syntastic/signs.vim @@ -0,0 +1,138 @@ +if exists('g:loaded_syntastic_notifier_signs') || !exists('g:loaded_syntastic_plugin') + finish +endif +let g:loaded_syntastic_notifier_signs = 1 + +" Initialisation {{{1 + +" start counting sign ids at 5000, start here to hopefully avoid conflicting +" with any other code that places signs (not sure if this precaution is +" actually needed) +let s:first_sign_id = 5000 +let s:next_sign_id = s:first_sign_id + +let g:SyntasticSignsNotifier = {} + +let s:setup_done = 0 + +" }}}1 + +" Public methods {{{1 + +function! g:SyntasticSignsNotifier.New() abort " {{{2 + let newObj = copy(self) + return newObj +endfunction " }}}2 + +function! g:SyntasticSignsNotifier.enabled() abort " {{{2 + return has('signs') && syntastic#util#var('enable_signs') +endfunction " }}}2 + +function! g:SyntasticSignsNotifier.refresh(loclist) abort " {{{2 + call syntastic#log#debug(g:_SYNTASTIC_DEBUG_NOTIFICATIONS, 'signs: refresh') + + let old_signs = copy(self._bufSignIds()) + if self.enabled() + if !s:setup_done + call self._setup() + let s:setup_done = 1 + lockvar s:setup_done + endif + + call self._signErrors(a:loclist) + endif + call self._removeSigns(old_signs) +endfunction " }}}2 + +" }}}1 + +" Private methods {{{1 + +" One time setup: define our own sign types and highlighting +function! g:SyntasticSignsNotifier._setup() abort " {{{2 + if has('signs') + if !hlexists('SyntasticErrorSign') + highlight link SyntasticErrorSign error + endif + if !hlexists('SyntasticWarningSign') + highlight link SyntasticWarningSign todo + endif + if !hlexists('SyntasticStyleErrorSign') + highlight link SyntasticStyleErrorSign SyntasticErrorSign + endif + if !hlexists('SyntasticStyleWarningSign') + highlight link SyntasticStyleWarningSign SyntasticWarningSign + endif + if !hlexists('SyntasticStyleErrorLine') + highlight link SyntasticStyleErrorLine SyntasticErrorLine + endif + if !hlexists('SyntasticStyleWarningLine') + highlight link SyntasticStyleWarningLine SyntasticWarningLine + endif + + " define the signs used to display syntax and style errors/warns + execute 'sign define SyntasticError text=' . g:syntastic_error_symbol . + \ ' texthl=SyntasticErrorSign linehl=SyntasticErrorLine' + execute 'sign define SyntasticWarning text=' . g:syntastic_warning_symbol . + \ ' texthl=SyntasticWarningSign linehl=SyntasticWarningLine' + execute 'sign define SyntasticStyleError text=' . g:syntastic_style_error_symbol . + \ ' texthl=SyntasticStyleErrorSign linehl=SyntasticStyleErrorLine' + execute 'sign define SyntasticStyleWarning text=' . g:syntastic_style_warning_symbol . + \ ' texthl=SyntasticStyleWarningSign linehl=SyntasticStyleWarningLine' + endif +endfunction " }}}2 + +" Place signs by all syntax errors in the buffer +function! g:SyntasticSignsNotifier._signErrors(loclist) abort " {{{2 + let loclist = a:loclist + if !loclist.isEmpty() + + let buf = bufnr('') + if !bufloaded(buf) + " signs can be placed only in loaded buffers + return + endif + + " errors come first, so that they are not masked by warnings + let issues = copy(loclist.errors()) + call extend(issues, loclist.warnings()) + call filter(issues, 'v:val["bufnr"] == buf') + let seen = {} + + for i in issues + if i['lnum'] > 0 && !has_key(seen, i['lnum']) + let seen[i['lnum']] = 1 + + let sign_severity = i['type'] ==? 'W' ? 'Warning' : 'Error' + let sign_subtype = get(i, 'subtype', '') + let sign_type = 'Syntastic' . sign_subtype . sign_severity + + execute 'sign place ' . s:next_sign_id . ' line=' . i['lnum'] . ' name=' . sign_type . ' buffer=' . i['bufnr'] + call add(self._bufSignIds(), s:next_sign_id) + let s:next_sign_id += 1 + endif + endfor + endif +endfunction " }}}2 + +" Remove the signs with the given ids from this buffer +function! g:SyntasticSignsNotifier._removeSigns(ids) abort " {{{2 + if has('signs') + for s in reverse(copy(a:ids)) + execute 'sign unplace ' . s + call remove(self._bufSignIds(), index(self._bufSignIds(), s)) + endfor + endif +endfunction " }}}2 + +" Get all the ids of the SyntaxError signs in the buffer +function! g:SyntasticSignsNotifier._bufSignIds() abort " {{{2 + if !exists('b:syntastic_private_sign_ids') + let b:syntastic_private_sign_ids = [] + endif + return b:syntastic_private_sign_ids +endfunction " }}}2 + +" }}}1 + +" vim: set sw=4 sts=4 et fdm=marker: |