1
0
mirror of https://github.com/amix/vimrc synced 2025-07-08 18:04:59 +08:00

Use syntastic instead of pyflakes (supports a ton of more languages)

This commit is contained in:
amix
2014-02-08 10:05:16 +00:00
parent 8265dca5d5
commit 497b5aa4fb
193 changed files with 11942 additions and 3531 deletions

View File

@ -0,0 +1,329 @@
if exists("g:loaded_syntastic_c_autoload")
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()
let known_os = has('unix') || has('mac') || syntastic#util#isRunningWindows()
return known_os ? '-o ' . syntastic#util#DevNull() : ''
endfunction
" 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)
" search in the current file's directory upwards
let config = findfile(a:file, '.;')
if config == '' || !filereadable(config)
return ''
endif
" convert filename into absolute path
let filepath = fnamemodify(config, ':p:h')
" try to read config file
try
let lines = readfile(config)
catch /^Vim\%((\a\+)\)\=:E48[45]/
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
" GetLocList() for C-like compilers
function! syntastic#c#GetLocList(filetype, subchecker, options)
try
let flags = s:GetCflags(a:filetype, a:subchecker, a:options)
catch /\m\C^Syntastic: skip checks$/
return []
endtry
let makeprg = expand(g:syntastic_{a:filetype}_compiler) . ' ' . flags . ' ' . syntastic#util#shexpand('%')
let errorformat = s:GetCheckerVar('g', a:filetype, a:subchecker, 'errorformat', a:options['errorformat'])
let postprocess = s:GetCheckerVar('g', a:filetype, a:subchecker, 'remove_include_errors', 0) ?
\ ['filterForeignErrors'] : []
" process makeprg
return SyntasticMake({
\ 'makeprg': makeprg,
\ 'errorformat': errorformat,
\ 'postprocess': postprocess })
endfunction
" Private functions {{{1
" initialize c/cpp syntax checker handlers
function! s:Init()
let s:handlers = []
let s:cflags = {}
call s:RegHandler('\m\<cairo', 'syntastic#c#CheckPKG', ['cairo', 'cairo'])
call s:RegHandler('\m\<freetype', 'syntastic#c#CheckPKG', ['freetype', 'freetype2', 'freetype'])
call s:RegHandler('\m\<glade', 'syntastic#c#CheckPKG', ['glade', 'libglade-2.0', 'libglade'])
call s:RegHandler('\m\<glib', 'syntastic#c#CheckPKG', ['glib', 'glib-2.0', 'glib'])
call s:RegHandler('\m\<gtk', 'syntastic#c#CheckPKG', ['gtk', 'gtk+-2.0', 'gtk+', 'glib-2.0', 'glib'])
call s:RegHandler('\m\<libsoup', 'syntastic#c#CheckPKG', ['libsoup', 'libsoup-2.4', 'libsoup-2.2'])
call s:RegHandler('\m\<libxml', 'syntastic#c#CheckPKG', ['libxml', 'libxml-2.0', 'libxml'])
call s:RegHandler('\m\<pango', 'syntastic#c#CheckPKG', ['pango', 'pango'])
call s:RegHandler('\m\<SDL', 'syntastic#c#CheckPKG', ['sdl', 'sdl'])
call s:RegHandler('\m\<opengl', 'syntastic#c#CheckPKG', ['opengl', 'gl'])
call s:RegHandler('\m\<webkit', 'syntastic#c#CheckPKG', ['webkit', 'webkit-1.0'])
call s:RegHandler('\m\<php\.h\>', 'syntastic#c#CheckPhp', [])
call s:RegHandler('\m\<Python\.h\>', 'syntastic#c#CheckPython', [])
call s:RegHandler('\m\<ruby', 'syntastic#c#CheckRuby', [])
endfunction
" resolve checker-related user variables
function! s:GetCheckerVar(scope, filetype, subchecker, name, default)
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
" resolve user CFLAGS
function! s:GetCflags(ft, ck, opts)
" determine whether to parse header files as well
if has_key(a:opts, 'header_names') && expand('%') =~? a:opts['header_names']
if s:GetCheckerVar('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:GetCheckerVar('g', a:ft, a:ck, 'compiler_options', '') . ' ' . s:GetIncludeDirs(a:ft)
" check if the user manually set some cflags
let b_cflags = s:GetCheckerVar('b', a:ft, a:ck, 'cflags', '')
if b_cflags == ''
" check whether to search for include files at all
if !s:GetCheckerVar('g', a:ft, a:ck, 'no_include_search', 0)
if a:ft ==# 'c' || a:ft ==# 'cpp'
" refresh the include file search if desired
if s:GetCheckerVar('g', a:ft, a:ck, 'auto_refresh_includes', 0)
let flags .= ' ' . s:SearchHeaders()
else
" search for header includes if not cached already
if !exists('b:syntastic_' . a:ft . '_includes')
let b:syntastic_{a:ft}_includes = s:SearchHeaders()
endif
let flags .= ' ' . b:syntastic_{a:ft}_includes
endif
endif
endif
else
" user-defined cflags
let flags .= ' ' . b_cflags
endif
" add optional config file parameters
let config_file = s:GetCheckerVar('g', a:ft, a:ck, 'config_file', '.syntastic_' . a:ft . '_config')
let flags .= ' ' . syntastic#c#ReadConfig(config_file)
return flags
endfunction
" get the gcc include directory argument depending on the default
" includes and the optional user-defined 'g:syntastic_c_include_dirs'
function! s:GetIncludeDirs(filetype)
let include_dirs = []
if a:filetype =~# '\v^%(c|cpp|d|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
" search the first 100 lines for include statements that are
" given in the handlers dictionary
function! s:SearchHeaders()
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') . syntastic#util#Slash() . hfile
try
let lines = readfile(filename, '', 100)
catch /^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
" try to find library with 'pkg-config'
" search possible libraries from first to last given
" argument until one is found
function! syntastic#c#CheckPKG(name, ...)
if executable('pkg-config')
if !has_key(s:cflags, a:name)
for pkg in a:000
let pkg_flags = 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
" try to find PHP includes with 'php-config'
function! syntastic#c#CheckPhp()
if executable('php-config')
if !has_key(s:cflags, 'php')
let s:cflags['php'] = system('php-config --includes')
let s:cflags['php'] = ' ' . substitute(s:cflags['php'], "\n", '', '')
endif
return s:cflags['php']
endif
return ''
endfunction
" try to find the ruby headers with 'rbconfig'
function! syntastic#c#CheckRuby()
if executable('ruby')
if !has_key(s:cflags, 'ruby')
let s:cflags['ruby'] = 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
" try to find the python headers with distutils
function! syntastic#c#CheckPython()
if executable('python')
if !has_key(s:cflags, 'python')
let s:cflags['python'] = 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
" return a handler dictionary object
function! s:RegHandler(regex, function, args)
let handler = {}
let handler["regex"] = a:regex
let handler["func"] = function(a:function)
let handler["args"] = a:args
call add(s:handlers, handler)
endfunction
" }}}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 et sts=4 sw=4 fdm=marker:

View File

@ -0,0 +1,181 @@
if exists("g:loaded_syntastic_log_autoload")
finish
endif
let g:loaded_syntastic_log_autoload = 1
let s:save_cpo = &cpo
set cpo&vim
if !exists("g:syntastic_debug")
let g:syntastic_debug = 0
endif
let s:global_options = [
\ 'syntastic_aggregate_errors',
\ 'syntastic_always_populate_loc_list',
\ 'syntastic_auto_jump',
\ 'syntastic_auto_loc_list',
\ 'syntastic_check_on_open',
\ 'syntastic_check_on_wq',
\ 'syntastic_debug',
\ 'syntastic_echo_current_error',
\ 'syntastic_enable_balloons',
\ 'syntastic_enable_highlighting',
\ 'syntastic_enable_signs',
\ 'syntastic_error_symbol',
\ 'syntastic_filetype_map',
\ 'syntastic_full_redraws',
\ 'syntastic_id_checkers',
\ 'syntastic_ignore_files',
\ 'syntastic_loc_list_height',
\ 'syntastic_mode_map',
\ 'syntastic_quiet_messages',
\ 'syntastic_reuse_loc_lists',
\ 'syntastic_stl_format',
\ 'syntastic_style_error_symbol',
\ 'syntastic_style_warning_symbol',
\ 'syntastic_warning_symbol' ]
let s:deprecation_notices_issued = []
" Public functions {{{1
function! syntastic#log#info(msg)
echomsg "syntastic: info: " . a:msg
endfunction
function! syntastic#log#warn(msg)
echohl WarningMsg
echomsg "syntastic: warning: " . a:msg
echohl None
endfunction
function! syntastic#log#error(msg)
execute "normal \<Esc>"
echohl ErrorMsg
echomsg "syntastic: error: " . a:msg
echohl None
endfunction
function! syntastic#log#deprecationWarn(msg)
if index(s:deprecation_notices_issued, a:msg) >= 0
return
endif
call add(s:deprecation_notices_issued, a:msg)
call syntastic#log#warn(a:msg)
endfunction
function! syntastic#log#debug(level, msg, ...)
if !s:isDebugEnabled(a:level)
return
endif
let leader = s:logTimestamp()
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
function! syntastic#log#debugShowOptions(level, names)
if !s:isDebugEnabled(a:level)
return
endif
let leader = s:logTimestamp()
call s:logRedirect(1)
let vlist = type(a:names) == type("") ? [a:names] : a:names
if !empty(vlist)
call map(vlist, "'&' . v:val . ' = ' . strtrans(string(eval('&' . v:val)))")
echomsg leader . join(vlist, ', ')
endif
call s:logRedirect(0)
endfunction
function! syntastic#log#debugShowVariables(level, names)
if !s:isDebugEnabled(a:level)
return
endif
let leader = s:logTimestamp()
call s:logRedirect(1)
let vlist = type(a:names) == type("") ? [a:names] : a:names
for name in vlist
echomsg leader . s:formatVariable(name)
endfor
call s:logRedirect(0)
endfunction
function! syntastic#log#debugDump(level)
if !s:isDebugEnabled(a:level)
return
endif
call syntastic#log#debugShowVariables(a:level, s:global_options)
endfunction
" Private functions {{{1
function! s:isDebugEnabled_smart(level)
return and(g:syntastic_debug, a:level)
endfunction
function! s:isDebugEnabled_dumb(level)
" poor man's bit test for bit N, assuming a:level == 2**N
return (g:syntastic_debug / a:level) % 2
endfunction
let s:isDebugEnabled = function(exists('*and') ? 's:isDebugEnabled_smart' : 's:isDebugEnabled_dumb')
function! s:logRedirect(on)
if exists("g:syntastic_debug_file")
if a:on
try
execute 'redir >> ' . fnameescape(expand(g:syntastic_debug_file))
catch /^Vim\%((\a\+)\)\=:/
silent! redir END
unlet g:syntastic_debug_file
endtry
else
silent! redir END
endif
endif
endfunction
function! s:logTimestamp_smart()
return 'syntastic: ' . split(reltimestr(reltime(g:syntastic_start)))[0] . ': '
endfunction
function! s:logTimestamp_dumb()
return 'syntastic: debug: '
endfunction
let s:logTimestamp = function(has('reltime') ? 's:logTimestamp_smart' : 's:logTimestamp_dumb')
function! s:formatVariable(name)
let vals = []
if exists('g:' . a:name)
call add(vals, 'g:' . a:name . ' = ' . strtrans(string(g:{a:name})))
endif
if exists('b:' . a:name)
call add(vals, 'b:' . a:name . ' = ' . strtrans(string(b:{a:name})))
endif
return join(vals, ', ')
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo
" vim: set et sts=4 sw=4 fdm=marker:

View File

@ -0,0 +1,67 @@
if exists("g:loaded_syntastic_postprocess_autoload")
finish
endif
let g:loaded_syntastic_postprocess_autoload = 1
let s:save_cpo = &cpo
set cpo&vim
function! s:compareErrorItems(a, b)
if a:a['bufnr'] != a:b['bufnr']
" group by files
return a:a['bufnr'] - a:b['bufnr']
elseif a:a['lnum'] != a:b['lnum']
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
return get(a:a, 'col', 0) - get(a:b, 'col', 0)
endif
endfunction
" natural sort
function! syntastic#postprocess#sort(errors)
return sort(copy(a:errors), 's:compareErrorItems')
endfunction
" merge consecutive blanks
function! syntastic#postprocess#compressWhitespace(errors)
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')
endfor
return a:errors
endfunction
" remove spurious CR under Cygwin
function! syntastic#postprocess#cygwinRemoveCR(errors)
if has('win32unix')
for e in a:errors
let e['text'] = substitute(e['text'], '\r', '', 'g')
endfor
endif
return a:errors
endfunction
" decode XML entities
function! syntastic#postprocess#decodeXMLEntities(errors)
for e in a:errors
let e['text'] = syntastic#util#decodeXMLEntities(e['text'])
endfor
return a:errors
endfunction
" filter out errors referencing other files
function! syntastic#postprocess#filterForeignErrors(errors)
return filter(copy(a:errors), 'get(v:val, "bufnr") == ' . bufnr(''))
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo
" vim: set et sts=4 sw=4:

View File

@ -0,0 +1,244 @@
if exists('g:loaded_syntastic_util_autoload')
finish
endif
let g:loaded_syntastic_util_autoload = 1
let s:save_cpo = &cpo
set cpo&vim
" 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')
" Public functions {{{1
function! syntastic#util#isRunningWindows()
return has('win16') || has('win32') || has('win64')
endfunction
function! syntastic#util#DevNull()
if syntastic#util#isRunningWindows()
return 'NUL'
endif
return '/dev/null'
endfunction
" Get directory separator
function! syntastic#util#Slash() abort
return (!exists("+shellslash") || &shellslash) ? '/' : '\'
endfunction
"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()
for lnum in range(1,5)
let line = getline(lnum)
if line =~ '^#!'
let exe = matchstr(line, '\m^#!\s*\zs[^ \t]*')
let args = split(matchstr(line, '\m^#!\s*[^ \t]*\zs.*'))
return { 'exe': exe, 'args': args }
endif
endfor
return { 'exe': '', 'args': [] }
endfunction
" Parse a version string. Return an array of version components.
function! syntastic#util#parseVersion(version)
return split(matchstr( a:version, '\v^\D*\zs\d+(\.\d+)+\ze' ), '\m\.')
endfunction
" Run 'command' in a shell and parse output as a version string.
" Returns an array of version components.
function! syntastic#util#getVersion(command)
return syntastic#util#parseVersion(system(a:command))
endfunction
" 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)
for idx in range(max([len(a:installed), len(a:required)]))
let installed_element = get(a:installed, idx, 0)
let required_element = get(a:required, idx, 0)
if installed_element != required_element
return installed_element > required_element
endif
endfor
" Everything matched, so it is at least the required version.
return 1
endfunction
"print as much of a:msg as possible without "Press Enter" prompt appearing
function! syntastic#util#wideMsg(msg)
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(" ", &ts - s:width(v:val) % &ts)'), '') . chunks[-1]
let msg = strpart(msg, 0, winwidth(0) - 1)
set noruler noshowcmd
call syntastic#util#redraw(0)
echo msg
let &ruler = old_ruler
let &showcmd = old_showcmd
endfunction
" Check whether a buffer is loaded, listed, and not hidden
function! syntastic#util#bufIsActive(buffer)
" 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
" 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#findInParent(what, where)
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 != ''
let p = split(globpath(here, a:what), '\n')
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
" Returns unique elements in a list
function! syntastic#util#unique(list)
let seen = {}
let uniques = []
for e in a:list
if !has_key(seen, e)
let seen[e] = 1
call add(uniques, e)
endif
endfor
return uniques
endfunction
" A less noisy shellescape()
function! syntastic#util#shescape(string)
return a:string =~ '\m^[A-Za-z0-9_/.-]\+$' ? a:string : shellescape(a:string)
endfunction
" A less noisy shellescape(expand())
function! syntastic#util#shexpand(string)
return syntastic#util#shescape(expand(a:string))
endfunction
" decode XML entities
function! syntastic#util#decodeXMLEntities(string)
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
function! syntastic#util#redraw(full)
if a:full
redraw!
else
redraw
endif
endfunction
function! syntastic#util#dictFilter(errors, filter)
let rules = s:translateFilter(a:filter)
" call syntastic#log#debug(g:SyntasticDebugFilters, "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
" Private functions {{{1
function! s:translateFilter(filters)
let conditions = []
for [k, v] in items(a:filters)
if type(v) == type([])
call extend(conditions, map(copy(v), 's:translateElement(k, v:val)'))
else
call add(conditions, s:translateElement(k, v))
endif
endfor
return len(conditions) == 1 ? conditions[0] : join(map(conditions, '"(" . v:val . ")"'), ' && ')
endfunction
function! s:translateElement(key, term)
if a:key ==? 'level'
let ret = 'v:val["type"] !=? ' . string(a:term[0])
elseif a:key ==? 'type'
let ret = a:term ==? 'style' ? 'get(v:val, "subtype", "") !=? "style"' : 'has_key(v:val, "subtype")'
elseif a:key ==? 'regex'
let ret = 'v:val["text"] !~? ' . string(a:term)
elseif a:key ==? 'file'
let ret = 'bufname(str2nr(v:val["bufnr"])) !~# ' . string(a:term)
else
let ret = "1"
endif
return ret
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo
" vim: set et sts=4 sw=4 fdm=marker: