2009-07-10 21:39:39 -04:00
"============================================================================
"File: syntastic.vim
2013-04-13 11:02:03 -04:00
"Description: Vim plugin for on the fly syntax checking.
2009-07-10 21:39:39 -04:00
"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.
"
"============================================================================
2015-03-25 12:44:34 -04:00
if exists ( 'g:loaded_syntastic_plugin' )
2009-07-10 19:09:52 -04:00
finish
endif
let g :loaded_syntastic_plugin = 1
2013-11-13 03:58:33 -05:00
if has ( 'reltime' )
2014-10-17 11:53:53 -04:00
let g :_SYNTASTIC_START = reltime ( )
lockvar ! g :_SYNTASTIC_START
2013-11-13 03:58:33 -05:00
endif
2015-05-03 12:45:24 -04:00
let g :_SYNTASTIC_VERSION = '3.6.0-79'
2014-10-17 11:53:53 -04:00
lockvar g :_SYNTASTIC_VERSION
2014-03-08 02:27:21 -05:00
2014-02-23 04:07:39 -05:00
" Sanity checks {{{1
2009-07-10 19:09:52 -04:00
2014-10-02 03:05:24 -04:00
for s :feature in [
\ 'autocmd' ,
\ 'eval' ,
\ 'file_in_path' ,
\ 'modify_fname' ,
\ 'quickfix' ,
\ 'reltime' ,
\ 'user_commands'
\ ]
2014-01-26 02:10:26 -05:00
if ! has ( s :feature )
2015-03-25 12:44:34 -04:00
call syntastic #log #error ( 'need Vim compiled with feature ' . s :feature )
2013-10-28 19:15:44 -04:00
finish
endif
endfor
2014-10-17 11:53:53 -04:00
let s :_running_windows = syntastic #util #isRunningWindows ( )
lockvar s :_running_windows
2014-04-23 07:45:21 -04:00
2015-03-12 13:20:06 -04:00
if ! exists ( 'g:syntastic_shell' )
let g :syntastic_shell = &shell
endif
2015-02-12 07:04:35 -05:00
if s :_running_windows
let g :_SYNTASTIC_UNAME = 'Windows'
elseif executable ( 'uname' )
2013-09-24 14:41:59 -04:00
try
2015-03-12 13:20:06 -04:00
let g :_SYNTASTIC_UNAME = split ( syntastic #util #system ( 'uname' ) , "\n" ) [0 ]
2014-02-23 18:10:33 -05:00
catch /\m^Vim\%((\a\+)\)\=:E484/
2015-03-12 13:20:06 -04:00
call syntastic #log #error ( "your shell " . syntastic #util #var ( 'shell' ) . " can't handle traditional UNIX syntax for redirections" )
2013-09-24 14:41:59 -04:00
finish
2015-02-12 07:04:35 -05:00
catch /\m^Vim\%((\a\+)\)\=:E684/
let g :_SYNTASTIC_UNAME = 'Unknown'
2013-09-24 14:41:59 -04:00
endtry
2015-02-12 07:04:35 -05:00
else
let g :_SYNTASTIC_UNAME = 'Unknown'
2013-09-24 14:41:59 -04:00
endif
2015-02-12 07:04:35 -05:00
lockvar g :_SYNTASTIC_UNAME
2013-09-24 14:41:59 -04:00
2014-02-23 04:07:39 -05:00
" }}}1
" Defaults {{{1
2014-10-17 11:53:53 -04:00
let g :_SYNTASTIC_DEFAULTS = {
2014-02-23 03:22:37 -05:00
\ 'aggregate_errors' : 0 ,
\ 'always_populate_loc_list' : 0 ,
\ 'auto_jump' : 0 ,
\ 'auto_loc_list' : 2 ,
\ 'check_on_open' : 0 ,
\ 'check_on_wq' : 1 ,
2014-07-26 13:54:22 -04:00
\ 'cursor_columns' : 1 ,
2014-02-23 03:22:37 -05:00
\ 'debug' : 0 ,
\ 'echo_current_error' : 1 ,
\ 'enable_balloons' : 1 ,
\ 'enable_highlighting' : 1 ,
\ 'enable_signs' : 1 ,
\ 'error_symbol' : '>>' ,
2015-03-12 13:20:06 -04:00
\ 'exit_checks' : ! ( s :_running_windows && syntastic #util #var ( 'shell' , &shell ) = ~ ? '\m\<cmd\.exe$' ) ,
2014-02-23 03:22:37 -05:00
\ 'filetype_map' : {},
\ 'full_redraws' : ! ( has ( 'gui_running' ) | | has ( 'gui_macvim' ) ) ,
\ 'id_checkers' : 1 ,
2014-07-13 15:43:57 -04:00
\ 'ignore_extensions' : '\c\v^([gx]?z|lzma|bz2)$' ,
2014-02-23 03:22:37 -05:00
\ 'ignore_files' : [],
\ 'loc_list_height' : 10 ,
\ 'quiet_messages' : {},
2014-07-20 14:32:29 -04:00
\ 'reuse_loc_lists' : 0 ,
2015-03-12 13:20:06 -04:00
\ 'shell' : &shell ,
2014-04-17 15:09:12 -04:00
\ 'sort_aggregated_errors' : 1 ,
2014-02-23 03:22:37 -05:00
\ 'stl_format' : '[Syntax: line:%F (%t)]' ,
\ 'style_error_symbol' : 'S>' ,
\ 'style_warning_symbol' : 'S>' ,
2014-02-24 04:04:34 -05:00
\ 'warning_symbol' : '>>'
2014-02-23 03:22:37 -05:00
\ }
2014-10-17 11:53:53 -04:00
lockvar ! g :_SYNTASTIC_DEFAULTS
2014-02-23 03:22:37 -05:00
2014-10-17 11:53:53 -04:00
for s :key in keys ( g :_SYNTASTIC_DEFAULTS )
2014-02-23 03:22:37 -05:00
if ! exists ( 'g:syntastic_' . s :key )
2014-10-17 11:53:53 -04:00
let g :syntastic_ {s :key } = copy ( g :_SYNTASTIC_DEFAULTS [s :key ])
2014-02-23 03:22:37 -05:00
endif
endfor
2013-08-13 02:31:43 -04:00
2015-03-25 12:44:34 -04:00
if exists ( 'g:syntastic_quiet_warnings' )
2014-06-24 12:02:42 -04:00
call syntastic #log #oneTimeWarn ( "variable g:syntastic_quiet_warnings is deprecated, please use let g:syntastic_quiet_messages = {'level': 'warnings'} instead" )
2013-12-12 13:40:30 -05:00
if g :syntastic_quiet_warnings
2014-01-26 02:10:26 -05:00
let s :quiet_warnings = get ( g :syntastic_quiet_messages , 'type' , [])
if type ( s :quiet_warnings ) ! = type ( [])
let s :quiet_warnings = [s :quiet_warnings ]
2013-12-12 13:40:30 -05:00
endif
2014-01-26 02:10:26 -05:00
call add ( s :quiet_warnings , 'warnings' )
let g :syntastic_quiet_messages ['type' ] = s :quiet_warnings
2013-12-12 13:40:30 -05:00
endif
endif
2014-02-23 04:07:39 -05:00
" }}}1
" Debug {{{1
2014-10-17 11:53:53 -04:00
let s :_DEBUG_DUMP_OPTIONS = [
2014-02-13 00:09:20 -05:00
\ 'shell' ,
\ 'shellcmdflag' ,
\ 'shellpipe' ,
\ 'shellquote' ,
\ 'shellredir' ,
\ 'shellslash' ,
\ 'shelltemp' ,
\ 'shellxquote'
\ ]
if v :version > 703 | | ( v :version = = 703 && has ( 'patch446' ) )
2014-10-17 11:53:53 -04:00
call add ( s :_DEBUG_DUMP_OPTIONS , 'shellxescape' )
2014-02-13 00:09:20 -05:00
endif
2014-10-17 11:53:53 -04:00
lockvar ! s :_DEBUG_DUMP_OPTIONS
2014-02-13 00:09:20 -05:00
2013-11-13 03:58:33 -05:00
" debug constants
2014-10-17 11:53:53 -04:00
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
2013-11-13 03:58:33 -05:00
2014-02-23 04:07:39 -05:00
" }}}1
runtime ! plugin /syntastic/ *.vim
2013-01-23 19:01:30 -05:00
let s :registry = g :SyntasticRegistry .Instance ( )
2013-06-01 00:45:42 -04:00
let s :notifiers = g :SyntasticNotifiers .Instance ( )
2013-03-22 18:50:47 -04:00
let s :modemap = g :SyntasticModeMap .Instance ( )
2013-01-23 19:01:30 -05:00
2014-02-23 04:07:39 -05:00
" Commands {{{1
2013-12-12 13:40:30 -05:00
2014-01-26 02:10:26 -05:00
" @vimlint(EVL103, 1, a:cursorPos)
" @vimlint(EVL103, 1, a:cmdLine)
" @vimlint(EVL103, 1, a:argLead)
2015-02-23 09:40:53 -05:00
function ! s :CompleteCheckerName ( argLead , cmdLine , cursorPos ) abort " {{{2
2013-02-01 02:36:41 -05:00
let checker_names = []
2014-11-03 13:12:21 -05:00
for ft in s :_resolve_filetypes ( [])
2014-06-02 14:25:49 -04:00
call extend ( checker_names , s :registry .getNamesOfAvailableCheckers ( ft ) )
2013-02-01 02:36:41 -05:00
endfor
return join ( checker_names , "\n" )
2014-02-23 04:07:39 -05:00
endfunction " }}}2
2014-01-26 02:10:26 -05:00
" @vimlint(EVL103, 0, a:cursorPos)
" @vimlint(EVL103, 0, a:cmdLine)
" @vimlint(EVL103, 0, a:argLead)
2013-02-01 02:36:41 -05:00
2014-01-26 02:10:26 -05:00
" @vimlint(EVL103, 1, a:cursorPos)
" @vimlint(EVL103, 1, a:cmdLine)
" @vimlint(EVL103, 1, a:argLead)
2015-02-23 09:40:53 -05:00
function ! s :CompleteFiletypes ( argLead , cmdLine , cursorPos ) abort " {{{2
2014-02-17 16:32:53 -05:00
return join ( s :registry .getKnownFiletypes ( ) , "\n" )
2014-02-23 04:07:39 -05:00
endfunction " }}}2
2014-01-26 02:10:26 -05:00
" @vimlint(EVL103, 0, a:cursorPos)
" @vimlint(EVL103, 0, a:cmdLine)
" @vimlint(EVL103, 0, a:argLead)
2014-11-04 01:42:08 -05:00
command ! - nargs = * - complete = custom , s :CompleteCheckerName SyntasticCheck call SyntasticCheck ( < f - args > )
command ! - nargs = ? - complete = custom , s :CompleteFiletypes SyntasticInfo call SyntasticInfo ( < f - args > )
command ! Errors call SyntasticErrors ( )
command ! SyntasticReset call SyntasticReset ( )
command ! SyntasticToggleMode call SyntasticToggleMode ( )
command ! SyntasticSetLoclist call SyntasticSetLoclist ( )
" }}}1
" Public API {{{1
2015-02-23 09:40:53 -05:00
function ! SyntasticCheck ( ...) abort " {{{2
2014-11-03 13:12:21 -05:00
call s :UpdateErrors ( 0 , a :000 )
call syntastic #util #redraw ( g :syntastic_full_redraws )
endfunction " }}}2
2015-02-23 09:40:53 -05:00
function ! SyntasticInfo ( ...) abort " {{{2
2014-11-03 13:12:21 -05:00
call s :modemap .modeInfo ( a :000 )
call s :registry .echoInfoFor ( s :_resolve_filetypes ( a :000 ) )
call s :_explain_skip ( a :000 )
endfunction " }}}2
2015-02-23 09:40:53 -05:00
function ! SyntasticErrors ( ) abort " {{{2
2014-11-03 13:12:21 -05:00
call g :SyntasticLoclist .current ( ) .show ( )
endfunction " }}}2
2015-02-23 09:40:53 -05:00
function ! SyntasticReset ( ) abort " {{{2
2014-11-03 13:12:21 -05:00
call s :ClearCache ( )
call s :notifiers .refresh ( g :SyntasticLoclist .New ( []) )
endfunction " }}}2
2015-02-23 09:40:53 -05:00
function ! SyntasticToggleMode ( ) abort " {{{2
2014-11-03 13:12:21 -05:00
call s :modemap .toggleMode ( )
call s :ClearCache ( )
call s :notifiers .refresh ( g :SyntasticLoclist .New ( []) )
call s :modemap .echoMode ( )
endfunction " }}}2
2015-02-23 09:40:53 -05:00
function ! SyntasticSetLoclist ( ) abort " {{{2
2014-11-03 13:12:21 -05:00
call g :SyntasticLoclist .current ( ) .setloclist ( )
endfunction " }}}2
2011-11-28 18:44:40 -05:00
2014-02-23 04:07:39 -05:00
" }}}1
2014-11-04 01:42:08 -05:00
" Autocommands {{{1
2014-02-23 04:07:39 -05:00
2011-12-09 20:15:24 -05:00
augroup syntastic
2014-11-03 13:12:21 -05:00
autocmd BufReadPost * call s :BufReadPostHook ( )
2013-11-13 03:58:33 -05:00
autocmd BufWritePost * call s :BufWritePostHook ( )
2014-11-03 13:12:21 -05:00
autocmd BufEnter * call s :BufEnterHook ( )
2011-12-09 20:15:24 -05:00
augroup END
2013-04-27 11:06:18 -04:00
if v :version > 703 | | ( v :version = = 703 && has ( 'patch544' ) )
" QuitPre was added in Vim 7.3.544
augroup syntastic
2013-05-06 13:18:02 -04:00
autocmd QuitPre * call s :QuitPreHook ( )
2013-04-27 11:06:18 -04:00
augroup END
endif
2015-02-23 09:40:53 -05:00
function ! s :BufReadPostHook ( ) abort " {{{2
2013-11-13 03:58:33 -05:00
if g :syntastic_check_on_open
2014-10-17 11:53:53 -04:00
call syntastic #log #debug ( g :_SYNTASTIC_DEBUG_AUTOCOMMANDS ,
2015-03-25 12:44:34 -04:00
\ 'autocmd: BufReadPost, buffer ' . bufnr ( '' ) . ' = ' . string ( bufname ( str2nr ( bufnr ( '' ) ) ) ) )
2014-11-03 13:12:21 -05:00
call s :UpdateErrors ( 1 , [])
2013-11-13 03:58:33 -05:00
endif
2014-02-23 04:07:39 -05:00
endfunction " }}}2
2013-11-13 03:58:33 -05:00
2015-02-23 09:40:53 -05:00
function ! s :BufWritePostHook ( ) abort " {{{2
2014-10-17 11:53:53 -04:00
call syntastic #log #debug ( g :_SYNTASTIC_DEBUG_AUTOCOMMANDS ,
2015-03-25 12:44:34 -04:00
\ 'autocmd: BufWritePost, buffer ' . bufnr ( '' ) . ' = ' . string ( bufname ( str2nr ( bufnr ( '' ) ) ) ) )
2014-11-03 13:12:21 -05:00
call s :UpdateErrors ( 1 , [])
2014-02-23 04:07:39 -05:00
endfunction " }}}2
2013-11-13 03:58:33 -05:00
2015-02-23 09:40:53 -05:00
function ! s :BufEnterHook ( ) abort " {{{2
2014-10-17 11:53:53 -04:00
call syntastic #log #debug ( g :_SYNTASTIC_DEBUG_AUTOCOMMANDS ,
2015-03-25 12:44:34 -04:00
\ 'autocmd: BufEnter, buffer ' . bufnr ( '' ) . ' = ' . string ( bufname ( str2nr ( bufnr ( '' ) ) ) ) .
2013-11-13 03:58:33 -05:00
\ ', &buftype = ' . string ( &buftype ) )
2015-03-25 12:44:34 -04:00
if &buftype = = # ''
2014-06-27 15:34:44 -04:00
call s :notifiers .refresh ( g :SyntasticLoclist .current ( ) )
2015-02-23 10:09:00 -05:00
elseif &buftype = = # 'quickfix'
2014-06-27 15:34:44 -04:00
" 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' )
2015-03-25 12:44:34 -04:00
let owner = str2nr ( getbufvar ( bufnr ( '' ) , 'syntastic_owner_buffer' ) )
2014-06-27 15:34:44 -04:00
let buffers = syntastic #util #unique ( map ( loclist , 'v:val["bufnr"]' ) + ( owner ? [owner ] : []) )
2014-12-08 04:14:17 -05:00
if get ( w :, 'syntastic_loclist_set' , 0 ) && ! empty ( loclist ) && empty ( filter ( buffers , 'syntastic#util#bufIsActive(v:val)' ) )
2014-06-27 15:34:44 -04:00
call SyntasticLoclistHide ( )
endif
2013-04-09 11:20:14 -04:00
endif
2014-02-23 04:07:39 -05:00
endfunction " }}}2
2013-04-09 11:20:14 -04:00
2015-02-23 09:40:53 -05:00
function ! s :QuitPreHook ( ) abort " {{{2
2014-10-17 11:53:53 -04:00
call syntastic #log #debug ( g :_SYNTASTIC_DEBUG_AUTOCOMMANDS ,
2015-03-25 12:44:34 -04:00
\ 'autocmd: QuitPre, buffer ' . bufnr ( '' ) . ' = ' . string ( bufname ( str2nr ( bufnr ( '' ) ) ) ) )
2014-09-15 23:36:37 -04:00
let b :syntastic_skip_checks = get ( b :, 'syntastic_skip_checks' , 0 ) | | ! syntastic #util #var ( 'check_on_wq' )
2014-12-08 04:14:17 -05:00
if get ( w :, 'syntastic_loclist_set' , 0 )
call SyntasticLoclistHide ( )
endif
2014-02-23 04:07:39 -05:00
endfunction " }}}2
" }}}1
" Main {{{1
2013-05-06 13:18:02 -04:00
2009-07-11 20:13:06 -04:00
"refresh and redraw all the error info for this buf when saving or reading
2015-02-23 09:40:53 -05:00
function ! s :UpdateErrors ( auto_invoked , checker_names ) abort " {{{2
2014-10-17 11:53:53 -04:00
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)' : '' ) .
2014-11-03 13:12:21 -05:00
\ ': ' . ( len ( a :checker_names ) ? join ( a :checker_names ) : 'default checkers' ) )
2014-11-03 04:58:46 -05:00
if s :_skip_file ( )
2011-01-11 17:33:29 -05:00
return
endif
2011-11-28 18:44:40 -05:00
2013-10-28 15:53:10 -04:00
call s :modemap .synch ( )
2014-12-08 04:59:45 -05:00
let run_checks = ! a :auto_invoked | | s :modemap .doAutoChecking ( )
2013-07-15 11:37:37 -04:00
if run_checks
2014-11-03 13:12:21 -05:00
call s :CacheErrors ( a :checker_names )
2015-03-30 06:44:07 -04:00
unlockvar ! b :syntastic_changedtick
let b :syntastic_changedtick = b :changedtick
lockvar ! b :syntastic_changedtick
2013-09-27 03:35:46 -04:00
endif
2009-07-10 21:47:17 -04:00
2013-05-14 13:18:10 -04:00
let loclist = g :SyntasticLoclist .current ( )
2013-03-21 13:44:19 -04:00
2014-11-04 01:42:08 -05:00
if exists ( '*SyntasticCheckHook' )
call SyntasticCheckHook ( loclist .getRaw ( ) )
endif
2014-02-23 18:10:33 -05:00
" populate loclist and jump {{{3
2014-12-10 17:31:00 -05:00
let do_jump = syntastic #util #var ( 'auto_jump' ) + 0
2014-02-23 18:10:33 -05:00
if do_jump = = 2
2014-12-11 01:32:33 -05:00
let do_jump = loclist .getFirstError ( 1 )
2014-12-10 17:31:00 -05:00
elseif do_jump = = 3
let do_jump = loclist .getFirstError ( )
elseif 0 > do_jump | | do_jump > 3
let do_jump = 0
2014-01-30 06:20:40 -05:00
endif
2014-02-23 18:10:33 -05:00
let w :syntastic_loclist_set = 0
if syntastic #util #var ( 'always_populate_loc_list' ) | | do_jump
2014-10-17 11:53:53 -04:00
call syntastic #log #debug ( g :_SYNTASTIC_DEBUG_NOTIFICATIONS , 'loclist: setloclist (new)' )
2014-01-22 14:14:31 -05:00
call setloclist ( 0 , loclist .getRaw ( ) )
2013-08-13 02:31:43 -04:00
let w :syntastic_loclist_set = 1
2014-01-30 06:20:40 -05:00
if run_checks && do_jump && ! loclist .isEmpty ( )
2014-10-17 11:53:53 -04:00
call syntastic #log #debug ( g :_SYNTASTIC_DEBUG_NOTIFICATIONS , 'loclist: jump' )
2014-12-10 17:31:00 -05:00
execute 'silent! lrewind ' . do_jump
2013-12-04 12:39:30 -05:00
" 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
2015-03-25 12:44:34 -04:00
if &filetype = = # ''
2013-12-04 12:39:30 -05:00
silent ! filetype detect
endif
2013-04-10 06:40:03 -04:00
endif
2011-12-23 08:56:49 -05:00
endif
2014-02-23 18:10:33 -05:00
" }}}3
2013-06-06 17:34:05 -04:00
call s :notifiers .refresh ( loclist )
2014-02-23 04:07:39 -05:00
endfunction " }}}2
2011-12-16 11:48:26 -05:00
"clear the loc list for the buffer
2015-02-23 09:40:53 -05:00
function ! s :ClearCache ( ) abort " {{{2
2013-05-14 13:18:10 -04:00
call s :notifiers .reset ( g :SyntasticLoclist .current ( ) )
2014-04-29 07:31:43 -04:00
call b :syntastic_loclist .destroy ( )
2014-02-23 04:07:39 -05:00
endfunction " }}}2
2013-12-16 11:06:30 -05:00
2009-07-10 19:55:51 -04:00
"detect and cache all syntax errors in this buffer
2015-02-23 09:40:53 -05:00
function ! s :CacheErrors ( checker_names ) abort " {{{2
2014-10-17 11:53:53 -04:00
call syntastic #log #debug ( g :_SYNTASTIC_DEBUG_TRACE , 'CacheErrors: ' .
2014-07-22 00:55:04 -04:00
\ ( len ( a :checker_names ) ? join ( a :checker_names ) : 'default checkers' ) )
2012-02-18 10:54:22 -05:00
call s :ClearCache ( )
2013-02-01 09:16:04 -05:00
let newLoclist = g :SyntasticLoclist .New ( [])
2009-07-10 19:09:52 -04:00
2014-11-03 04:58:46 -05:00
if ! s :_skip_file ( )
2014-02-23 04:47:52 -05:00
" debug logging {{{3
2014-10-17 11:53:53 -04:00
call syntastic #log #debugShowVariables ( g :_SYNTASTIC_DEBUG_TRACE , 'aggregate_errors' )
2015-02-12 07:04:35 -05:00
call syntastic #log #debug ( g :_SYNTASTIC_DEBUG_CHECKERS , '$PATH = ' . string ( $PATH ) )
call syntastic #log #debug ( g :_SYNTASTIC_DEBUG_TRACE , 'getcwd() = ' . string ( getcwd ( ) ) )
2014-02-23 04:47:52 -05:00
" }}}3
2013-08-09 08:33:18 -04:00
2014-11-03 13:12:21 -05:00
let filetypes = s :_resolve_filetypes ( [])
2014-04-19 02:09:48 -04:00
let aggregate_errors = syntastic #util #var ( 'aggregate_errors' ) | | len ( filetypes ) > 1
let decorate_errors = aggregate_errors && syntastic #util #var ( 'id_checkers' )
2014-04-17 15:09:12 -04:00
let sort_aggregated_errors = aggregate_errors && syntastic #util #var ( 'sort_aggregated_errors' )
2013-11-02 04:39:06 -04:00
2014-02-23 03:22:37 -05:00
let clist = []
2014-02-24 04:04:34 -05:00
for type in filetypes
call extend ( clist , s :registry .getCheckers ( type , a :checker_names ) )
2014-02-23 04:47:52 -05:00
endfor
2013-02-01 09:38:53 -05:00
2014-02-23 18:10:33 -05:00
let names = []
2014-06-02 14:25:49 -04:00
let unavailable_checkers = 0
2014-02-23 04:47:52 -05:00
for checker in clist
2014-03-10 09:50:58 -04:00
let cname = checker .getFiletype ( ) . '/' . checker .getName ( )
2014-06-02 14:25:49 -04:00
if ! checker .isAvailable ( )
2014-10-17 11:53:53 -04:00
call syntastic #log #debug ( g :_SYNTASTIC_DEBUG_TRACE , 'CacheErrors: Checker ' . cname . ' is not available' )
2014-06-02 14:25:49 -04:00
let unavailable_checkers + = 1
continue
endif
2014-10-17 11:53:53 -04:00
call syntastic #log #debug ( g :_SYNTASTIC_DEBUG_TRACE , 'CacheErrors: Invoking checker: ' . cname )
2013-04-13 11:51:23 -04:00
2014-02-23 04:47:52 -05:00
let loclist = checker .getLocList ( )
2013-01-23 19:01:30 -05:00
2014-02-23 04:47:52 -05:00
if ! loclist .isEmpty ( )
if decorate_errors
2014-03-10 09:50:58 -04:00
call loclist .decorate ( cname )
2014-02-23 04:47:52 -05:00
endif
2014-03-10 09:50:58 -04:00
call add ( names , cname )
2014-10-24 08:55:47 -04:00
if checker .wantSort ( ) && ! sort_aggregated_errors
2014-04-19 02:09:48 -04:00
call loclist .sort ( )
2014-10-17 11:53:53 -04:00
call syntastic #log #debug ( g :_SYNTASTIC_DEBUG_LOCLIST , 'sorted:' , loclist )
2014-04-19 02:09:48 -04:00
endif
2013-11-02 04:39:06 -04:00
2014-02-23 04:47:52 -05:00
let newLoclist = newLoclist .extend ( loclist )
2013-11-02 04:39:06 -04:00
2014-02-23 04:47:52 -05:00
if ! aggregate_errors
break
2013-01-23 19:01:30 -05:00
endif
2014-02-23 04:47:52 -05:00
endif
2011-12-21 18:52:58 -05:00
endfor
2013-06-15 00:36:20 -04:00
2014-02-23 04:47:52 -05:00
" set names {{{3
2013-08-05 02:25:33 -04:00
if ! empty ( names )
2014-03-10 09:50:58 -04:00
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.\\{-}/", "", "")' ) , ', ' )
2013-08-05 02:25:33 -04:00
call newLoclist .setName ( name . ' (' . type . ')' )
else
" checkers from mixed types
2014-03-10 09:50:58 -04:00
call newLoclist .setName ( join ( names , ', ' ) )
2013-08-05 02:25:33 -04:00
endif
endif
2014-02-23 04:47:52 -05:00
" }}}3
2013-08-05 02:25:33 -04:00
2014-02-23 04:47:52 -05:00
" issue warning about no active checkers {{{3
2014-06-02 14:25:49 -04:00
if len ( clist ) = = unavailable_checkers
2014-02-24 04:04:34 -05:00
if ! empty ( a :checker_names )
if len ( a :checker_names ) = = 1
call syntastic #log #warn ( 'checker ' . a :checker_names [0 ] . ' is not available' )
2013-11-29 17:56:10 -05:00
else
2014-02-24 04:04:34 -05:00
call syntastic #log #warn ( 'checkers ' . join ( a :checker_names , ', ' ) . ' are not available' )
2013-11-29 17:56:10 -05:00
endif
2013-06-15 00:36:20 -04:00
else
2014-10-17 11:53:53 -04:00
call syntastic #log #debug ( g :_SYNTASTIC_DEBUG_TRACE , 'CacheErrors: no checkers available for ' . &filetype )
2013-06-15 00:36:20 -04:00
endif
endif
2014-02-23 04:47:52 -05:00
" }}}3
2013-11-13 03:58:33 -05:00
2014-10-17 11:53:53 -04:00
call syntastic #log #debug ( g :_SYNTASTIC_DEBUG_LOCLIST , 'aggregated:' , newLoclist )
2014-04-17 15:09:12 -04:00
if sort_aggregated_errors
call newLoclist .sort ( )
2014-10-17 11:53:53 -04:00
call syntastic #log #debug ( g :_SYNTASTIC_DEBUG_LOCLIST , 'sorted:' , newLoclist )
2014-04-17 15:09:12 -04:00
endif
2009-09-20 06:45:06 -04:00
endif
2013-02-01 09:16:04 -05:00
2014-04-29 07:31:43 -04:00
call newLoclist .deploy ( )
2014-02-23 04:07:39 -05:00
endfunction " }}}2
2009-07-10 19:09:52 -04:00
2013-08-01 06:40:29 -04:00
"Emulates the :lmake command. Sets up the make environment according to the
"options given, runs make, resets the environment, returns the location list
2009-07-15 05:28:44 -04:00
"
"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.
2011-12-09 08:44:54 -05:00
"
"a:options may also contain:
" 'defaults' - a dict containing default values for the returned errors
2012-02-08 08:26:55 -05:00
" 'subtype' - all errors will be assigned the given subtype
2013-08-01 06:40:29 -04:00
" 'preprocess' - a function to be applied to the error file before parsing errors
2013-05-10 07:11:07 -04:00
" 'postprocess' - a list of functions to be applied to the error list
2013-06-11 14:36:44 -04:00
" 'cwd' - change directory to the given path before running the checker
2014-07-07 12:04:22 -04:00
" 'env' - environment variables to set before running the checker
2013-07-12 01:08:41 -04:00
" 'returns' - a list of valid exit codes for the checker
2014-07-07 12:04:22 -04:00
" @vimlint(EVL102, 1, l:env_save)
2015-02-23 09:40:53 -05:00
function ! SyntasticMake ( options ) abort " {{{2
2014-10-17 11:53:53 -04:00
call syntastic #log #debug ( g :_SYNTASTIC_DEBUG_TRACE , 'SyntasticMake: called with options:' , a :options )
2013-04-13 11:51:23 -04:00
2014-02-23 04:47:52 -05:00
" save options and locale env variables {{{3
2013-09-19 18:04:35 -04:00
let old_local_errorformat = &l :errorformat
2013-08-01 06:40:29 -04:00
let old_errorformat = &errorformat
2013-06-11 14:36:44 -04:00
let old_cwd = getcwd ( )
2014-02-23 04:47:52 -05:00
" }}}3
2009-07-15 05:28:44 -04:00
if has_key ( a :options , 'errorformat' )
2013-08-01 06:40:29 -04:00
let &errorformat = a :options ['errorformat' ]
2009-07-15 05:28:44 -04:00
endif
2013-06-11 14:36:44 -04:00
if has_key ( a :options , 'cwd' )
2013-11-01 05:51:04 -04:00
execute 'lcd ' . fnameescape ( a :options ['cwd' ])
2013-06-11 14:36:44 -04:00
endif
2014-07-07 12:04:22 -04:00
" 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_]\+$'
2015-02-19 04:43:35 -05:00
execute 'let env_save[' . string ( key ) . '] = $' . key
execute 'let $' . key . ' = ' . string ( a :options ['env' ][key ])
2014-07-07 12:04:22 -04:00
endif
endfor
endif
" }}}3
2015-03-12 13:20:06 -04:00
let err_lines = split ( syntastic #util #system ( a :options ['makeprg' ]) , "\n" , 1 )
2014-07-07 12:04:22 -04:00
" restore environment variables {{{3
if len ( env_save )
for key in keys ( env_save )
2015-02-19 04:43:35 -05:00
execute 'let $' . key . ' = ' . string ( env_save [key ])
2014-07-07 12:04:22 -04:00
endfor
endif
" }}}3
2013-08-01 06:40:29 -04:00
2014-10-17 11:53:53 -04:00
call syntastic #log #debug ( g :_SYNTASTIC_DEBUG_LOCLIST , 'checker output:' , err_lines )
2013-11-13 03:58:33 -05:00
2014-10-22 02:16:31 -04:00
" 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
2013-08-01 06:40:29 -04:00
2014-10-22 02:16:31 -04:00
let errors = deepcopy ( getloclist ( 0 ) )
2009-07-15 05:28:44 -04:00
2014-10-22 02:16:31 -04:00
if has_key ( a :options , 'cwd' )
execute 'lcd ' . fnameescape ( old_cwd )
endif
2013-06-11 14:36:44 -04:00
2014-10-22 02:16:31 -04:00
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
2014-10-24 08:55:47 -04:00
else
let errors = []
2014-10-22 02:16:31 -04:00
endif
2014-02-23 04:47:52 -05:00
" restore options {{{3
2013-08-01 06:40:29 -04:00
let &errorformat = old_errorformat
2013-09-19 18:04:35 -04:00
let &l :errorformat = old_local_errorformat
2014-02-23 04:47:52 -05:00
" }}}3
2011-02-17 15:53:53 -05:00
2015-03-25 12:44:34 -04:00
if ! s :_running_windows && ( s :_os_name ( ) = ~ ? 'FreeBSD' | | s :_os_name ( ) = ~ ? 'OpenBSD' )
2013-10-29 03:09:34 -04:00
call syntastic #util #redraw ( g :syntastic_full_redraws )
2011-09-19 16:10:53 -04:00
endif
2014-10-22 02:16:31 -04:00
if bailout
2013-07-12 01:08:41 -04:00
throw 'Syntastic: checker error'
endif
2014-10-22 02:16:31 -04:00
call syntastic #log #debug ( g :_SYNTASTIC_DEBUG_LOCLIST , 'raw loclist:' , errors )
2011-12-09 08:44:54 -05:00
if has_key ( a :options , 'defaults' )
2014-11-03 04:58:46 -05:00
call s :_add_to_errors ( errors , a :options ['defaults' ])
2011-12-09 08:44:54 -05:00
endif
2012-02-08 08:25:11 -05:00
" Add subtype info if present.
if has_key ( a :options , 'subtype' )
2014-11-03 04:58:46 -05:00
call s :_add_to_errors ( errors , { 'subtype' : a :options ['subtype' ] })
2012-02-08 08:25:11 -05:00
endif
2014-03-04 10:18:59 -05:00
if has_key ( a :options , 'Postprocess' ) && ! empty ( a :options ['Postprocess' ])
for rule in a :options ['Postprocess' ]
let errors = call ( rule , [errors ])
endfor
2014-10-17 11:53:53 -04:00
call syntastic #log #debug ( g :_SYNTASTIC_DEBUG_LOCLIST , 'postprocess (external):' , errors )
2014-03-04 10:18:59 -05:00
elseif has_key ( a :options , 'postprocess' ) && ! empty ( a :options ['postprocess' ])
2013-05-10 07:11:07 -04:00
for rule in a :options ['postprocess' ]
let errors = call ( 'syntastic#postprocess#' . rule , [errors ])
endfor
2014-10-17 11:53:53 -04:00
call syntastic #log #debug ( g :_SYNTASTIC_DEBUG_LOCLIST , 'postprocess:' , errors )
2013-05-10 07:11:07 -04:00
endif
2009-07-15 05:28:44 -04:00
return errors
2014-02-23 04:07:39 -05:00
endfunction " }}}2
2014-07-07 12:04:22 -04:00
" @vimlint(EVL102, 0, l:env_save)
2014-02-23 04:07:39 -05:00
"return a string representing the state of buffer according to
"g:syntastic_stl_format
"
"return '' if no errors are cached for the buffer
2015-02-23 09:40:53 -05:00
function ! SyntasticStatuslineFlag ( ) abort " {{{2
2014-02-23 04:07:39 -05:00
return g :SyntasticLoclist .current ( ) .getStatuslineFlag ( )
endfunction " }}}2
" }}}1
" Utilities {{{1
2015-02-23 09:40:53 -05:00
function ! s :_resolve_filetypes ( filetypes ) abort " {{{2
2014-11-03 13:12:21 -05:00
let type = len ( a :filetypes ) ? a :filetypes [0 ] : &filetype
2014-02-23 04:07:39 -05:00
return split ( get ( g :syntastic_filetype_map , type , type ) , '\m\.' )
endfunction " }}}2
2015-02-23 09:40:53 -05:00
function ! s :_ignore_file ( filename ) abort " {{{2
2014-02-23 04:07:39 -05:00
let fname = fnamemodify ( a :filename , ':p' )
for pattern in g :syntastic_ignore_files
if fname = ~ # pattern
return 1
endif
endfor
return 0
endfunction " }}}2
" Skip running in special buffers
2015-02-23 09:40:53 -05:00
function ! s :_skip_file ( ) abort " {{{2
2015-01-04 02:01:55 -05:00
let fname = expand ( '%' , 1 )
2015-03-25 12:44:34 -04:00
let skip = get ( b :, 'syntastic_skip_checks' , 0 ) | | ( &buftype ! = # '' ) | |
2014-11-03 04:58:46 -05:00
\ ! filereadable ( fname ) | | getwinvar ( 0 , '&diff' ) | | s :_ignore_file ( fname ) | |
2014-09-15 23:36:37 -04:00
\ fnamemodify ( fname , ':e' ) = ~ ? g :syntastic_ignore_extensions
2014-07-22 00:55:04 -04:00
if skip
2014-11-03 04:58:46 -05:00
call syntastic #log #debug ( g :_SYNTASTIC_DEBUG_TRACE , '_skip_file: skipping checks' )
2014-07-22 00:55:04 -04:00
endif
2014-07-22 13:37:06 -04:00
return skip
2014-02-23 04:07:39 -05:00
endfunction " }}}2
2009-07-15 05:28:44 -04:00
2014-10-16 02:56:29 -04:00
" Explain why checks will be skipped for the current file
2015-02-23 09:40:53 -05:00
function ! s :_explain_skip ( filetypes ) abort " {{{2
2014-11-03 13:12:21 -05:00
if empty ( a :filetypes ) && s :_skip_file ( )
2014-10-16 02:56:29 -04:00
let why = []
2015-01-04 02:01:55 -05:00
let fname = expand ( '%' , 1 )
2014-10-16 02:56:29 -04:00
if get ( b :, 'syntastic_skip_checks' , 0 )
call add ( why , 'b:syntastic_skip_checks set' )
endif
2015-03-25 12:44:34 -04:00
if &buftype ! = # ''
2014-10-16 02:56:29 -04:00
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
2014-11-03 04:58:46 -05:00
if s :_ignore_file ( fname )
2014-10-16 02:56:29 -04:00
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
2014-02-23 03:22:37 -05:00
" Take a list of errors and add default values to them from a:options
2015-02-23 09:40:53 -05:00
function ! s :_add_to_errors ( errors , options ) abort " {{{2
2014-02-01 11:44:04 -05:00
for err in a :errors
2011-12-09 08:44:54 -05:00
for key in keys ( a :options )
2014-02-01 11:44:04 -05:00
if ! has_key ( err , key ) | | empty ( err [key ])
let err [key ] = a :options [key ]
2011-12-09 08:44:54 -05:00
endif
endfor
endfor
2014-02-01 11:44:04 -05:00
2011-12-09 08:44:54 -05:00
return a :errors
2014-02-23 04:07:39 -05:00
endfunction " }}}2
2011-12-09 08:44:54 -05:00
2015-02-23 09:40:53 -05:00
function ! s :_os_name ( ) abort " {{{2
2015-02-12 07:04:35 -05:00
return g :_SYNTASTIC_UNAME
2014-02-23 04:07:39 -05:00
endfunction " }}}2
" }}}1
2014-02-23 03:22:37 -05:00
" vim: set sw=4 sts=4 et fdm=marker: