aboutsummaryrefslogtreecommitdiff
path: root/vim/bundle/syntastic/autoload
diff options
context:
space:
mode:
Diffstat (limited to 'vim/bundle/syntastic/autoload')
-rw-r--r--vim/bundle/syntastic/autoload/syntastic/c.vim341
-rw-r--r--vim/bundle/syntastic/autoload/syntastic/log.vim222
-rw-r--r--vim/bundle/syntastic/autoload/syntastic/postprocess.vim73
-rw-r--r--vim/bundle/syntastic/autoload/syntastic/preprocess.vim614
-rw-r--r--vim/bundle/syntastic/autoload/syntastic/util.vim552
5 files changed, 1802 insertions, 0 deletions
diff --git a/vim/bundle/syntastic/autoload/syntastic/c.vim b/vim/bundle/syntastic/autoload/syntastic/c.vim
new file mode 100644
index 0000000..e49a29a
--- /dev/null
+++ b/vim/bundle/syntastic/autoload/syntastic/c.vim
@@ -0,0 +1,341 @@
+if exists('g:loaded_syntastic_c_autoload') || !exists('g:loaded_syntastic_plugin')
+ finish
+endif
+let g:loaded_syntastic_c_autoload = 1
+
+let s:save_cpo = &cpo
+set cpo&vim
+
+" Public functions {{{1
+
+" convenience function to determine the 'null device' parameter
+" based on the current operating system
+function! syntastic#c#NullOutput() abort " {{{2
+ let known_os = has('unix') || has('mac') || syntastic#util#isRunningWindows()
+ return known_os ? '-o ' . syntastic#util#DevNull() : ''
+endfunction " }}}2
+
+" read additional compiler flags from the given configuration file
+" the file format and its parsing mechanism is inspired by clang_complete
+function! syntastic#c#ReadConfig(file) abort " {{{2
+ call syntastic#log#debug(g:_SYNTASTIC_DEBUG_CHECKERS, 'ReadConfig: looking for', a:file)
+
+ " search upwards from the current file's directory
+ let config = syntastic#util#findFileInParent(a:file, expand('%:p:h', 1))
+ if config ==# ''
+ call syntastic#log#debug(g:_SYNTASTIC_DEBUG_CHECKERS, 'ReadConfig: file not found')
+ return ''
+ endif
+ call syntastic#log#debug(g:_SYNTASTIC_DEBUG_CHECKERS, 'ReadConfig: config file:', config)
+ if !filereadable(config)
+ call syntastic#log#debug(g:_SYNTASTIC_DEBUG_CHECKERS, 'ReadConfig: file unreadable')
+ return ''
+ endif
+
+ " convert filename into absolute path
+ let filepath = fnamemodify(config, ':p:h')
+
+ " try to read config file
+ try
+ let lines = readfile(config)
+ catch /\m^Vim\%((\a\+)\)\=:E48[45]/
+ call syntastic#log#debug(g:_SYNTASTIC_DEBUG_CHECKERS, 'ReadConfig: error reading file')
+ return ''
+ endtry
+
+ " filter out empty lines and comments
+ call filter(lines, 'v:val !~# ''\v^(\s*#|$)''')
+
+ " remove leading and trailing spaces
+ call map(lines, 'substitute(v:val, ''\m^\s\+'', "", "")')
+ call map(lines, 'substitute(v:val, ''\m\s\+$'', "", "")')
+
+ let parameters = []
+ for line in lines
+ let matches = matchstr(line, '\m\C^\s*-I\s*\zs.\+')
+ if matches !=# ''
+ " this one looks like an absolute path
+ if match(matches, '\m^\%(/\|\a:\)') != -1
+ call add(parameters, '-I' . matches)
+ else
+ call add(parameters, '-I' . filepath . syntastic#util#Slash() . matches)
+ endif
+ else
+ call add(parameters, line)
+ endif
+ endfor
+
+ return join(map(parameters, 'syntastic#util#shescape(v:val)'))
+endfunction " }}}2
+
+" GetLocList() for C-like compilers
+function! syntastic#c#GetLocList(filetype, subchecker, options) abort " {{{2
+ try
+ let flags = s:_get_cflags(a:filetype, a:subchecker, a:options)
+ catch /\m\C^Syntastic: skip checks$/
+ return []
+ endtry
+
+ let makeprg = syntastic#util#shexpand(g:syntastic_{a:filetype}_compiler) .
+ \ ' ' . flags . ' ' . syntastic#util#shexpand('%')
+
+ let errorformat = s:_get_checker_var('g', a:filetype, a:subchecker, 'errorformat', a:options['errorformat'])
+
+ let postprocess = s:_get_checker_var('g', a:filetype, a:subchecker, 'remove_include_errors', 0) ?
+ \ ['filterForeignErrors'] : []
+
+ " process makeprg
+ return SyntasticMake({
+ \ 'makeprg': makeprg,
+ \ 'errorformat': errorformat,
+ \ 'postprocess': postprocess })
+endfunction " }}}2
+
+" }}}1
+
+" Private functions {{{1
+
+" initialize c/cpp syntax checker handlers
+function! s:_init() abort " {{{2
+ let s:handlers = []
+ let s:cflags = {}
+
+ call s:_registerHandler('\m\<cairo', 's:_checkPackage', ['cairo', 'cairo'])
+ call s:_registerHandler('\m\<freetype', 's:_checkPackage', ['freetype', 'freetype2', 'freetype'])
+ call s:_registerHandler('\m\<glade', 's:_checkPackage', ['glade', 'libglade-2.0', 'libglade'])
+ call s:_registerHandler('\m\<glib', 's:_checkPackage', ['glib', 'glib-2.0', 'glib'])
+ call s:_registerHandler('\m\<gtk', 's:_checkPackage', ['gtk', 'gtk+-2.0', 'gtk+', 'glib-2.0', 'glib'])
+ call s:_registerHandler('\m\<libsoup', 's:_checkPackage', ['libsoup', 'libsoup-2.4', 'libsoup-2.2'])
+ call s:_registerHandler('\m\<libxml', 's:_checkPackage', ['libxml', 'libxml-2.0', 'libxml'])
+ call s:_registerHandler('\m\<pango', 's:_checkPackage', ['pango', 'pango'])
+ call s:_registerHandler('\m\<SDL', 's:_checkPackage', ['sdl', 'sdl'])
+ call s:_registerHandler('\m\<opengl', 's:_checkPackage', ['opengl', 'gl'])
+ call s:_registerHandler('\m\<webkit', 's:_checkPackage', ['webkit', 'webkit-1.0'])
+
+ call s:_registerHandler('\m\<php\.h\>', 's:_checkPhp', [])
+ call s:_registerHandler('\m\<Python\.h\>', 's:_checkPython', [])
+ call s:_registerHandler('\m\<ruby', 's:_checkRuby', [])
+endfunction " }}}2
+
+" register a handler dictionary object
+function! s:_registerHandler(regex, function, args) abort " {{{2
+ let handler = {}
+ let handler['regex'] = a:regex
+ let handler['func'] = function(a:function)
+ let handler['args'] = a:args
+ call add(s:handlers, handler)
+endfunction " }}}2
+
+" try to find library with 'pkg-config'
+" search possible libraries from first to last given
+" argument until one is found
+function! s:_checkPackage(name, ...) abort " {{{2
+ if executable('pkg-config')
+ if !has_key(s:cflags, a:name)
+ for pkg in a:000
+ let pkg_flags = syntastic#util#system('pkg-config --cflags ' . pkg)
+ " since we cannot necessarily trust the pkg-config exit code
+ " we have to check for an error output as well
+ if v:shell_error == 0 && pkg_flags !~? 'not found'
+ let pkg_flags = ' ' . substitute(pkg_flags, "\n", '', '')
+ let s:cflags[a:name] = pkg_flags
+ return pkg_flags
+ endif
+ endfor
+ else
+ return s:cflags[a:name]
+ endif
+ endif
+ return ''
+endfunction " }}}2
+
+" try to find PHP includes with 'php-config'
+function! s:_checkPhp() abort " {{{2
+ if executable('php-config')
+ if !has_key(s:cflags, 'php')
+ let s:cflags['php'] = syntastic#util#system('php-config --includes')
+ let s:cflags['php'] = ' ' . substitute(s:cflags['php'], "\n", '', '')
+ endif
+ return s:cflags['php']
+ endif
+ return ''
+endfunction " }}}2
+
+" try to find the python headers with distutils
+function! s:_checkPython() abort " {{{2
+ if executable('python')
+ if !has_key(s:cflags, 'python')
+ let s:cflags['python'] = syntastic#util#system('python -c ''from distutils import ' .
+ \ 'sysconfig; import sys; sys.stdout.write(sysconfig.get_python_inc())''')
+ let s:cflags['python'] = substitute(s:cflags['python'], "\n", '', '')
+ let s:cflags['python'] = ' -I' . s:cflags['python']
+ endif
+ return s:cflags['python']
+ endif
+ return ''
+endfunction " }}}2
+
+" try to find the ruby headers with 'rbconfig'
+function! s:_checkRuby() abort " {{{2
+ if executable('ruby')
+ if !has_key(s:cflags, 'ruby')
+ let s:cflags['ruby'] = syntastic#util#system('ruby -r rbconfig -e ' .
+ \ '''puts RbConfig::CONFIG["rubyhdrdir"] || RbConfig::CONFIG["archdir"]''')
+ let s:cflags['ruby'] = substitute(s:cflags['ruby'], "\n", '', '')
+ let s:cflags['ruby'] = ' -I' . s:cflags['ruby']
+ endif
+ return s:cflags['ruby']
+ endif
+ return ''
+endfunction " }}}2
+
+" }}}1
+
+" Utilities {{{1
+
+" resolve checker-related user variables
+function! s:_get_checker_var(scope, filetype, subchecker, name, default) abort " {{{2
+ let prefix = a:scope . ':' . 'syntastic_'
+ if exists(prefix . a:filetype . '_' . a:subchecker . '_' . a:name)
+ return {a:scope}:syntastic_{a:filetype}_{a:subchecker}_{a:name}
+ elseif exists(prefix . a:filetype . '_' . a:name)
+ return {a:scope}:syntastic_{a:filetype}_{a:name}
+ else
+ return a:default
+ endif
+endfunction " }}}2
+
+" resolve user CFLAGS
+function! s:_get_cflags(ft, ck, opts) abort " {{{2
+ " determine whether to parse header files as well
+ if has_key(a:opts, 'header_names') && expand('%', 1) =~? a:opts['header_names']
+ if s:_get_checker_var('g', a:ft, a:ck, 'check_header', 0)
+ let flags = get(a:opts, 'header_flags', '') . ' -c ' . syntastic#c#NullOutput()
+ else
+ " checking headers when check_header is unset: bail out
+ throw 'Syntastic: skip checks'
+ endif
+ else
+ let flags = get(a:opts, 'main_flags', '')
+ endif
+
+ let flags .= ' ' . s:_get_checker_var('g', a:ft, a:ck, 'compiler_options', '') . ' ' . s:_get_include_dirs(a:ft)
+
+ " check if the user manually set some cflags
+ let b_cflags = s:_get_checker_var('b', a:ft, a:ck, 'cflags', '')
+ if b_cflags !=# ''
+ let flags .= ' ' . b_cflags
+ endif
+
+ " add optional config file parameters
+ let config_file = s:_get_checker_var('g', a:ft, a:ck, 'config_file', '.syntastic_' . a:ft . '_config')
+ let flags .= ' ' . syntastic#c#ReadConfig(config_file)
+
+ if b_cflags ==# '' && (a:ft ==# 'c' || a:ft ==# 'cpp') && !s:_get_checker_var('g', a:ft, a:ck, 'no_include_search', 0)
+ " refresh the include file search if desired
+ if s:_get_checker_var('g', a:ft, a:ck, 'auto_refresh_includes', 0)
+ let flags .= ' ' . s:_search_headers()
+ else
+ " search for header includes if not cached already
+ if !exists('b:syntastic_' . a:ft . '_includes')
+ let b:syntastic_{a:ft}_includes = s:_search_headers()
+ endif
+ let flags .= ' ' . b:syntastic_{a:ft}_includes
+ endif
+ endif
+
+ return flags
+endfunction " }}}2
+
+" get the gcc include directory argument depending on the default
+" includes and the optional user-defined 'g:syntastic_c_include_dirs'
+function! s:_get_include_dirs(filetype) abort " {{{2
+ let include_dirs = []
+
+ if a:filetype =~# '\v^%(c|cpp|objc|objcpp)$' &&
+ \ (!exists('g:syntastic_'.a:filetype.'_no_default_include_dirs') ||
+ \ !g:syntastic_{a:filetype}_no_default_include_dirs)
+ let include_dirs = copy(s:default_includes)
+ endif
+
+ if exists('g:syntastic_'.a:filetype.'_include_dirs')
+ call extend(include_dirs, g:syntastic_{a:filetype}_include_dirs)
+ endif
+
+ return join(map(syntastic#util#unique(include_dirs), 'syntastic#util#shescape("-I" . v:val)'))
+endfunction " }}}2
+
+" search the first 100 lines for include statements that are
+" given in the handlers dictionary
+function! s:_search_headers() abort " {{{2
+ let includes = ''
+ let files = []
+ let found = []
+ let lines = filter(getline(1, 100), 'v:val =~# ''\m^\s*#\s*include''')
+
+ " search current buffer
+ for line in lines
+ let file = matchstr(line, '\m"\zs\S\+\ze"')
+ if file !=# ''
+ call add(files, file)
+ continue
+ endif
+
+ for handler in s:handlers
+ if line =~# handler['regex']
+ let includes .= call(handler['func'], handler['args'])
+ call add(found, handler['regex'])
+ break
+ endif
+ endfor
+ endfor
+
+ " search included headers
+ for hfile in files
+ if hfile !=# ''
+ let filename = expand('%:p:h', 1) . syntastic#util#Slash() . hfile
+
+ try
+ let lines = readfile(filename, '', 100)
+ catch /\m^Vim\%((\a\+)\)\=:E484/
+ continue
+ endtry
+
+ call filter(lines, 'v:val =~# ''\m^\s*#\s*include''')
+
+ for handler in s:handlers
+ if index(found, handler['regex']) != -1
+ continue
+ endif
+
+ for line in lines
+ if line =~# handler['regex']
+ let includes .= call(handler['func'], handler['args'])
+ call add(found, handler['regex'])
+ break
+ endif
+ endfor
+ endfor
+ endif
+ endfor
+
+ return includes
+endfunction " }}}2
+
+" }}}1
+
+" default include directories
+let s:default_includes = [
+ \ '.',
+ \ '..',
+ \ 'include',
+ \ 'includes',
+ \ '..' . syntastic#util#Slash() . 'include',
+ \ '..' . syntastic#util#Slash() . 'includes' ]
+
+call s:_init()
+
+let &cpo = s:save_cpo
+unlet s:save_cpo
+
+" vim: set sw=4 sts=4 et fdm=marker:
diff --git a/vim/bundle/syntastic/autoload/syntastic/log.vim b/vim/bundle/syntastic/autoload/syntastic/log.vim
new file mode 100644
index 0000000..5ad562d
--- /dev/null
+++ b/vim/bundle/syntastic/autoload/syntastic/log.vim
@@ -0,0 +1,222 @@
+if exists('g:loaded_syntastic_log_autoload') || !exists('g:loaded_syntastic_plugin')
+ finish
+endif
+let g:loaded_syntastic_log_autoload = 1
+
+let s:save_cpo = &cpo
+set cpo&vim
+
+let s:one_time_notices_issued = []
+
+" Public functions {{{1
+
+function! syntastic#log#info(msg) abort " {{{2
+ echomsg 'syntastic: info: ' . a:msg
+endfunction " }}}2
+
+function! syntastic#log#warn(msg) abort " {{{2
+ echohl WarningMsg
+ echomsg 'syntastic: warning: ' . a:msg
+ echohl None
+endfunction " }}}2
+
+function! syntastic#log#error(msg) abort " {{{2
+ execute "normal \<Esc>"
+ echohl ErrorMsg
+ echomsg 'syntastic: error: ' . a:msg
+ echohl None
+endfunction " }}}2
+
+function! syntastic#log#oneTimeWarn(msg) abort " {{{2
+ if index(s:one_time_notices_issued, a:msg) >= 0
+ return
+ endif
+
+ call add(s:one_time_notices_issued, a:msg)
+ call syntastic#log#warn(a:msg)
+endfunction " }}}2
+
+" @vimlint(EVL102, 1, l:OLD_VAR)
+function! syntastic#log#deprecationWarn(old, new, ...) abort " {{{2
+ if exists('g:syntastic_' . a:old) && !exists('g:syntastic_' . a:new)
+ let msg = 'variable g:syntastic_' . a:old . ' is deprecated, please use '
+
+ if a:0
+ let OLD_VAR = g:syntastic_{a:old}
+ try
+ let NEW_VAR = eval(a:1)
+ let msg .= 'in its stead: let g:syntastic_' . a:new . ' = ' . string(NEW_VAR)
+ let g:syntastic_{a:new} = NEW_VAR
+ catch
+ let msg .= 'g:syntastic_' . a:new . ' instead'
+ endtry
+ else
+ let msg .= 'g:syntastic_' . a:new . ' instead'
+ let g:syntastic_{a:new} = g:syntastic_{a:old}
+ endif
+
+ call syntastic#log#oneTimeWarn(msg)
+ endif
+endfunction " }}}2
+" @vimlint(EVL102, 0, l:OLD_VAR)
+
+function! syntastic#log#debug(level, msg, ...) abort " {{{2
+ if !s:_isDebugEnabled(a:level)
+ return
+ endif
+
+ let leader = s:_log_timestamp()
+ call s:_logRedirect(1)
+
+ if a:0 > 0
+ " filter out dictionary functions
+ echomsg leader . a:msg . ' ' .
+ \ strtrans(string(type(a:1) == type({}) || type(a:1) == type([]) ?
+ \ filter(copy(a:1), 'type(v:val) != type(function("tr"))') : a:1))
+ else
+ echomsg leader . a:msg
+ endif
+
+ call s:_logRedirect(0)
+endfunction " }}}2
+
+function! syntastic#log#debugShowOptions(level, names) abort " {{{2
+ if !s:_isDebugEnabled(a:level)
+ return
+ endif
+
+ let leader = s:_log_timestamp()
+ call s:_logRedirect(1)
+
+ let vlist = copy(type(a:names) == type('') ? [a:names] : a:names)
+ let add_shell = index(vlist, 'shell') >= 0 && &shell !=# syntastic#util#var('shell')
+ if !empty(vlist)
+ call map(vlist, "'&' . v:val . ' = ' . strtrans(string(eval('&' . v:val))) . (s:_is_modified(v:val) ? ' (!)' : '')")
+ if add_shell
+ call add(vlist, 'u:shell = ' . strtrans(string(syntastic#util#var('shell'))) . ' (!)')
+ endif
+ echomsg leader . join(vlist, ', ')
+ endif
+ call s:_logRedirect(0)
+endfunction " }}}2
+
+function! syntastic#log#debugShowVariables(level, names) abort " {{{2
+ if !s:_isDebugEnabled(a:level)
+ return
+ endif
+
+ let leader = s:_log_timestamp()
+ call s:_logRedirect(1)
+
+ let vlist = type(a:names) == type('') ? [a:names] : a:names
+ for name in vlist
+ let msg = s:_format_variable(name)
+ if msg !=# ''
+ echomsg leader . msg
+ endif
+ endfor
+
+ call s:_logRedirect(0)
+endfunction " }}}2
+
+function! syntastic#log#debugDump(level) abort " {{{2
+ if !s:_isDebugEnabled(a:level)
+ return
+ endif
+
+ call syntastic#log#debugShowVariables( a:level, sort(keys(g:_SYNTASTIC_DEFAULTS)) )
+endfunction " }}}2
+
+function! syntastic#log#ndebug(level, title, messages) abort " {{{2
+ if s:_isDebugEnabled(a:level)
+ return
+ endif
+
+ call syntastic#log#error(a:title)
+ if type(a:messages) == type([])
+ for msg in a:messages
+ echomsg msg
+ endfor
+ else
+ echomsg a:messages
+ endif
+endfunction " }}}2
+
+" }}}1
+
+" Private functions {{{1
+
+function! s:_isDebugEnabled_smart(level) abort " {{{2
+ return and(g:syntastic_debug, a:level)
+endfunction " }}}2
+
+function! s:_isDebugEnabled_dumb(level) abort " {{{2
+ " poor man's bit test for bit N, assuming a:level == 2**N
+ return (g:syntastic_debug / a:level) % 2
+endfunction " }}}2
+
+let s:_isDebugEnabled = function(exists('*and') ? 's:_isDebugEnabled_smart' : 's:_isDebugEnabled_dumb')
+lockvar s:_isDebugEnabled
+
+function! s:_logRedirect(on) abort " {{{2
+ if exists('g:syntastic_debug_file')
+ if a:on
+ try
+ execute 'redir >> ' . fnameescape(expand(g:syntastic_debug_file, 1))
+ catch /\m^Vim\%((\a\+)\)\=:/
+ silent! redir END
+ unlet g:syntastic_debug_file
+ endtry
+ else
+ silent! redir END
+ endif
+ endif
+endfunction " }}}2
+
+" }}}1
+
+" Utilities {{{1
+
+function! s:_log_timestamp_smart() abort " {{{2
+ return printf('syntastic: %f: ', reltimefloat(reltime(g:_SYNTASTIC_START)))
+endfunction " }}}2
+
+function! s:_log_timestamp_dumb() abort " {{{2
+ return 'syntastic: ' . split(reltimestr(reltime(g:_SYNTASTIC_START)))[0] . ': '
+endfunction " }}}2
+
+let s:_log_timestamp = function(has('float') && exists('*reltimefloat') ? 's:_log_timestamp_smart' : 's:_log_timestamp_dumb')
+lockvar s:_log_timestamp
+
+function! s:_format_variable(name) abort " {{{2
+ let vals = []
+ if exists('g:syntastic_' . a:name)
+ call add(vals, 'g:syntastic_' . a:name . ' = ' . strtrans(string(g:syntastic_{a:name})))
+ endif
+ if exists('b:syntastic_' . a:name)
+ call add(vals, 'b:syntastic_' . a:name . ' = ' . strtrans(string(b:syntastic_{a:name})))
+ endif
+
+ return join(vals, ', ')
+endfunction " }}}2
+
+function! s:_is_modified(name) abort " {{{2
+ if !exists('s:option_defaults')
+ let s:option_defaults = {}
+ endif
+ if !has_key(s:option_defaults, a:name)
+ let opt_save = eval('&' . a:name)
+ execute 'set ' . a:name . '&'
+ let s:option_defaults[a:name] = eval('&' . a:name)
+ execute 'let &' . a:name . ' = ' . string(opt_save)
+ endif
+
+ return s:option_defaults[a:name] !=# eval('&' . a:name)
+endfunction " }}}2
+
+" }}}1
+
+let &cpo = s:save_cpo
+unlet s:save_cpo
+
+" vim: set sw=4 sts=4 et fdm=marker:
diff --git a/vim/bundle/syntastic/autoload/syntastic/postprocess.vim b/vim/bundle/syntastic/autoload/syntastic/postprocess.vim
new file mode 100644
index 0000000..136fa58
--- /dev/null
+++ b/vim/bundle/syntastic/autoload/syntastic/postprocess.vim
@@ -0,0 +1,73 @@
+if exists('g:loaded_syntastic_postprocess_autoload') || !exists('g:loaded_syntastic_plugin')
+ finish
+endif
+let g:loaded_syntastic_postprocess_autoload = 1
+
+let s:save_cpo = &cpo
+set cpo&vim
+
+" Public functions {{{1
+
+" merge consecutive blanks
+function! syntastic#postprocess#compressWhitespace(errors) abort " {{{2
+ for e in a:errors
+ let e['text'] = substitute(e['text'], "\001", '', 'g')
+ let e['text'] = substitute(e['text'], '\n', ' ', 'g')
+ let e['text'] = substitute(e['text'], '\m\s\{2,}', ' ', 'g')
+ let e['text'] = substitute(e['text'], '\m^\s\+', '', '')
+ let e['text'] = substitute(e['text'], '\m\s\+$', '', '')
+ endfor
+
+ return a:errors
+endfunction " }}}2
+
+" remove spurious CR under Cygwin
+function! syntastic#postprocess#cygwinRemoveCR(errors) abort " {{{2
+ if has('win32unix')
+ for e in a:errors
+ let e['text'] = substitute(e['text'], '\r', '', 'g')
+ endfor
+ endif
+
+ return a:errors
+endfunction " }}}2
+
+" decode XML entities
+function! syntastic#postprocess#decodeXMLEntities(errors) abort " {{{2
+ for e in a:errors
+ let e['text'] = syntastic#util#decodeXMLEntities(e['text'])
+ endfor
+
+ return a:errors
+endfunction " }}}2
+
+" filter out errors referencing other files
+function! syntastic#postprocess#filterForeignErrors(errors) abort " {{{2
+ return filter(copy(a:errors), 'get(v:val, "bufnr") == ' . bufnr(''))
+endfunction " }}}2
+
+" make sure line numbers are not past end of buffers
+" XXX: this loads all referenced buffers in memory
+function! syntastic#postprocess#guards(errors) abort " {{{2
+ let buffers = syntastic#util#unique(map(filter(copy(a:errors), 'v:val["valid"]'), 'str2nr(v:val["bufnr"])'))
+
+ let guards = {}
+ for b in buffers
+ let guards[b] = len(getbufline(b, 1, '$'))
+ endfor
+
+ for e in a:errors
+ if e['valid'] && e['lnum'] > guards[e['bufnr']]
+ let e['lnum'] = guards[e['bufnr']]
+ endif
+ endfor
+
+ return a:errors
+endfunction " }}}2
+
+" }}}1
+
+let &cpo = s:save_cpo
+unlet s:save_cpo
+
+" vim: set sw=4 sts=4 et fdm=marker:
diff --git a/vim/bundle/syntastic/autoload/syntastic/preprocess.vim b/vim/bundle/syntastic/autoload/syntastic/preprocess.vim
new file mode 100644
index 0000000..cbab6fd
--- /dev/null
+++ b/vim/bundle/syntastic/autoload/syntastic/preprocess.vim
@@ -0,0 +1,614 @@
+if exists('g:loaded_syntastic_preprocess_autoload') || !exists('g:loaded_syntastic_plugin')
+ finish
+endif
+let g:loaded_syntastic_preprocess_autoload = 1
+
+let s:save_cpo = &cpo
+set cpo&vim
+
+" Public functions {{{1
+
+function! syntastic#preprocess#cabal(errors) abort " {{{2
+ let out = []
+ let star = 0
+ for err in a:errors
+ if star
+ if err ==# ''
+ let star = 0
+ else
+ let out[-1] .= ' ' . err
+ endif
+ else
+ call add(out, err)
+ if err =~# '\m^*\s'
+ let star = 1
+ endif
+ endif
+ endfor
+ return out
+endfunction " }}}2
+
+function! syntastic#preprocess#checkstyle(errors) abort " {{{2
+ let out = []
+ let fname = expand('%', 1)
+ for err in a:errors
+ if match(err, '\m<error\>') > -1
+ let line = str2nr(matchstr(err, '\m\<line="\zs\d\+\ze"'))
+ if line == 0
+ continue
+ endif
+
+ let col = str2nr(matchstr(err, '\m\<column="\zs\d\+\ze"'))
+
+ let type = matchstr(err, '\m\<severity="\zs.\ze')
+ if type !~? '^[EW]'
+ let type = 'E'
+ endif
+
+ let message = syntastic#util#decodeXMLEntities(matchstr(err, '\m\<message="\zs[^"]\+\ze"'))
+
+ call add(out, join([fname, type, line, col, message], ':'))
+ elseif match(err, '\m<file name="') > -1
+ let fname = syntastic#util#decodeXMLEntities(matchstr(err, '\v\<file name\="\zs[^"]+\ze"'))
+ endif
+ endfor
+ return out
+endfunction " }}}2
+
+function! syntastic#preprocess#cppcheck(errors) abort " {{{2
+ return map(copy(a:errors), 'substitute(v:val, ''\v^\[[^]]+\]\zs( -\> \[[^]]+\])+\ze:'', "", "")')
+endfunction " }}}2
+
+function! syntastic#preprocess#dockerfile_lint(errors) abort " {{{2
+ let out = []
+ let json = s:_decode_JSON(join(a:errors, ''))
+
+ if type(json) == type({})
+ try
+ let data = json['error']['data'] + json['warn']['data'] + json['info']['data']
+ for e in data
+ let type = toupper(e['level'][0])
+ if type ==# 'I'
+ let type = 'W'
+ let style = 1
+ else
+ let style = 0
+ endif
+
+ let line = get(e, 'line', 1)
+ let message = e['message']
+ if has_key(e, 'description') && e['description'] !=# 'None'
+ let message = message . '. ' . e['description']
+ endif
+
+ let msg =
+ \ type . ':' .
+ \ style . ':' .
+ \ line . ':' .
+ \ message
+ call add(out, msg)
+ endfor
+ catch /\m^Vim\%((\a\+)\)\=:E716/
+ call syntastic#log#warn('checker dockerfile/dockerfile_lint: unrecognized error format')
+ let out = []
+ endtry
+ else
+ call syntastic#log#warn('checker dockerfile/dockerfile_lint: unrecognized error format')
+ endif
+ return out
+endfunction " }}}2
+
+function! syntastic#preprocess#flow(errors) abort " {{{2
+ let idx = 0
+ while idx < len(a:errors) && a:errors[idx][0] !=# '{'
+ let idx += 1
+ endwhile
+ let errs = s:_decode_JSON(join(a:errors[idx :], ''))
+
+ let out = []
+ if type(errs) == type({}) && has_key(errs, 'errors') && type(errs['errors']) == type([])
+ for e in errs['errors']
+ if type(e) == type({}) && has_key(e, 'message') && type(e['message']) == type([]) && len(e['message'])
+ let m = e['message'][0]
+ let t = e['message'][1:]
+
+ try
+ let msg =
+ \ m['path'] . ':' .
+ \ m['line'] . ':' .
+ \ m['start'] . ':' .
+ \ (m['line'] ==# m['endline'] && str2nr(m['end']) > 0 ? m['end'] . ':' : '') .
+ \ ' ' . m['descr']
+
+ if len(t)
+ let msg .= ' ' . join(map(t,
+ \ 'v:val["descr"] . " (" . v:val["path"] . ":" . v:val["line"] . ":" . v:val["start"] . ' .
+ \ '"," . (v:val["line"] !=# v:val["endline"] ? v:val["endline"] . ":" : "") . ' .
+ \ 'v:val["end"] . ")"'))
+ endif
+
+ let msg = substitute(msg, '\r', '', 'g')
+ let msg = substitute(msg, '\n', ' ', 'g')
+
+ call add(out, msg)
+ catch /\m^Vim\%((\a\+)\)\=:E716/
+ call syntastic#log#warn('checker javascript/flow: unrecognized error format')
+ let out = []
+ break
+ endtry
+ else
+ call syntastic#log#warn('checker javascript/flow: unrecognized error format')
+ let out = []
+ break
+ endif
+ endfor
+ else
+ call syntastic#log#warn('checker javascript/flow: unrecognized error format')
+ endif
+
+ return out
+endfunction " }}}2
+
+function! syntastic#preprocess#iconv(errors) abort " {{{2
+ return
+ \ has('iconv') && &encoding !=# '' && &encoding !=# 'utf-8' ?
+ \ map(a:errors, 'iconv(v:val, "utf-8", &encoding)') :
+ \ a:errors
+endfunction " }}}2
+
+function! syntastic#preprocess#jscs(errors) abort " {{{2
+ let errs = join(a:errors, '')
+ if errs ==# ''
+ return []
+ endif
+
+ let json = s:_decode_JSON(errs)
+
+ let out = []
+ if type(json) == type({})
+ for fname in keys(json)
+ if type(json[fname]) == type([])
+ for e in json[fname]
+ try
+ let e['message'] = substitute(e['message'], "\n", ' ', 'g')
+ cal add(out, fname . ':' . e['line'] . ':' . e['column'] . ':' . e['message'])
+ catch /\m^Vim\%((\a\+)\)\=:E716/
+ call syntastic#log#warn('checker javascript/jscs: unrecognized error item ' . string(e))
+ let out = []
+ endtry
+ endfor
+ else
+ call syntastic#log#warn('checker javascript/jscs: unrecognized error format')
+ endif
+ endfor
+ else
+ call syntastic#log#warn('checker javascript/jscs: unrecognized error format')
+ endif
+ return out
+endfunction " }}}2
+
+function! syntastic#preprocess#killEmpty(errors) abort " {{{2
+ return filter(copy(a:errors), 'v:val !=# ""')
+endfunction " }}}2
+
+function! syntastic#preprocess#perl(errors) abort " {{{2
+ let out = []
+
+ for e in a:errors
+ let parts = matchlist(e, '\v^(.*)\sat\s(.{-})\sline\s(\d+)(.*)$')
+ if !empty(parts)
+ call add(out, parts[2] . ':' . parts[3] . ':' . parts[1] . parts[4])
+ endif
+ endfor
+
+ return syntastic#util#unique(out)
+endfunction " }}}2
+
+function! syntastic#preprocess#prospector(errors) abort " {{{2
+ let errs = s:_decode_JSON(join(a:errors, ''))
+
+ let out = []
+ if type(errs) == type({}) && has_key(errs, 'messages')
+ if type(errs['messages']) == type([])
+ for e in errs['messages']
+ if type(e) == type({})
+ try
+ if e['source'] ==# 'pylint'
+ let e['location']['character'] += 1
+ endif
+
+ let msg =
+ \ e['location']['path'] . ':' .
+ \ e['location']['line'] . ':' .
+ \ e['location']['character'] . ': ' .
+ \ e['code'] . ' ' .
+ \ e['message'] . ' ' .
+ \ '[' . e['source'] . ']'
+
+ call add(out, msg)
+ catch /\m^Vim\%((\a\+)\)\=:E716/
+ call syntastic#log#warn('checker python/prospector: unrecognized error item ' . string(e))
+ let out = []
+ break
+ endtry
+ else
+ call syntastic#log#warn('checker python/prospector: unrecognized error item ' . string(e))
+ let out = []
+ break
+ endif
+ endfor
+ else
+ call syntastic#log#warn('checker python/prospector: unrecognized error format')
+ endif
+ endif
+
+ return out
+endfunction " }}}2
+
+function! syntastic#preprocess#rparse(errors) abort " {{{2
+ let errlist = copy(a:errors)
+
+ " remove uninteresting lines and handle continuations
+ let i = 0
+ while i < len(errlist)
+ if i > 0 && errlist[i][:1] ==# ' ' && errlist[i] !~# '\m\s\+\^$'
+ let errlist[i-1] .= errlist[i][1:]
+ call remove(errlist, i)
+ elseif errlist[i] !~# '\m^\(Lint:\|Lint checking:\|Error in\) '
+ call remove(errlist, i)
+ else
+ let i += 1
+ endif
+ endwhile
+
+ let out = []
+ let fname = ''
+ for e in errlist
+ if match(e, '\m^Lint: ') == 0
+ let parts = matchlist(e, '\m^Lint: \(.*\): found on lines \([0-9, ]\+\)\(+\(\d\+\) more\)\=')
+ if len(parts) >= 3
+ for line in split(parts[2], '\m,\s*')
+ call add(out, 'E:' . fname . ':' . line . ': ' . parts[1])
+ endfor
+ endif
+ if len(parts) >= 5 && parts[4] !=# ''
+ call add(out, 'E:' . fname . ':0: ' . parts[1] . ' - ' . parts[4] . ' messages not shown')
+ endif
+ elseif match(e, '\m^Lint checking: ') == 0
+ let fname = matchstr(e, '\m^Lint checking: \zs.*')
+ elseif match(e, '\m^Error in ') == 0
+ call add(out, substitute(e, '\m^Error in .\+ : .\+\ze:\d\+:\d\+: ', 'E:' . fname, ''))
+ endif
+ endfor
+
+ return out
+endfunction " }}}2
+
+function! syntastic#preprocess#scss_lint(errors) abort " {{{2
+ let errs = join(a:errors, '')
+ if errs ==# ''
+ return []
+ endif
+
+ let json = s:_decode_JSON(errs)
+
+ let out = []
+ if type(json) == type({})
+ for fname in keys(json)
+ if type(json[fname]) == type([])
+ for e in json[fname]
+ try
+ cal add(out, fname . ':' .
+ \ e['severity'][0] . ':' .
+ \ e['line'] . ':' .
+ \ e['column'] . ':' .
+ \ e['length'] . ':' .
+ \ ( has_key(e, 'linter') ? e['linter'] . ': ' : '' ) .
+ \ e['reason'])
+ catch /\m^Vim\%((\a\+)\)\=:E716/
+ call syntastic#log#warn('checker scss/scss_lint: unrecognized error item ' . string(e))
+ let out = []
+ endtry
+ endfor
+ else
+ call syntastic#log#warn('checker scss/scss_lint: unrecognized error format')
+ endif
+ endfor
+ else
+ call syntastic#log#warn('checker scss/scss_lint: unrecognized error format')
+ endif
+ return out
+endfunction " }}}2
+
+function! syntastic#preprocess#stylelint(errors) abort " {{{2
+ let out = []
+
+ " CssSyntaxError: /path/to/file.css:2:11: Missed semicolon
+ let parts = matchlist(a:errors[0], '\v^CssSyntaxError: (.{-1,}):(\d+):(\d+): (.+)')
+ if len(parts) > 4
+ call add(out, 'E:' . join(parts[1:4], ':'))
+ else
+ let errs = s:_decode_JSON(join(a:errors, ''))
+
+ let out = []
+ if type(errs) == type([]) && len(errs) == 1 && type(errs[0]) == type({}) &&
+ \ has_key(errs[0], 'source') && has_key(errs[0], 'warnings') && type(errs[0]['warnings']) == type([])
+
+ for e in errs[0]['warnings']
+ try
+ let severity = type(e['severity']) == type(0) ? ['W', 'E'][e['severity']-1] : e['severity'][0]
+ let msg =
+ \ severity . ':' .
+ \ errs[0]['source'] . ':' .
+ \ e['line'] . ':' .
+ \ e['column'] . ':' .
+ \ e['text']
+ call add(out, msg)
+ catch /\m^Vim\%((\a\+)\)\=:E716/
+ call syntastic#log#warn('checker css/stylelint: unrecognized error item ' . string(e))
+ let out = []
+ break
+ endtry
+ endfor
+ else
+ call syntastic#log#warn('checker css/stylelint: unrecognized error format')
+ endif
+ endif
+ return out
+endfunction " }}}2
+
+function! syntastic#preprocess#tern_lint(errors) abort " {{{2
+ let errs = join(a:errors, '')
+ let json = s:_decode_JSON(errs)
+
+echomsg string(json)
+ let out = []
+ if type(json) == type({}) && has_key(json, 'messages') && type(json['messages']) == type([])
+ for e in json['messages']
+ try
+ let line_from = byte2line(e['from'] + 1)
+ if line_from > 0
+ let line = line_from
+ let column = e['from'] - line2byte(line_from) + 2
+ let line_to = byte2line(e['from'] + 1)
+ let hl = line_to == line ? e['to'] - line2byte(line_to) + 1 : 0
+ else
+ let line = 0
+ let column = 0
+ let hl = 0
+ endif
+
+ if column < 0
+ let column = 0
+ endif
+ if hl < 0
+ let hl = 0
+ endif
+
+ call add(out,
+ \ e['file'] . ':' .
+ \ e['severity'][0] . ':' .
+ \ line . ':' .
+ \ column . ':' .
+ \ hl . ':' .
+ \ e['message'])
+ catch /\m^Vim\%((\a\+)\)\=:E716/
+ call syntastic#log#warn('checker javascript/tern_lint: unrecognized error item ' . string(e))
+ let out = []
+ endtry
+ endfor
+ else
+ call syntastic#log#warn('checker javascript/tern_lint: unrecognized error format')
+ endif
+
+echomsg string(out)
+ return out
+endfunction " }}}2
+
+function! syntastic#preprocess#tslint(errors) abort " {{{2
+ return map(copy(a:errors), 'substitute(v:val, ''\m^\(([^)]\+)\)\s\(.\+\)$'', ''\2 \1'', "")')
+endfunction " }}}2
+
+function! syntastic#preprocess#validator(errors) abort " {{{2
+ let out = []
+ for e in a:errors
+ let parts = matchlist(e, '\v^"([^"]+)"(.+)')
+ if len(parts) >= 3
+ " URL decode, except leave alone any "+"
+ let parts[1] = substitute(parts[1], '\m%\(\x\x\)', '\=nr2char("0x".submatch(1))', 'g')
+ let parts[1] = substitute(parts[1], '\m\\"', '"', 'g')
+ let parts[1] = substitute(parts[1], '\m\\\\', '\\', 'g')
+ call add(out, '"' . parts[1] . '"' . parts[2])
+ endif
+ endfor
+ return out
+endfunction " }}}2
+
+function! syntastic#preprocess#vint(errors) abort " {{{2
+ let errs = s:_decode_JSON(join(a:errors, ''))
+
+ let out = []
+ if type(errs) == type([])
+ for e in errs
+ if type(e) == type({})
+ try
+ let msg =
+ \ e['file_path'] . ':' .
+ \ e['line_number'] . ':' .
+ \ e['column_number'] . ':' .
+ \ e['severity'][0] . ': ' .
+ \ e['description'] . ' (' .
+ \ e['policy_name'] . ')'
+
+ call add(out, msg)
+ catch /\m^Vim\%((\a\+)\)\=:E716/
+ call syntastic#log#warn('checker vim/vint: unrecognized error item ' . string(e))
+ let out = []
+ break
+ endtry
+ else
+ call syntastic#log#warn('checker vim/vint: unrecognized error item ' . string(e))
+ let out = []
+ break
+ endif
+ endfor
+ else
+ call syntastic#log#warn('checker vim/vint: unrecognized error format')
+ endif
+
+ return out
+endfunction " }}}2
+
+" }}}1
+
+" Workarounds {{{1
+
+" In errorformat, \ or % following %f make it depend on isfname. The default
+" setting of isfname is crafted to work with completion, rather than general
+" filename matching. The result for syntastic is that filenames containing
+" spaces (or a few other special characters) can't be matched.
+"
+" Fixing isfname to address this problem would depend on the set of legal
+" characters for filenames on the filesystem the project's files lives on.
+" Inferring the kind of filesystem a file lives on, in advance to parsing the
+" file's name, is an interesting problem (think f.i. a file loaded from a VFAT
+" partition, mounted on Linux). A problem syntastic is not prepared to solve.
+"
+" As a result, the functions below exist for the only reason to avoid using
+" things like %f\, in errorformat.
+"
+" References:
+" https://groups.google.com/forum/#!topic/vim_dev/pTKmZmouhio
+" https://vimhelp.appspot.com/quickfix.txt.html#error-file-format
+
+function! syntastic#preprocess#basex(errors) abort " {{{2
+ let out = []
+ let idx = 0
+ while idx < len(a:errors)
+ let parts = matchlist(a:errors[idx], '\v^\[\S+\] Stopped at (.+), (\d+)/(\d+):')
+ if len(parts) > 3
+ let err = parts[1] . ':' . parts[2] . ':' . parts[3] . ':'
+ let parts = matchlist(a:errors[idx+1], '\v^\[(.)\D+(\d+)\] (.+)')
+ if len(parts) > 3
+ let err .= (parts[1] ==? 'W' || parts[1] ==? 'E' ? parts[1] : 'E') . ':' . parts[2] . ':' . parts[3]
+ call add(out, err)
+ let idx +=1
+ endif
+ elseif a:errors[idx] =~# '\m^\['
+ " unparseable errors
+ call add(out, a:errors[idx])
+ endif
+ let idx +=1
+ endwhile
+ return out
+endfunction " }}}2
+
+function! syntastic#preprocess#bro(errors) abort " {{{2
+ let out = []
+ for e in a:errors
+ let parts = matchlist(e, '\v^%(fatal )?(error|warning) in (.{-1,}), line (\d+): (.+)')
+ if len(parts) > 4
+ let parts[1] = parts[1][0]
+ call add(out, join(parts[1:4], ':'))
+ endif
+ endfor
+ return out
+endfunction " }}}2
+
+function! syntastic#preprocess#coffeelint(errors) abort " {{{2
+ let out = []
+ for e in a:errors
+ let parts = matchlist(e, '\v^(.{-1,}),(\d+)%(,\d*)?,(error|warn),(.+)')
+ if len(parts) > 4
+ let parts[3] = parts[3][0]
+ call add(out, join(parts[1:4], ':'))
+ endif
+ endfor
+ return out
+endfunction " }}}2
+
+function! syntastic#preprocess#mypy(errors) abort " {{{2
+ let out = []
+ for e in a:errors
+ " new format
+ let parts = matchlist(e, '\v^(.{-1,}):(\d+): error: (.+)')
+ if len(parts) > 3
+ call add(out, join(parts[1:3], ':'))
+ continue
+ endif
+
+ " old format
+ let parts = matchlist(e, '\v^(.{-1,}), line (\d+): (.+)')
+ if len(parts) > 3
+ call add(out, join(parts[1:3], ':'))
+ endif
+ endfor
+ return out
+endfunction " }}}2
+
+function! syntastic#preprocess#nix(errors) abort " {{{2
+ let out = []
+ for e in a:errors
+ let parts = matchlist(e, '\v^(.{-1,}), at (.{-1,}):(\d+):(\d+)$')
+ if len(parts) > 4
+ call add(out, join(parts[2:4], ':') . ':' . parts[1])
+ continue
+ endif
+
+ let parts = matchlist(e, '\v^(.{-1,}) at (.{-1,}), line (\d+):')
+ if len(parts) > 3
+ call add(out, parts[2] . ':' . parts[3] . ':' . parts[1])
+ continue
+ endif
+
+ let parts = matchlist(e, '\v^error: (.{-1,}), in (.{-1,})$')
+ if len(parts) > 2
+ call add(out, parts[2] . ':' . parts[1])
+ endif
+ endfor
+ return out
+endfunction " }}}2
+
+" }}}1
+
+" Private functions {{{1
+
+" @vimlint(EVL102, 1, l:true)
+" @vimlint(EVL102, 1, l:false)
+" @vimlint(EVL102, 1, l:null)
+function! s:_decode_JSON(json) abort " {{{2
+ if a:json ==# ''
+ return []
+ endif
+
+ " The following is inspired by https://github.com/MarcWeber/vim-addon-manager and
+ " http://stackoverflow.com/questions/17751186/iterating-over-a-string-in-vimscript-or-parse-a-json-file/19105763#19105763
+ " A hat tip to Marc Weber for this trick
+ if substitute(a:json, '\v\"%(\\.|[^"\\])*\"|true|false|null|[+-]?\d+%(\.\d+%([Ee][+-]?\d+)?)?', '', 'g') !~# "[^,:{}[\\] \t]"
+ " JSON artifacts
+ let true = 1
+ let false = 0
+ let null = ''
+
+ try
+ let object = eval(a:json)
+ catch
+ " malformed JSON
+ let object = ''
+ endtry
+ else
+ let object = ''
+ endif
+
+ return object
+endfunction " }}}2
+" @vimlint(EVL102, 0, l:true)
+" @vimlint(EVL102, 0, l:false)
+" @vimlint(EVL102, 0, l:null)
+
+" }}}1
+
+let &cpo = s:save_cpo
+unlet s:save_cpo
+
+" vim: set sw=4 sts=4 et fdm=marker:
diff --git a/vim/bundle/syntastic/autoload/syntastic/util.vim b/vim/bundle/syntastic/autoload/syntastic/util.vim
new file mode 100644
index 0000000..68eb06e
--- /dev/null
+++ b/vim/bundle/syntastic/autoload/syntastic/util.vim
@@ -0,0 +1,552 @@
+if exists('g:loaded_syntastic_util_autoload') || !exists('g:loaded_syntastic_plugin')
+ finish
+endif
+let g:loaded_syntastic_util_autoload = 1
+
+let s:save_cpo = &cpo
+set cpo&vim
+
+" Public functions {{{1
+
+function! syntastic#util#isRunningWindows() abort " {{{2
+ return has('win16') || has('win32') || has('win64')
+endfunction " }}}2
+
+function! syntastic#util#DevNull() abort " {{{2
+ if syntastic#util#isRunningWindows()
+ return 'NUL'
+ endif
+ return '/dev/null'
+endfunction " }}}2
+
+" Get directory separator
+function! syntastic#util#Slash() abort " {{{2
+ return (!exists('+shellslash') || &shellslash) ? '/' : '\'
+endfunction " }}}2
+
+function! syntastic#util#CygwinPath(path) abort " {{{2
+ return substitute(syntastic#util#system('cygpath -m ' . syntastic#util#shescape(a:path)), "\n", '', 'g')
+endfunction " }}}2
+
+function! syntastic#util#system(command) abort " {{{2
+ let old_shell = &shell
+ let old_lc_messages = $LC_MESSAGES
+ let old_lc_all = $LC_ALL
+
+ let &shell = syntastic#util#var('shell')
+ let $LC_MESSAGES = 'C'
+ let $LC_ALL = ''
+
+ let cmd_start = reltime()
+ let out = system(a:command)
+ let cmd_time = split(reltimestr(reltime(cmd_start)))[0]
+
+ let $LC_ALL = old_lc_all
+ let $LC_MESSAGES = old_lc_messages
+
+ let &shell = old_shell
+
+ if exists('g:_SYNTASTIC_DEBUG_TRACE')
+ call syntastic#log#debug(g:_SYNTASTIC_DEBUG_TRACE, 'system: command run in ' . cmd_time . 's')
+ endif
+
+ return out
+endfunction " }}}2
+
+" Create a temporary directory
+function! syntastic#util#tmpdir() abort " {{{2
+ let tempdir = ''
+
+ if (has('unix') || has('mac')) && executable('mktemp') && !has('win32unix')
+ " TODO: option "-t" to mktemp(1) is not portable
+ let tmp = $TMPDIR !=# '' ? $TMPDIR : $TMP !=# '' ? $TMP : '/tmp'
+ let out = split(syntastic#util#system('mktemp -q -d ' . tmp . '/vim-syntastic-' . getpid() . '-XXXXXXXX'), "\n")
+ if v:shell_error == 0 && len(out) == 1
+ let tempdir = out[0]
+ endif
+ endif
+
+ if tempdir ==# ''
+ if has('win32') || has('win64')
+ let tempdir = $TEMP . syntastic#util#Slash() . 'vim-syntastic-' . getpid()
+ elseif has('win32unix')
+ let tempdir = syntastic#util#CygwinPath('/tmp/vim-syntastic-' . getpid())
+ elseif $TMPDIR !=# ''
+ let tempdir = $TMPDIR . '/vim-syntastic-' . getpid()
+ else
+ let tempdir = '/tmp/vim-syntastic-' . getpid()
+ endif
+
+ try
+ call mkdir(tempdir, 'p', 0700)
+ catch /\m^Vim\%((\a\+)\)\=:E739/
+ call syntastic#log#error(v:exception)
+ let tempdir = '.'
+ endtry
+ endif
+
+ return tempdir
+endfunction " }}}2
+
+" Recursively remove a directory
+function! syntastic#util#rmrf(what) abort " {{{2
+ " try to make sure we don't delete directories we didn't create
+ if a:what !~? 'vim-syntastic-'
+ return
+ endif
+
+ if getftype(a:what) ==# 'dir'
+ call s:_delete(a:what, 'rf')
+ else
+ silent! call delete(a:what)
+ endif
+endfunction " }}}2
+
+" Search the first 5 lines of the file for a magic number and return a map
+" containing the args and the executable
+"
+" e.g.
+"
+" #!/usr/bin/perl -f -bar
+"
+" returns
+"
+" {'exe': '/usr/bin/perl', 'args': ['-f', '-bar']}
+function! syntastic#util#parseShebang() abort " {{{2
+ for lnum in range(1, 5)
+ let line = getline(lnum)
+ if line =~# '^#!'
+ let line = substitute(line, '\v^#!\s*(\S+/env(\s+-\S+)*\s+)?', '', '')
+ let exe = matchstr(line, '\m^\S*\ze')
+ let args = split(matchstr(line, '\m^\S*\zs.*'))
+ return { 'exe': exe, 'args': args }
+ endif
+ endfor
+
+ return { 'exe': '', 'args': [] }
+endfunction " }}}2
+
+" Get the value of a Vim variable. Allow local variables to override global ones.
+function! syntastic#util#rawVar(name, ...) abort " {{{2
+ return get(b:, a:name, get(g:, a:name, a:0 > 0 ? a:1 : ''))
+endfunction " }}}2
+
+" Get the value of a syntastic variable. Allow local variables to override global ones.
+function! syntastic#util#var(name, ...) abort " {{{2
+ return call('syntastic#util#rawVar', ['syntastic_' . a:name] + a:000)
+endfunction " }}}2
+
+" Parse a version string. Return an array of version components.
+function! syntastic#util#parseVersion(version, ...) abort " {{{2
+ return map(split(matchstr( a:version, a:0 ? a:1 : '\v^\D*\zs\d+(\.\d+)+\ze' ), '\m\.'), 'str2nr(v:val)')
+endfunction " }}}2
+
+" Verify that the 'installed' version is at least the 'required' version.
+"
+" 'installed' and 'required' must be arrays. If they have different lengths,
+" the "missing" elements will be assumed to be 0 for the purposes of checking.
+"
+" See http://semver.org for info about version numbers.
+function! syntastic#util#versionIsAtLeast(installed, required) abort " {{{2
+ return syntastic#util#compareLexi(a:installed, a:required) >= 0
+endfunction " }}}2
+
+" Almost lexicographic comparison of two lists of integers. :) If lists
+" have different lengths, the "missing" elements are assumed to be 0.
+function! syntastic#util#compareLexi(a, b) abort " {{{2
+ for idx in range(max([len(a:a), len(a:b)]))
+ let a_element = str2nr(get(a:a, idx, 0))
+ let b_element = str2nr(get(a:b, idx, 0))
+ if a_element != b_element
+ return a_element > b_element ? 1 : -1
+ endif
+ endfor
+ " still here, thus everything matched
+ return 0
+endfunction " }}}2
+
+" strwidth() was added in Vim 7.3; if it doesn't exist, we use strlen()
+" and hope for the best :)
+let s:_width = function(exists('*strwidth') ? 'strwidth' : 'strlen')
+lockvar s:_width
+
+function! syntastic#util#screenWidth(str, tabstop) abort " {{{2
+ let chunks = split(a:str, "\t", 1)
+ let width = s:_width(chunks[-1])
+ for c in chunks[:-2]
+ let cwidth = s:_width(c)
+ let width += cwidth + a:tabstop - cwidth % a:tabstop
+ endfor
+ return width
+endfunction " }}}2
+
+" Print as much of a:msg as possible without "Press Enter" prompt appearing
+function! syntastic#util#wideMsg(msg) abort " {{{2
+ let old_ruler = &ruler
+ let old_showcmd = &showcmd
+
+ "This is here because it is possible for some error messages to
+ "begin with \n which will cause a "press enter" prompt.
+ let msg = substitute(a:msg, "\n", '', 'g')
+
+ "convert tabs to spaces so that the tabs count towards the window
+ "width as the proper amount of characters
+ let chunks = split(msg, "\t", 1)
+ let msg = join(map(chunks[:-2], 'v:val . repeat(" ", &tabstop - s:_width(v:val) % &tabstop)'), '') . chunks[-1]
+ let msg = strpart(msg, 0, &columns - 1)
+
+ set noruler noshowcmd
+ call syntastic#util#redraw(0)
+
+ echo msg
+
+ let &ruler = old_ruler
+ let &showcmd = old_showcmd
+endfunction " }}}2
+
+" Check whether a buffer is loaded, listed, and not hidden
+function! syntastic#util#bufIsActive(buffer) abort " {{{2
+ " convert to number, or hell breaks loose
+ let buf = str2nr(a:buffer)
+
+ if !bufloaded(buf) || !buflisted(buf)
+ return 0
+ endif
+
+ " get rid of hidden buffers
+ for tab in range(1, tabpagenr('$'))
+ if index(tabpagebuflist(tab), buf) >= 0
+ return 1
+ endif
+ endfor
+
+ return 0
+endfunction " }}}2
+
+" Start in directory a:where and walk up the parent folders until it finds a
+" file named a:what; return path to that file
+function! syntastic#util#findFileInParent(what, where) abort " {{{2
+ let old_suffixesadd = &suffixesadd
+ let &suffixesadd = ''
+ let file = findfile(a:what, escape(a:where, ' ') . ';')
+ let &suffixesadd = old_suffixesadd
+ return file
+endfunction " }}}2
+
+" Start in directory a:where and walk up the parent folders until it finds a
+" file matching a:what; return path to that file
+function! syntastic#util#findGlobInParent(what, where) abort " {{{2
+ let here = fnamemodify(a:where, ':p')
+
+ let root = syntastic#util#Slash()
+ if syntastic#util#isRunningWindows() && here[1] ==# ':'
+ " The drive letter is an ever-green source of fun. That's because
+ " we don't care about running syntastic on Amiga these days. ;)
+ let root = fnamemodify(root, ':p')
+ let root = here[0] . root[1:]
+ endif
+
+ let old = ''
+ while here !=# ''
+ try
+ " Vim 7.4.279 and later
+ let p = globpath(here, a:what, 1, 1)
+ catch /\m^Vim\%((\a\+)\)\=:E118/
+ let p = split(globpath(here, a:what, 1), "\n")
+ endtry
+
+ if !empty(p)
+ return fnamemodify(p[0], ':p')
+ elseif here ==? root || here ==? old
+ break
+ endif
+
+ let old = here
+
+ " we use ':h:h' rather than ':h' since ':p' adds a trailing '/'
+ " if 'here' is a directory
+ let here = fnamemodify(here, ':p:h:h')
+ endwhile
+
+ return ''
+endfunction " }}}2
+
+" Returns unique elements in a list
+function! syntastic#util#unique(list) abort " {{{2
+ let seen = {}
+ let uniques = []
+ for e in a:list
+ let k = string(e)
+ if !has_key(seen, k)
+ let seen[k] = 1
+ call add(uniques, e)
+ endif
+ endfor
+ return uniques
+endfunction " }}}2
+
+" A less noisy shellescape()
+function! syntastic#util#shescape(string) abort " {{{2
+ return a:string =~# '\m^[A-Za-z0-9_/.-]\+$' ? a:string : shellescape(a:string)
+endfunction " }}}2
+
+" A less noisy shellescape(expand())
+function! syntastic#util#shexpand(string, ...) abort " {{{2
+ return syntastic#util#shescape(a:0 ? expand(a:string, a:1) : expand(a:string, 1))
+endfunction " }}}2
+
+" Escape arguments
+function! syntastic#util#argsescape(opt) abort " {{{2
+ if type(a:opt) == type('') && a:opt !=# ''
+ return [a:opt]
+ elseif type(a:opt) == type([])
+ return map(copy(a:opt), 'syntastic#util#shescape(v:val)')
+ endif
+
+ return []
+endfunction " }}}2
+
+" Decode XML entities
+function! syntastic#util#decodeXMLEntities(string) abort " {{{2
+ let str = a:string
+ let str = substitute(str, '\m&lt;', '<', 'g')
+ let str = substitute(str, '\m&gt;', '>', 'g')
+ let str = substitute(str, '\m&quot;', '"', 'g')
+ let str = substitute(str, '\m&apos;', "'", 'g')
+ let str = substitute(str, '\m&amp;', '\&', 'g')
+ return str
+endfunction " }}}2
+
+function! syntastic#util#redraw(full) abort " {{{2
+ if a:full
+ redraw!
+ else
+ redraw
+ endif
+endfunction " }}}2
+
+function! syntastic#util#dictFilter(errors, filter) abort " {{{2
+ let rules = s:_translateFilter(a:filter)
+ " call syntastic#log#debug(g:_SYNTASTIC_DEBUG_TRACE, "applying filter:", rules)
+ try
+ call filter(a:errors, rules)
+ catch /\m^Vim\%((\a\+)\)\=:E/
+ let msg = matchstr(v:exception, '\m^Vim\%((\a\+)\)\=:\zs.*')
+ call syntastic#log#error('quiet_messages: ' . msg)
+ endtry
+endfunction " }}}2
+
+" Return a [seconds, fractions] list of strings, representing the
+" (hopefully high resolution) time since program start
+function! syntastic#util#stamp() abort " {{{2
+ return split( split(reltimestr(reltime(g:_SYNTASTIC_START)))[0], '\.' )
+endfunction " }}}2
+
+function! syntastic#util#setChangedtick() abort " {{{2
+ unlockvar! b:syntastic_changedtick
+ let b:syntastic_changedtick = b:changedtick
+ lockvar! b:syntastic_changedtick
+endfunction " }}}2
+
+let s:_wid_base = 'syntastic_' . getpid() . '_' . reltimestr(g:_SYNTASTIC_START) . '_'
+let s:_wid_pool = 0
+
+" Add unique IDs to windows
+function! syntastic#util#setWids() abort " {{{2
+ for tab in range(1, tabpagenr('$'))
+ for win in range(1, tabpagewinnr(tab, '$'))
+ if gettabwinvar(tab, win, 'syntastic_wid') ==# ''
+ call settabwinvar(tab, win, 'syntastic_wid', s:_wid_base . s:_wid_pool)
+ let s:_wid_pool += 1
+ endif
+ endfor
+ endfor
+endfunction " }}}2
+
+let s:_str2float = function(exists('*str2float') ? 'str2float' : 'str2nr')
+lockvar s:_str2float
+
+function! syntastic#util#str2float(val) abort " {{{2
+ return s:_str2float(a:val)
+endfunction " }}}2
+
+function! syntastic#util#float2str(val) abort " {{{2
+ return s:_float2str(a:val)
+endfunction " }}}2
+
+" Crude printf()-like width formatter. Handles wide characters.
+function! syntastic#util#wformat(format, str) abort " {{{2
+ if a:format ==# ''
+ return a:str
+ endif
+
+ echomsg string(a:format) . ', ' . string(a:str)
+ let specs = matchlist(a:format, '\v^(-?)(0?)(%([1-9]\d*))?%(\.(\d+))?$')
+ if len(specs) < 5
+ return a:str
+ endif
+
+ let flushleft = specs[1] ==# '-'
+ let lpad = specs[2] ==# '0' ? '0' : ' '
+ let minlen = str2nr(specs[3])
+ let maxlen = str2nr(specs[4])
+ let out = substitute(a:str, "\t", ' ', 'g')
+
+ if maxlen && s:_width(out) > maxlen
+ let chars = filter(split(out, '\zs\ze', 1), 'v:val !=# ""')
+ let out = ''
+
+ if flushleft
+ for c in chars
+ if s:_width(out . c) < maxlen
+ let out .= c
+ else
+ let out .= &encoding ==# 'utf-8' && &termencoding ==# 'utf-8' ? "\u2026" : '>'
+ break
+ endif
+ endfor
+ else
+ call reverse(chars)
+ for c in chars
+ if s:_width(c . out) < maxlen
+ let out = c . out
+ else
+ let out = (&encoding ==# 'utf-8' && &termencoding ==# 'utf-8' ? "\u2026" : '<') . out
+ break
+ endif
+ endfor
+ endif
+ endif
+
+ if minlen && s:_width(out) < minlen
+ if flushleft
+ let out .= repeat(' ', minlen - s:_width(out))
+ else
+ let out = repeat(lpad, minlen - s:_width(out)) . out
+ endif
+ endif
+
+ return out
+endfunction " }}}2
+
+" }}}1
+
+" Private functions {{{1
+
+function! s:_translateFilter(filters) abort " {{{2
+ let conditions = []
+ for k in keys(a:filters)
+ if type(a:filters[k]) == type([])
+ call extend(conditions, map(copy(a:filters[k]), 's:_translateElement(k, v:val)'))
+ else
+ call add(conditions, s:_translateElement(k, a:filters[k]))
+ endif
+ endfor
+
+ if conditions == []
+ let conditions = ['1']
+ endif
+ return len(conditions) == 1 ? conditions[0] : join(map(conditions, '"(" . v:val . ")"'), ' && ')
+endfunction " }}}2
+
+function! s:_translateElement(key, term) abort " {{{2
+ let fkey = a:key
+ if fkey[0] ==# '!'
+ let fkey = fkey[1:]
+ let not = 1
+ else
+ let not = 0
+ endif
+
+ if fkey ==? 'level'
+ let op = not ? ' ==? ' : ' !=? '
+ let ret = 'v:val["type"]' . op . string(a:term[0])
+ elseif fkey ==? 'type'
+ if a:term ==? 'style'
+ let op = not ? ' ==? ' : ' !=? '
+ let ret = 'get(v:val, "subtype", "")' . op . '"style"'
+ else
+ let op = not ? '!' : ''
+ let ret = op . 'has_key(v:val, "subtype")'
+ endif
+ elseif fkey ==? 'regex'
+ let op = not ? ' =~? ' : ' !~? '
+ let ret = 'v:val["text"]' . op . string(a:term)
+ elseif fkey ==? 'file' || fkey[:4] ==? 'file:'
+ let op = not ? ' =~# ' : ' !~# '
+ let ret = 'bufname(str2nr(v:val["bufnr"]))'
+ let mod = fkey[4:]
+ if mod !=# ''
+ let ret = 'fnamemodify(' . ret . ', ' . string(mod) . ')'
+ endif
+ let ret .= op . string(a:term)
+ else
+ call syntastic#log#warn('quiet_messages: ignoring invalid key ' . strtrans(string(fkey)))
+ let ret = '1'
+ endif
+ return ret
+endfunction " }}}2
+
+" @vimlint(EVL103, 1, a:flags)
+function! s:_delete_dumb(what, flags) abort " {{{2
+ if !exists('s:rmrf')
+ let s:rmrf =
+ \ has('unix') || has('mac') ? 'rm -rf' :
+ \ has('win32') || has('win64') ? 'rmdir /S /Q' :
+ \ has('win16') || has('win95') || has('dos16') || has('dos32') ? 'deltree /Y' : ''
+ endif
+
+ if s:rmrf !=# ''
+ silent! call syntastic#util#system(s:rmrf . ' ' . syntastic#util#shescape(a:what))
+ else
+ call s:_rmrf(a:what)
+ endif
+endfunction " }}}2
+" @vimlint(EVL103, 0, a:flags)
+
+" delete(dir, 'rf') was added in Vim 7.4.1107, but it didn't become usable until 7.4.1128
+let s:_delete = function(v:version > 704 || (v:version == 704 && has('patch1128')) ? 'delete' : 's:_delete_dumb')
+lockvar s:_delete
+
+function! s:_rmrf(what) abort " {{{2
+ if !exists('s:rmdir')
+ let s:rmdir = syntastic#util#shescape(get(g:, 'netrw_localrmdir', 'rmdir'))
+ endif
+
+ if getftype(a:what) ==# 'dir'
+ if filewritable(a:what) != 2
+ return
+ endif
+
+ try
+ " Vim 7.4.279 and later
+ let entries = globpath(a:what, '*', 1, 1)
+ catch /\m^Vim\%((\a\+)\)\=:E118/
+ let entries = split(globpath(a:what, '*', 1), "\n")
+ endtry
+ for f in entries
+ call s:_rmrf(f)
+ endfor
+ silent! call syntastic#util#system(s:rmdir . ' ' . syntastic#util#shescape(a:what))
+ else
+ silent! call delete(a:what)
+ endif
+endfunction " }}}2
+
+function! s:_float2str_smart(val) abort " {{{2
+ return printf('%.1f', a:val)
+endfunction " }}}2
+
+function! s:_float2str_dumb(val) abort " {{{2
+ return a:val
+endfunction " }}}2
+
+let s:_float2str = function(has('float') ? 's:_float2str_smart' : 's:_float2str_dumb')
+lockvar s:_float2str
+
+" }}}1
+
+let &cpo = s:save_cpo
+unlet s:save_cpo
+
+" vim: set sw=4 sts=4 et fdm=marker: