Now more explicit about accessing user options

We don't inspect the Vim process anymore when we want an option; we parse the
options on startup and then use that data structure.
This commit is contained in:
Strahinja Val Markovic 2013-09-02 14:45:53 -07:00
parent 496fe8f7a3
commit a26243092f
23 changed files with 163 additions and 101 deletions

View File

@ -37,12 +37,16 @@ function! youcompleteme#Enable()
return
endif
call s:SetUpBackwardsCompatibility()
py import sys
py import vim
exe 'python sys.path.insert( 0, "' . s:script_folder_path . '/../python" )'
py from ycm import base
py from ycm import user_options_store
py user_options_store.SetAll( base.BuildServerConf() )
py from ycm import extra_conf_store
py extra_conf_store.CallExtraConfYcmCorePreloadIfExists()
py from ycm import base
if !pyeval( 'base.CompatibleWithYcmCore()')
echohl WarningMsg |
@ -51,10 +55,12 @@ function! youcompleteme#Enable()
return
endif
py from ycm.youcompleteme import YouCompleteMe
py ycm_state = YouCompleteMe( user_options_store.GetAll() )
call s:SetUpCpoptions()
call s:SetUpCompleteopt()
call s:SetUpKeyMappings()
call s:SetUpBackwardsCompatibility()
if g:ycm_register_as_syntastic_checker
call s:ForceSyntasticCFamilyChecker()
@ -64,9 +70,6 @@ function! youcompleteme#Enable()
set ut=2000
endif
py from ycm.youcompleteme import YouCompleteMe
py ycm_state = YouCompleteMe()
augroup youcompleteme
autocmd!
autocmd CursorMovedI * call s:OnCursorMovedInsertMode()

View File

@ -23,6 +23,8 @@ import vim
from ycm import vimsupport
from ycm import utils
YCM_VAR_PREFIX = 'ycm_'
try:
import ycm_core
except ImportError as e:
@ -34,6 +36,30 @@ except ImportError as e:
str( e ) ) )
def BuildServerConf():
"""Builds a dictionary mapping YCM Vim user options to values. Option names
don't have the 'ycm_' prefix."""
try:
# vim.vars is fairly new so it might not exist
vim_globals = vim.vars
except:
vim_globals = vim.eval( 'g:' )
server_conf = {}
for key, value in vim_globals.items():
if not key.startswith( YCM_VAR_PREFIX ):
continue
try:
new_value = int( value )
except:
new_value = value
new_key = key[ len( YCM_VAR_PREFIX ): ]
server_conf[ new_key ] = new_value
return server_conf
def CompletionStartColumn():
"""Returns the 0-based index where the completion string should start. So if
the user enters:

View File

@ -27,16 +27,12 @@ from ycm import vimsupport
from ycm import utils
MAX_IDENTIFIER_COMPLETIONS_RETURNED = 10
MIN_NUM_COMPLETION_START_CHARS = int( vimsupport.GetVariableValue(
"g:ycm_min_num_of_chars_for_completion" ) )
MIN_NUM_CANDIDATE_SIZE_CHARS = int( vimsupport.GetVariableValue(
"g:ycm_min_num_identifier_candidate_chars" ) )
SYNTAX_FILENAME = 'YCM_PLACEHOLDER_FOR_SYNTAX'
class IdentifierCompleter( GeneralCompleter ):
def __init__( self ):
super( IdentifierCompleter, self ).__init__()
def __init__( self, user_options ):
super( IdentifierCompleter, self ).__init__( user_options )
self.completer = ycm_core.IdentifierCompleter()
self.completer.EnableThreading()
self.tags_file_last_mtime = defaultdict( int )
@ -69,7 +65,8 @@ class IdentifierCompleter( GeneralCompleter ):
def AddPreviousIdentifier( self ):
self.AddIdentifier( PreviousIdentifier() )
self.AddIdentifier( _PreviousIdentifier( self.user_options[
'min_num_of_chars_for_completion' ] ) )
def AddIdentifierUnderCursor( self ):
@ -90,8 +87,8 @@ class IdentifierCompleter( GeneralCompleter ):
# TODO: use vimsupport.GetFiletypes; also elsewhere in file
filetype = vim.eval( "&filetype" )
filepath = vim.eval( "expand('%:p')" )
collect_from_comments_and_strings = vimsupport.GetBoolValue(
"g:ycm_collect_identifiers_from_comments_and_strings" )
collect_from_comments_and_strings = bool( self.user_options[
'collect_identifiers_from_comments_and_strings' ] )
if not filetype or not filepath:
return
@ -153,10 +150,10 @@ class IdentifierCompleter( GeneralCompleter ):
def OnFileReadyToParse( self ):
self.AddBufferIdentifiers()
if vimsupport.GetBoolValue( 'g:ycm_collect_identifiers_from_tags_files' ):
if self.user_options[ 'collect_identifiers_from_tags_files' ]:
self.AddIdentifiersFromTagFiles()
if vimsupport.GetBoolValue( 'g:ycm_seed_identifiers_with_syntax' ):
if self.user_options[ 'seed_identifiers_with_syntax' ]:
self.AddIdentifiersFromSyntax()
@ -174,7 +171,8 @@ class IdentifierCompleter( GeneralCompleter ):
completions = self.completions_future.GetResults()[
: MAX_IDENTIFIER_COMPLETIONS_RETURNED ]
completions = _RemoveSmallCandidates( completions )
completions = _RemoveSmallCandidates(
completions, self.user_options[ 'min_num_identifier_candidate_chars' ] )
# We will never have duplicates in completions so with 'dup':1 we tell Vim
# to add this candidate even if it's a duplicate of an existing one (which
@ -183,7 +181,7 @@ class IdentifierCompleter( GeneralCompleter ):
return [ { 'word': x, 'dup': 1 } for x in completions ]
def PreviousIdentifier():
def _PreviousIdentifier( min_num_completion_start_chars ):
line_num, column_num = vimsupport.CurrentLineAndColumn()
buffer = vim.current.buffer
line = buffer[ line_num ]
@ -208,15 +206,15 @@ def PreviousIdentifier():
while start_column > 0 and utils.IsIdentifierChar( line[ start_column - 1 ] ):
start_column -= 1
if end_column - start_column < MIN_NUM_COMPLETION_START_CHARS:
if end_column - start_column < min_num_completion_start_chars:
return ""
return line[ start_column : end_column ]
def _RemoveSmallCandidates( candidates ):
if MIN_NUM_CANDIDATE_SIZE_CHARS == 0:
def _RemoveSmallCandidates( candidates, min_num_candidate_size_chars ):
if min_num_candidate_size_chars == 0:
return candidates
return [ x for x in candidates if len( x ) >= MIN_NUM_CANDIDATE_SIZE_CHARS ]
return [ x for x in candidates if len( x ) >= min_num_candidate_size_chars ]

View File

@ -26,8 +26,8 @@ OMNIFUNC_NOT_LIST = ( 'Omnifunc did not return a list or a dict with a "words" '
' list when expected.' )
class OmniCompleter( Completer ):
def __init__( self ):
super( OmniCompleter, self ).__init__()
def __init__( self, user_options ):
super( OmniCompleter, self ).__init__( user_options )
self.omnifunc = None
self.stored_candidates = None
@ -37,7 +37,7 @@ class OmniCompleter( Completer ):
def ShouldUseCache( self ):
return vimsupport.GetBoolValue( "g:ycm_cache_omnifunc" )
return bool( self.user_options[ 'cache_omnifunc' ] )
def ShouldUseNow( self, start_column, current_line ):

View File

@ -20,9 +20,9 @@
import ycm_core
from ycm.completers.cpp.clang_completer import ClangCompleter
def GetCompleter():
def GetCompleter( user_options ):
if ycm_core.HasClangSupport():
return ClangCompleter()
return ClangCompleter( user_options )
else:
return None

View File

@ -24,9 +24,6 @@ from ycm.completers.completer_utils import TriggersForFiletype
NO_USER_COMMANDS = 'This completer does not define any commands.'
MIN_NUM_CHARS = int( vimsupport.GetVariableValue(
"g:ycm_min_num_of_chars_for_completion" ) )
class Completer( object ):
"""A base class for all Completers in YCM.
@ -116,7 +113,9 @@ class Completer( object ):
__metaclass__ = abc.ABCMeta
def __init__( self ):
def __init__( self, user_options ):
self.user_options = user_options
self.min_num_chars = user_options[ 'min_num_of_chars_for_completion' ]
self.triggers_for_filetype = TriggersForFiletype()
self.completions_future = None
self.completions_cache = None
@ -161,7 +160,7 @@ class Completer( object ):
def QueryLengthAboveMinThreshold( self, start_column ):
query_length = vimsupport.CurrentColumn() - start_column
return query_length >= MIN_NUM_CHARS
return query_length >= self.min_num_chars
# It's highly likely you DON'T want to override this function but the *Inner

View File

@ -26,13 +26,13 @@ from ycm.completers.completer import Completer
from ycm.completers.cpp.flags import Flags
CLANG_FILETYPES = set( [ 'c', 'cpp', 'objc', 'objcpp' ] )
MAX_DIAGNOSTICS_TO_DISPLAY = int( vimsupport.GetVariableValue(
"g:ycm_max_diagnostics_to_display" ) )
class ClangCompleter( Completer ):
def __init__( self ):
super( ClangCompleter, self ).__init__()
def __init__( self, user_options ):
super( ClangCompleter, self ).__init__( user_options )
self.max_diagnostics_to_display = user_options[
'max_diagnostics_to_display' ]
self.completer = ycm_core.ClangCompleter()
self.completer.EnableThreading()
self.contents_holder = []
@ -262,7 +262,7 @@ class ClangCompleter( Completer ):
diagnostics = self.completer.DiagnosticsForFile( vim.current.buffer.name )
self.diagnostic_store = DiagnosticsToDiagStructure( diagnostics )
self.last_prepared_diagnostics = [ DiagnosticToDict( x ) for x in
diagnostics[ : MAX_DIAGNOSTICS_TO_DISPLAY ] ]
diagnostics[ : self.max_diagnostics_to_display ] ]
self.parse_future = None
if self.extra_parse_desired:

View File

@ -20,9 +20,9 @@
import ycm_core
from ycm.completers.cpp.clang_completer import ClangCompleter
def GetCompleter():
def GetCompleter( user_options ):
if ycm_core.HasClangSupport():
return ClangCompleter()
return ClangCompleter( user_options )
else:
return None

View File

@ -41,16 +41,16 @@ class CsharpCompleter( ThreadedCompleter ):
A Completer that uses the Omnisharp server as completion engine.
"""
def __init__( self ):
super( CsharpCompleter, self ).__init__()
def __init__( self, user_options ):
super( CsharpCompleter, self ).__init__( user_options )
self._omnisharp_port = None
if vimsupport.GetBoolValue( 'g:ycm_auto_start_csharp_server' ):
if self.user_options[ 'auto_start_csharp_server' ]:
self._StartServer()
def OnVimLeave( self ):
if ( vimsupport.GetBoolValue( 'g:ycm_auto_stop_csharp_server' ) and
if ( self.user_options[ 'auto_start_csharp_server' ] and
self._ServerIsRunning() ):
self._StopServer()
@ -199,8 +199,7 @@ class CsharpCompleter( ThreadedCompleter ):
def _FindFreePort( self ):
""" Find port without an OmniSharp server running on it """
port = int( vimsupport.GetVariableValue(
'g:ycm_csharp_server_port' ) )
port = self.user_options[ 'csharp_server_port' ]
while self._GetResponse( '/checkalivestatus',
silent=True,
port=port ) != None:

View File

@ -17,5 +17,5 @@
from ycm.completers.cs.cs_completer import CsharpCompleter
def GetCompleter():
return CsharpCompleter()
def GetCompleter( user_options ):
return CsharpCompleter( user_options )

View File

@ -20,22 +20,17 @@ import vim
import os
import re
from ycm import vimsupport
from ycm.completers.threaded_completer import ThreadedCompleter
from ycm.completers.cpp.clang_completer import InCFamilyFile
from ycm.completers.cpp.flags import Flags
USE_WORKING_DIR = vimsupport.GetBoolValue(
'g:ycm_filepath_completion_use_working_dir' )
class FilenameCompleter( ThreadedCompleter ):
"""
General completer that provides filename and filepath completions.
"""
def __init__( self ):
super( FilenameCompleter, self ).__init__()
def __init__( self, user_options ):
super( FilenameCompleter, self ).__init__( user_options )
self._flags = Flags()
self._path_regex = re.compile( """
@ -88,7 +83,9 @@ class FilenameCompleter( ThreadedCompleter ):
path_match = self._path_regex.search( line )
path_dir = os.path.expanduser( path_match.group() ) if path_match else ''
return _GenerateCandidatesForPaths( _GetPathsStandardCase( path_dir ) )
return _GenerateCandidatesForPaths(
_GetPathsStandardCase( path_dir, self.user_options[
'filepath_completion_use_working_dir' ] ) )
def GetPathsIncludeCase( self, path_dir, include_current_file_dir ):
@ -110,8 +107,8 @@ class FilenameCompleter( ThreadedCompleter ):
return sorted( set( paths ) )
def _GetPathsStandardCase( path_dir ):
if not USE_WORKING_DIR and not path_dir.startswith( '/' ):
def _GetPathsStandardCase( path_dir, use_working_dir ):
if not use_working_dir and not path_dir.startswith( '/' ):
path_dir = os.path.join( os.path.dirname( vim.current.buffer.name ),
path_dir )

View File

@ -38,11 +38,11 @@ class GeneralCompleterStore( Completer ):
GeneralCompleterStore are passed to all general completers.
"""
def __init__( self ):
super( GeneralCompleterStore, self ).__init__()
self._identifier_completer = IdentifierCompleter()
self._filename_completer = FilenameCompleter()
self._ultisnips_completer = ( UltiSnipsCompleter()
def __init__( self, user_options ):
super( GeneralCompleterStore, self ).__init__( user_options )
self._identifier_completer = IdentifierCompleter( user_options )
self._filename_completer = FilenameCompleter( user_options )
self._ultisnips_completer = ( UltiSnipsCompleter( user_options )
if USE_ULTISNIPS_COMPLETER else None )
self._non_filename_completers = filter( lambda x: x,
[ self._ultisnips_completer,

View File

@ -27,8 +27,8 @@ class UltiSnipsCompleter( GeneralCompleter ):
General completer that provides UltiSnips snippet names in completions.
"""
def __init__( self ):
super( UltiSnipsCompleter, self ).__init__()
def __init__( self, user_options ):
super( UltiSnipsCompleter, self ).__init__( user_options )
self._candidates = None
self._filtered_candidates = None

View File

@ -29,8 +29,8 @@ class GeneralCompleter( Completer ):
Subclass Completer directly.
"""
def __init__( self ):
super( GeneralCompleter, self ).__init__()
def __init__( self, user_options ):
super( GeneralCompleter, self ).__init__( user_options )
def SupportedFiletypes( self ):

View File

@ -20,8 +20,8 @@
import ycm_core
from ycm.completers.cpp.clang_completer import ClangCompleter
def GetCompleter():
def GetCompleter( user_options ):
if ycm_core.HasClangSupport():
return ClangCompleter()
return ClangCompleter( user_options )
else:
return None

View File

@ -20,9 +20,9 @@
import ycm_core
from ycm.completers.cpp.clang_completer import ClangCompleter
def GetCompleter():
def GetCompleter( user_options ):
if ycm_core.HasClangSupport():
return ClangCompleter()
return ClangCompleter( user_options )
else:
return None

View File

@ -17,5 +17,5 @@
from ycm.completers.python.jedi_completer import JediCompleter
def GetCompleter():
return JediCompleter()
def GetCompleter( user_options ):
return JediCompleter( user_options )

View File

@ -45,8 +45,8 @@ class JediCompleter( ThreadedCompleter ):
https://jedi.readthedocs.org/en/latest/
"""
def __init__( self ):
super( JediCompleter, self ).__init__()
def __init__( self, user_options ):
super( JediCompleter, self ).__init__( user_options )
def SupportedFiletypes( self ):

View File

@ -38,8 +38,8 @@ class ThreadedCompleter( Completer ):
python/completers/general/filename_completer.py
"""
def __init__( self ):
super( ThreadedCompleter, self ).__init__()
def __init__( self, user_options ):
super( ThreadedCompleter, self ).__init__( user_options )
self._query_ready = Event()
self._candidates_ready = Event()
self._candidates = None

View File

@ -26,15 +26,13 @@ import string
import sys
import vim
from ycm import vimsupport
from ycm import user_options_store
from fnmatch import fnmatch
# Constants
YCM_EXTRA_CONF_FILENAME = '.ycm_extra_conf.py'
CONFIRM_CONF_FILE_MESSAGE = ('Found {0}. Load? \n\n(Question can be turned '
'off with options, see YCM docs)')
GLOBAL_YCM_EXTRA_CONF_FILE = os.path.expanduser(
vimsupport.GetVariableValue( "g:ycm_global_ycm_extra_conf" )
)
# Singleton variables
_module_for_module_file = {}
@ -86,11 +84,11 @@ def _ShouldLoad( module_file ):
decide using a white-/blacklist and ask the user for confirmation as a
fallback."""
if ( module_file == GLOBAL_YCM_EXTRA_CONF_FILE or
not vimsupport.GetBoolValue( 'g:ycm_confirm_extra_conf' ) ):
if ( module_file == _GlobalYcmExtraConfFileLocation() or
not user_options_store.Value( 'confirm_extra_conf' ) ):
return True
globlist = vimsupport.GetVariableValue( 'g:ycm_extra_conf_globlist' )
globlist = user_options_store.Value( 'extra_conf_globlist' )
for glob in globlist:
is_blacklisted = glob[0] == '!'
if _MatchesGlobPattern( module_file, glob.lstrip('!') ):
@ -139,15 +137,16 @@ def _MatchesGlobPattern( filename, glob ):
def _ExtraConfModuleSourceFilesForFile( filename ):
"""For a given filename, search all parent folders for YCM_EXTRA_CONF_FILENAME
files that will compute the flags necessary to compile the file.
If GLOBAL_YCM_EXTRA_CONF_FILE exists it is returned as a fallback."""
If _GlobalYcmExtraConfFileLocation() exists it is returned as a fallback."""
for folder in _PathsToAllParentFolders( filename ):
candidate = os.path.join( folder, YCM_EXTRA_CONF_FILENAME )
if os.path.exists( candidate ):
yield candidate
if ( GLOBAL_YCM_EXTRA_CONF_FILE
and os.path.exists( GLOBAL_YCM_EXTRA_CONF_FILE ) ):
yield GLOBAL_YCM_EXTRA_CONF_FILE
global_ycm_extra_conf = _GlobalYcmExtraConfFileLocation()
if ( global_ycm_extra_conf
and os.path.exists( global_ycm_extra_conf ) ):
yield global_ycm_extra_conf
def _PathsToAllParentFolders( filename ):
@ -188,3 +187,8 @@ def _DirectoryOfThisScript():
def _RandomName():
"""Generates a random module name."""
return ''.join( random.choice( string.ascii_lowercase ) for x in range( 15 ) )
def _GlobalYcmExtraConfFileLocation():
return os.path.expanduser(
user_options_store.Value( 'global_ycm_extra_conf' ) )

View File

@ -0,0 +1,34 @@
#!/usr/bin/env python
#
# Copyright (C) 2013 Strahinja Val Markovic <val@markovic.io>
#
# This file is part of YouCompleteMe.
#
# YouCompleteMe is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# YouCompleteMe is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with YouCompleteMe. If not, see <http://www.gnu.org/licenses/>.
from frozendict import frozendict
_USER_OPTIONS = {}
def SetAll( new_options ):
global _USER_OPTIONS
_USER_OPTIONS = frozendict( new_options )
def GetAll():
return _USER_OPTIONS
def Value( key ):
return _USER_OPTIONS[ key ]

View File

@ -145,3 +145,7 @@ def GetVariableValue( variable ):
def GetBoolValue( variable ):
return bool( int( vim.eval( variable ) ) )
def GetIntValue( variable ):
return int( vim.eval( variable ) )

View File

@ -26,14 +26,11 @@ from ycm.completers.all.omni_completer import OmniCompleter
from ycm.completers.general.general_completer_store import GeneralCompleterStore
FILETYPE_SPECIFIC_COMPLETION_TO_DISABLE = vim.eval(
'g:ycm_filetype_specific_completion_to_disable' )
class YouCompleteMe( object ):
def __init__( self ):
self._gencomp = GeneralCompleterStore()
self._omnicomp = OmniCompleter()
def __init__( self, user_options ):
self._user_options = user_options
self._gencomp = GeneralCompleterStore( user_options )
self._omnicomp = OmniCompleter( user_options )
self._filetype_completers = {}
@ -60,7 +57,7 @@ class YouCompleteMe( object ):
return completer
# Return the omni completer for the first filetype
return completers[0]
return completers[ 0 ]
def GetFiletypeCompleterForFiletype( self, filetype ):
@ -75,7 +72,7 @@ class YouCompleteMe( object ):
supported_filetypes = [ filetype ]
if os.path.exists( module_path ):
module = imp.load_source( filetype, module_path )
completer = module.GetCompleter()
completer = module.GetCompleter( self._user_options )
if completer:
supported_filetypes.extend( completer.SupportedFiletypes() )
else:
@ -107,12 +104,12 @@ class YouCompleteMe( object ):
def NativeFiletypeCompletionUsable( self ):
return ( _CurrentFiletypeCompletionEnabled() and
return ( self.CurrentFiletypeCompletionEnabled() and
self.NativeFiletypeCompletionAvailable() )
def FiletypeCompletionUsable( self ):
return ( _CurrentFiletypeCompletionEnabled() and
return ( self.CurrentFiletypeCompletionEnabled() and
self.FiletypeCompletionAvailable() )
@ -202,10 +199,11 @@ class YouCompleteMe( object ):
return '\n'.join( output )
def _CurrentFiletypeCompletionEnabled():
def CurrentFiletypeCompletionEnabled( self ):
filetypes = vimsupport.CurrentFiletypes()
return not all([ x in FILETYPE_SPECIFIC_COMPLETION_TO_DISABLE
for x in filetypes ])
filetype_to_disable = self._user_options[
'filetype_specific_completion_to_disable' ]
return not all([ x in filetype_to_disable for x in filetypes ])
def _PathToCompletersFolder():