From e291f9f06d4c73119896a3da5cb0b3038b4f4d08 Mon Sep 17 00:00:00 2001 From: LCD 47 Date: Sat, 22 Jun 2013 08:03:03 +0300 Subject: [PATCH 1/2] Bug fix: add enabled/disabled guards to notifiers. Also handle the case when user disables notifiers after the first run. This doesn't work for signs though, since it causes an ugly flicker in the common case. --- plugin/syntastic/balloons.vim | 10 +++-- plugin/syntastic/cursor.vim | 7 +++- plugin/syntastic/highlighting.vim | 62 ++++++++++++++++--------------- plugin/syntastic/notifiers.vim | 6 ++- plugin/syntastic/signs.vim | 23 ++++++------ 5 files changed, 62 insertions(+), 46 deletions(-) diff --git a/plugin/syntastic/balloons.vim b/plugin/syntastic/balloons.vim index c98cb170..f6e60418 100644 --- a/plugin/syntastic/balloons.vim +++ b/plugin/syntastic/balloons.vim @@ -21,13 +21,15 @@ function! g:SyntasticBalloonsNotifier.New() endfunction function! g:SyntasticBalloonsNotifier.enabled() - return exists('b:syntastic_enable_balloons') ? b:syntastic_enable_balloons : g:syntastic_enable_balloons + return + \ has('balloon_eval') && + \ (exists('b:syntastic_enable_balloons') ? b:syntastic_enable_balloons : g:syntastic_enable_balloons) endfunction " Update the error balloons function! g:SyntasticBalloonsNotifier.refresh(loclist) let b:syntastic_balloons = {} - if a:loclist.hasErrorsOrWarningsToDisplay() + if self.enabled() && a:loclist.hasErrorsOrWarningsToDisplay() let buf = bufnr('') let issues = filter(a:loclist.filteredRaw(), 'v:val["bufnr"] == buf') if !empty(issues) @@ -45,7 +47,9 @@ endfunction " Reset the error balloons function! g:SyntasticBalloonsNotifier.reset(loclist) - set nobeval + if has('balloon_eval') + set nobeval + endif endfunction " Private functions {{{1 diff --git a/plugin/syntastic/cursor.vim b/plugin/syntastic/cursor.vim index 03024008..77f97dc5 100644 --- a/plugin/syntastic/cursor.vim +++ b/plugin/syntastic/cursor.vim @@ -16,9 +16,12 @@ function! g:SyntasticCursorNotifier.New() return newObj endfunction +function! g:SyntasticCursorNotifier.enabled() + return exists('b:syntastic_echo_current_error') ? b:syntastic_echo_current_error : g:syntastic_echo_current_error +endfunction + function! g:SyntasticCursorNotifier.refresh(loclist) - let enabled = exists('b:syntastic_echo_current_error') ? b:syntastic_echo_current_error : g:syntastic_echo_current_error - if enabled && a:loclist.hasErrorsOrWarningsToDisplay() + if self.enabled() && a:loclist.hasErrorsOrWarningsToDisplay() let b:syntastic_messages = copy(a:loclist.messages(bufnr(''))) let b:oldLine = -1 autocmd! syntastic CursorMoved diff --git a/plugin/syntastic/highlighting.vim b/plugin/syntastic/highlighting.vim index 48bd4bb5..e04e6cc5 100644 --- a/plugin/syntastic/highlighting.vim +++ b/plugin/syntastic/highlighting.vim @@ -3,15 +3,13 @@ if exists("g:loaded_syntastic_notifier_highlighting") endif let g:loaded_syntastic_notifier_highlighting = 1 +" Highlighting requires getmatches introduced in 7.1.040 +let s:has_highlighting = v:version > 701 || (v:version == 701 && has('patch040')) + if !exists("g:syntastic_enable_highlighting") let g:syntastic_enable_highlighting = 1 endif -" Highlighting requires getmatches introduced in 7.1.040 -if v:version < 701 || (v:version == 701 && !has('patch040')) - let g:syntastic_enable_highlighting = 0 -endif - let g:SyntasticHighlightingNotifier = {} " Public methods {{{1 @@ -22,41 +20,47 @@ function! g:SyntasticHighlightingNotifier.New() endfunction function! g:SyntasticHighlightingNotifier.enabled() - return exists('b:syntastic_enable_highlighting') ? b:syntastic_enable_highlighting : g:syntastic_enable_highlighting + return + \ s:has_highlighting && + \ (exists('b:syntastic_enable_highlighting') ? b:syntastic_enable_highlighting : g:syntastic_enable_highlighting) endfunction " Sets error highlights in the cuirrent window function! g:SyntasticHighlightingNotifier.refresh(loclist) - call self.reset(a:loclist) - let buf = bufnr('') - let issues = filter(a:loclist.filteredRaw(), 'v:val["bufnr"] == buf') - for item in issues - let group = item['type'] == 'E' ? 'SyntasticError' : 'SyntasticWarning' + if self.enabled() + call self.reset(a:loclist) + let buf = bufnr('') + let issues = filter(a:loclist.filteredRaw(), 'v:val["bufnr"] == buf') + for item in issues + let group = item['type'] == 'E' ? 'SyntasticError' : 'SyntasticWarning' - " The function `Syntastic_{filetype}_{checker}_GetHighlightRegex` is - " used to override default highlighting. - if has_key(item, 'hl') - call matchadd(group, '\%' . item['lnum'] . 'l' . item['hl']) - elseif get(item, 'col') - let lastcol = col([item['lnum'], '$']) - let lcol = min([lastcol, item['col']]) + " The function `Syntastic_{filetype}_{checker}_GetHighlightRegex` is + " used to override default highlighting. + if has_key(item, 'hl') + call matchadd(group, '\%' . item['lnum'] . 'l' . item['hl']) + elseif get(item, 'col') + let lastcol = col([item['lnum'], '$']) + let lcol = min([lastcol, item['col']]) - " a bug in vim can sometimes cause there to be no 'vcol' key, - " so check for its existence - let coltype = has_key(item, 'vcol') && item['vcol'] ? 'v' : 'c' + " a bug in vim can sometimes cause there to be no 'vcol' key, + " so check for its existence + let coltype = has_key(item, 'vcol') && item['vcol'] ? 'v' : 'c' - call matchadd(group, '\%' . item['lnum'] . 'l\%' . lcol . coltype) - endif - endfor + call matchadd(group, '\%' . item['lnum'] . 'l\%' . lcol . coltype) + endif + endfor + endif endfunction " Remove all error highlights from the window function! g:SyntasticHighlightingNotifier.reset(loclist) - for match in getmatches() - if stridx(match['group'], 'Syntastic') == 0 - call matchdelete(match['id']) - endif - endfor + if s:has_highlighting + for match in getmatches() + if stridx(match['group'], 'Syntastic') == 0 + call matchdelete(match['id']) + endif + endfor + endif endfunction " vim: set sw=4 sts=4 et fdm=marker: diff --git a/plugin/syntastic/notifiers.vim b/plugin/syntastic/notifiers.vim index 1a7766aa..12f41445 100644 --- a/plugin/syntastic/notifiers.vim +++ b/plugin/syntastic/notifiers.vim @@ -30,7 +30,11 @@ endfunction function! g:SyntasticNotifiers.reset(loclist) for type in self._enabled_types let class = substitute(type, '.*', 'Syntastic\u&Notifier', '') - if has_key(g:{class}, 'reset') && (!has_key(g:{class}, 'enabled') || self._notifier[type].enabled()) + + " reset notifiers regardless if they are enabled or not, since + " the user might have disabled them since the last refresh(); + " notifiers MUST be prepared to deal with reset() when disabled + if has_key(g:{class}, 'reset') call self._notifier[type].reset(a:loclist) endif endfor diff --git a/plugin/syntastic/signs.vim b/plugin/syntastic/signs.vim index ab3a3f36..9877269d 100644 --- a/plugin/syntastic/signs.vim +++ b/plugin/syntastic/signs.vim @@ -23,10 +23,6 @@ if !exists("g:syntastic_style_warning_symbol") let g:syntastic_style_warning_symbol = 'S>' endif -if !has('signs') - let g:syntastic_enable_signs = 0 -endif - " start counting sign ids at 5000, start here to hopefully avoid conflicting " with any other code that places signs (not sure if this precaution is @@ -52,13 +48,16 @@ function! g:SyntasticSignsNotifier.New() endfunction function! g:SyntasticSignsNotifier.enabled() - return exists('b:syntastic_enable_signs') ? b:syntastic_enable_signs : g:syntastic_enable_signs + return + \ has('signs') && + \ exists('b:syntastic_enable_signs') ? b:syntastic_enable_signs : g:syntastic_enable_signs endfunction -" Update the error signs function! g:SyntasticSignsNotifier.refresh(loclist) let old_signs = copy(self._bufSignIds()) - call self._signErrors(a:loclist) + if self.enabled() + call self._signErrors(a:loclist) + endif call self._removeSigns(old_signs) let s:first_sign_id = s:next_sign_id endfunction @@ -125,10 +124,12 @@ endfunction " Remove the signs with the given ids from this buffer function! g:SyntasticSignsNotifier._removeSigns(ids) - for i in a:ids - exec "sign unplace " . i - call remove(self._bufSignIds(), index(self._bufSignIds(), i)) - endfor + if has('signs') + for i in a:ids + exec "sign unplace " . i + call remove(self._bufSignIds(), index(self._bufSignIds(), i)) + endfor + endif endfunction " Get all the ids of the SyntaxError signs in the buffer From 9dfc53c9c74218a9760d64be1a52e2c6d82ce535 Mon Sep 17 00:00:00 2001 From: LCD 47 Date: Sat, 22 Jun 2013 20:01:22 +0300 Subject: [PATCH 2/2] Optimisation: avoid placing duplicate signs. --- plugin/syntastic/signs.vim | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/plugin/syntastic/signs.vim b/plugin/syntastic/signs.vim index 9877269d..067658b1 100644 --- a/plugin/syntastic/signs.vim +++ b/plugin/syntastic/signs.vim @@ -103,21 +103,27 @@ function! g:SyntasticSignsNotifier._signErrors(loclist) let loclist = a:loclist if loclist.hasErrorsOrWarningsToDisplay() - " make sure the errors come after the warnings, so that errors mask - " the warnings on the same line, not the other way around + " errors some first, so that they are not masked by warnings let buf = bufnr('') - let issues = loclist.quietWarnings() ? [] : loclist.warnings() - call extend(issues, loclist.errors()) + let issues = copy(loclist.errors()) + if !loclist.quietWarnings() + call extend(issues, loclist.warnings()) + endif call filter(issues, 'v:val["bufnr"] == buf') + let seen = {} for i in issues - let sign_severity = i['type'] ==? 'W' ? 'Warning' : 'Error' - let sign_subtype = get(i, 'subtype', '') - let sign_type = 'Syntastic' . sign_subtype . sign_severity + if !has_key(seen, i['lnum']) + let seen[i['lnum']] = 1 - exec "sign place " . s:next_sign_id . " line=" . i['lnum'] . " name=" . sign_type . " buffer=" . i['bufnr'] - call add(self._bufSignIds(), s:next_sign_id) - let s:next_sign_id += 1 + let sign_severity = i['type'] ==? 'W' ? 'Warning' : 'Error' + let sign_subtype = get(i, 'subtype', '') + let sign_type = 'Syntastic' . sign_subtype . sign_severity + + exec "sign place " . s:next_sign_id . " line=" . i['lnum'] . " name=" . sign_type . " buffer=" . i['bufnr'] + call add(self._bufSignIds(), s:next_sign_id) + let s:next_sign_id += 1 + endif endfor endif endfunction