Better triggering of semantic completion

Now there's a nice user-configurable setting for when YCM should trigger
semantic completion. This is very useful for the new omni_completer that uses
data coming from Vim's omnicomplete system.
This commit is contained in:
Strahinja Val Markovic 2013-02-11 21:46:06 -08:00
parent 5d89aef907
commit 452f7d1fec
4 changed files with 49 additions and 36 deletions

View File

@ -95,6 +95,14 @@ let g:ycm_key_detailed_diagnostics =
let g:ycm_global_ycm_extra_conf = let g:ycm_global_ycm_extra_conf =
\ get( g:, 'ycm_global_ycm_extra_conf', '' ) \ get( g:, 'ycm_global_ycm_extra_conf', '' )
let g:ycm_semantic_triggers =
\ get( g:, 'ycm_semantic_triggers', {
\ 'c,cpp,objc,objcpp' : ['->', '.', '::'],
\ 'perl,php' : ['->'],
\ 'cs,java,javascript,d,vim,ruby,python,perl6,scala,vb' : ['.'],
\ 'lua' : ['.', ':'],
\ } )
" On-demand loading. Let's use the autoload folder and not slow down vim's " On-demand loading. Let's use the autoload folder and not slow down vim's
" startup procedure. " startup procedure.
augroup youcompletemeStart augroup youcompletemeStart

View File

@ -32,19 +32,6 @@ class OmniCompleter( Completer ):
return [] return []
def ShouldUseNowInner( self, start_column ):
line = vim.current.line
previous_char_index = start_column - 1
if ( not len( line ) or
previous_char_index < 0 or
previous_char_index >= len( line ) ):
return False
if line[ previous_char_index ] == '.':
return True
return False
def CandidatesForQueryAsyncInner( self, query ): def CandidatesForQueryAsyncInner( self, query ):
if not self.omnifunc: if not self.omnifunc:
self.stored_candidates = None self.stored_candidates = None

View File

@ -21,6 +21,7 @@ import abc
import vim import vim
import vimsupport import vimsupport
import ycm_core import ycm_core
from collections import defaultdict
class CompletionsCache( object ): class CompletionsCache( object ):
@ -42,19 +43,43 @@ class Completer( object ):
def __init__( self ): def __init__( self ):
self.triggers_for_filetype = TriggersForFiletype()
self.completions_future = None self.completions_future = None
self.completions_cache = None self.completions_cache = None
def ShouldUseNow( self, start_column ): def ShouldUseNow( self, start_column ):
inner_says_yes = self.ShouldUseNowInner( start_column ) inner_says_yes = self.ShouldUseNowInner( start_column )
if not inner_says_yes:
self.completions_cache = None
previous_results_were_empty = ( self.completions_cache and previous_results_were_empty = ( self.completions_cache and
self.completions_cache.CacheValid() and
not self.completions_cache.raw_completions ) not self.completions_cache.raw_completions )
return inner_says_yes and not previous_results_were_empty return inner_says_yes and not previous_results_were_empty
def ShouldUseNowInner( self, start_column ): def ShouldUseNowInner( self, start_column ):
pass line = vim.current.line
line_length = len( line )
if not line_length or start_column - 1 >= line_length:
return False
filetype = vimsupport.CurrentFiletypes()[ 0 ]
triggers = self.triggers_for_filetype[ filetype ]
for trigger in triggers:
index = -1
trigger_length = len( trigger )
while True:
line_index = start_column + index
if line_index < 0 or line[ line_index ] != trigger[ index ]:
break
if abs( index ) == trigger_length:
return True
index -= 1
return False
def CandidatesForQueryAsync( self, query ): def CandidatesForQueryAsync( self, query ):
@ -169,3 +194,16 @@ class Completer( object ):
def DebugInfo( self ): def DebugInfo( self ):
return '' return ''
def TriggersForFiletype():
triggers = vim.eval( 'g:ycm_semantic_triggers' )
triggers_for_filetype = defaultdict( list )
for key, value in triggers.iteritems():
filetypes = key.split( ',' )
for filetype in filetypes:
triggers_for_filetype[ filetype ].extend( value )
return triggers_for_filetype

View File

@ -199,7 +199,8 @@ class ClangCompleter( Completer ):
def ShouldUseNow( self, start_column ): def ShouldUseNow( self, start_column ):
return ShouldUseClang( start_column ) # We don't want to use the Completer API cache, we use one in the C++ code.
return self.ShouldUseNowInner( start_column )
def DebugInfo( self ): def DebugInfo( self ):
@ -246,24 +247,3 @@ def DiagnosticsToDiagStructure( diagnostics ):
def ClangAvailableForBuffer( buffer_object ): def ClangAvailableForBuffer( buffer_object ):
filetype = vim.eval( 'getbufvar({0}, "&ft")'.format( buffer_object.number ) ) filetype = vim.eval( 'getbufvar({0}, "&ft")'.format( buffer_object.number ) )
return filetype in CLANG_FILETYPES return filetype in CLANG_FILETYPES
def ShouldUseClang( start_column ):
line = vim.current.line
previous_char_index = start_column - 1
if ( not len( line ) or
previous_char_index < 0 or
previous_char_index >= len( line ) ):
return False
if line[ previous_char_index ] == '.':
return True
if previous_char_index - 1 < 0:
return False
two_previous_chars = line[ previous_char_index - 1 : start_column ]
if ( two_previous_chars == '->' or two_previous_chars == '::' ):
return True
return False