diff --git a/autoload/youcompleteme.vim b/autoload/youcompleteme.vim index 8db48339..508dcddd 100644 --- a/autoload/youcompleteme.vim +++ b/autoload/youcompleteme.vim @@ -365,6 +365,7 @@ function! s:OnCursorMovedInsertMode() return endif + py ycm_state.OnCursorMoved() call s:UpdateCursorMoved() " Basically, we need to only trigger the completion menu when the user has @@ -402,6 +403,7 @@ function! s:OnCursorMovedNormalMode() endif call s:OnFileReadyToParse() + py ycm_state.OnCursorMoved() endfunction diff --git a/python/ycm/diagnostic_interface.py b/python/ycm/diagnostic_interface.py index 9c9c239b..654dd36a 100644 --- a/python/ycm/diagnostic_interface.py +++ b/python/ycm/diagnostic_interface.py @@ -20,36 +20,66 @@ from collections import defaultdict from operator import itemgetter from ycm import vimsupport +import vim class DiagnosticInterface( object ): def __init__( self ): - self._buffer_number_to_diags = {} + # Line and column numbers are 1-based + self._buffer_number_to_line_to_diags = defaultdict( + lambda: defaultdict( list ) ) self._next_sign_id = 1 + self._previous_line_number = -1 + + + def OnCursorMoved( self ): + line, _ = vimsupport.CurrentLineAndColumn() + line += 1 # Convert to 1-based + if line != self._previous_line_number: + self._previous_line_number = line + self._EchoDiagnosticForLine( line ) def UpdateWithNewDiagnostics( self, diags ): - self._buffer_number_to_diags = ConvertDiagListToDict( diags ) - for buffer_number, buffer_diags in self._buffer_number_to_diags.iteritems(): - if not vimsupport.BufferIsVisible( buffer_number ): - continue + self._buffer_number_to_line_to_diags = _ConvertDiagListToDict( diags ) + self._next_sign_id = _UpdateSigns( self._buffer_number_to_line_to_diags, + self._next_sign_id ) - vimsupport.UnplaceAllSignsInBuffer( buffer_number ) - for diag in buffer_diags: - vimsupport.PlaceSign( self._next_sign_id, - diag[ 'lnum' ], + + def _EchoDiagnosticForLine( self, line_num ): + buffer_num = vim.current.buffer.number + diags = self._buffer_number_to_line_to_diags[ buffer_num ][ line_num ] + if not diags: + # Clear any previous diag echo + vimsupport.EchoText( '', False ) + return + vimsupport.EchoTextVimWidth( diags[ 0 ][ 'text' ] ) + + +def _UpdateSigns( buffer_number_to_line_to_diags, next_sign_id ): + for buffer_number, line_to_diags in buffer_number_to_line_to_diags.iteritems(): + if not vimsupport.BufferIsVisible( buffer_number ): + continue + + vimsupport.UnplaceAllSignsInBuffer( buffer_number ) + for line, diags in line_to_diags.iteritems(): + for diag in diags: + vimsupport.PlaceSign( next_sign_id, + line, buffer_number, diag[ 'type' ] == 'E' ) - self._next_sign_id += 1 + next_sign_id += 1 + return next_sign_id -def ConvertDiagListToDict( diags ): - buffer_to_diags = defaultdict( list ) - for diag in diags: - buffer_to_diags[ diag[ 'bufnr' ] ].append( diag ) - for buffer_diags in buffer_to_diags.itervalues(): - # We also want errors to be listed before warnings so that errors aren't - # hidden by the warnings; Vim won't place a sign oven an existing one. - buffer_diags.sort( key = lambda diag: itemgetter( 'lnum', 'col', 'type' ) ) - return buffer_to_diags +def _ConvertDiagListToDict( diag_list ): + buffer_to_line_to_diags = defaultdict( lambda: defaultdict( list ) ) + for diag in diag_list: + buffer_to_line_to_diags[ diag[ 'bufnr' ] ][ diag[ 'lnum' ] ].append( diag ) + for line_to_diags in buffer_to_line_to_diags.itervalues(): + for diags in line_to_diags.itervalues(): + # We also want errors to be listed before warnings so that errors aren't + # hidden by the warnings; Vim won't place a sign oven an existing one. + diags.sort( key = lambda diag: itemgetter( 'col', 'type' ) ) + return buffer_to_line_to_diags diff --git a/python/ycm/vimsupport.py b/python/ycm/vimsupport.py index 95013f66..9ac07d8a 100644 --- a/python/ycm/vimsupport.py +++ b/python/ycm/vimsupport.py @@ -220,14 +220,23 @@ def Confirm( message ): return bool( PresentDialog( message, [ "Ok", "Cancel" ] ) == 0 ) -def EchoText( text ): +def EchoText( text, log_as_message = True ): def EchoLine( text ): - vim.command( "echom '{0}'".format( EscapeForVim( text ) ) ) + command = 'echom' if log_as_message else 'echo' + vim.command( "{0} '{1}'".format( command, EscapeForVim( text ) ) ) for line in text.split( '\n' ): EchoLine( line ) +# Echos text but truncates the text so that it all fits on one line +def EchoTextVimWidth( text ): + vim_width = GetIntValue( '&columns' ) + truncated_text = text[ : int( vim_width * 0.9 ) ] + truncated_text.replace( '\n', ' ' ) + EchoText( truncated_text, False ) + + def EscapeForVim( text ): return text.replace( "'", "''" ) diff --git a/python/ycm/youcompleteme.py b/python/ycm/youcompleteme.py index 0877fc03..78b4a973 100644 --- a/python/ycm/youcompleteme.py +++ b/python/ycm/youcompleteme.py @@ -246,6 +246,10 @@ class YouCompleteMe( object ): SendEventNotificationAsync( 'InsertLeave' ) + def OnCursorMoved( self ): + self._diag_interface.OnCursorMoved() + + def OnVimLeave( self ): self._ServerCleanup()