A (barely) working version of ycmd + client

Still a lot of work to do.
This commit is contained in:
Strahinja Val Markovic 2013-09-20 17:24:34 -07:00
parent 02b88dccf1
commit 1730660555
23 changed files with 798 additions and 354 deletions

View File

@ -539,11 +539,6 @@ function! youcompleteme#Complete( findstart, base )
endif
py request = ycm_state.CreateCompletionRequest()
if !pyeval( 'request.ShouldComplete()' )
" for vim, -2 means not found but don't trigger an error message
" see :h complete-functions
return -2
endif
return pyeval( 'request.CompletionStartColumn()' )
else
return s:CompletionsForQuery( a:base )
@ -628,14 +623,15 @@ function! youcompleteme#OpenGoToList()
endfunction
command! -nargs=* -complete=custom,youcompleteme#SubCommandsComplete
\ YcmCompleter call s:CompleterCommand(<f-args>)
function! youcompleteme#SubCommandsComplete( arglead, cmdline, cursorpos )
return join( pyeval( 'ycm_state.GetFiletypeCompleter().DefinedSubcommands()' ),
\ "\n")
endfunction
" TODO: Make this work again
" command! -nargs=* -complete=custom,youcompleteme#SubCommandsComplete
" \ YcmCompleter call s:CompleterCommand(<f-args>)
"
"
" function! youcompleteme#SubCommandsComplete( arglead, cmdline, cursorpos )
" return join( pyeval( 'ycm_state.GetFiletypeCompleter().DefinedSubcommands()' ),
" \ "\n")
" endfunction
function! s:ForceCompile()

View File

@ -217,6 +217,18 @@ TEST( IdentifierCompleterTest, ShorterAndLowercaseWins ) {
"STDIN_FILENO" ) );
}
TEST( IdentifierCompleterTest, AddIdentifiersToDatabaseFromBufferWorks ) {
IdentifierCompleter completer;
completer.AddIdentifiersToDatabaseFromBuffer( "foo foogoo ba",
"foo",
"/foo/bar",
false );
EXPECT_THAT( completer.CandidatesForQueryAndType( "oo", "foo" ),
ElementsAre( "foo",
"foogoo" ) );
}
TEST( IdentifierCompleterTest, TagsEndToEndWorks ) {
IdentifierCompleter completer;
std::vector< std::string > tag_files;

View File

View File

@ -0,0 +1,77 @@
#!/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/>.
import vim
import json
import requests
from ycm import vimsupport
HEADERS = {'content-type': 'application/json'}
class BaseRequest( object ):
def __init__( self ):
pass
def Start( self ):
pass
def Done( self ):
return True
def Response( self ):
return {}
def PostDataToHandler( self, data, handler ):
response = requests.post( _BuildUri( handler ),
data = json.dumps( data ),
headers = HEADERS )
response.raise_for_status()
if response.text:
return response.json()
return None
server_location = 'http://localhost:6666'
def BuildRequestData( start_column = None, query = None ):
line, column = vimsupport.CurrentLineAndColumn()
request_data = {
'filetypes': vimsupport.CurrentFiletypes(),
'line_num': line,
'column_num': column,
'start_column': start_column,
'line_value': vim.current.line,
'filepath': vim.current.buffer.name,
'file_data': vimsupport.GetUnsavedAndCurrentBufferData()
}
if query:
request_data[ 'query' ] = query
return request_data
def _BuildUri( handler ):
return ''.join( [ BaseRequest.server_location, '/', handler ] )

View File

@ -0,0 +1,67 @@
#!/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 ycm.client.base_request import BaseRequest, BuildRequestData
class CommandRequest( BaseRequest ):
class ServerResponse( object ):
def __init__( self ):
pass
def Valid( self ):
return True
def __init__( self, arguments, completer_target = None ):
super( CommandRequest, self ).__init__()
self._arguments = arguments
self._completer_target = ( completer_target if completer_target
else 'filetype_default' )
# TODO: Handle this case.
# if completer_target == 'omni':
# completer = SERVER_STATE.GetOmniCompleter()
def Start( self ):
request_data = BuildRequestData()
request_data.update( {
'completer_target': self._completer_target,
'command_arguments': self._arguments
} )
self._response = self.PostDataToHandler( request_data,
'run_completer_command' )
def Response( self ):
# TODO: Call vimsupport.JumpToLocation if the user called a GoTo command...
# we may want to have specific subclasses of CommandRequest so that a
# GoToRequest knows it needs to jump after the data comes back.
#
# Also need to run the following on GoTo data:
#
# CAREFUL about line/column number 0-based/1-based confusion!
#
# defs = []
# defs.append( {'filename': definition.module_path.encode( 'utf-8' ),
# 'lnum': definition.line,
# 'col': definition.column + 1,
# 'text': definition.description.encode( 'utf-8' ) } )
# vim.eval( 'setqflist( %s )' % repr( defs ) )
# vim.eval( 'youcompleteme#OpenGoToList()' )
return self.ServerResponse()

View File

@ -0,0 +1,74 @@
#!/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 ycm import base
from ycm import vimsupport
from ycm.client.base_request import BaseRequest, BuildRequestData
class CompletionRequest( BaseRequest ):
def __init__( self ):
super( CompletionRequest, self ).__init__()
self._completion_start_column = base.CompletionStartColumn()
self._request_data = BuildRequestData( self._completion_start_column )
# def ShouldComplete( self ):
# return ( self._do_filetype_completion or
# self._ycm_state.ShouldUseGeneralCompleter( self._request_data ) )
def CompletionStartColumn( self ):
return self._completion_start_column
def Start( self, query ):
self._request_data[ 'query' ] = query
self._response = self.PostDataToHandler( self._request_data,
'get_completions' )
def Results( self ):
if not self._response:
return []
try:
return [ _ConvertCompletionDataToVimData( x ) for x in self._response ]
except Exception as e:
vimsupport.PostVimMessage( str( e ) )
return []
def _ConvertCompletionDataToVimData( completion_data ):
# see :h complete-items for a description of the dictionary fields
vim_data = {
'word' : completion_data[ 'insertion_text' ],
'dup' : 1,
}
if 'menu_text' in completion_data:
vim_data[ 'abbr' ] = completion_data[ 'menu_text' ]
if 'extra_menu_info' in completion_data:
vim_data[ 'menu' ] = completion_data[ 'extra_menu_info' ]
if 'kind' in completion_data:
vim_data[ 'kind' ] = completion_data[ 'kind' ]
if 'detailed_info' in completion_data:
vim_data[ 'info' ] = completion_data[ 'detailed_info' ]
return vim_data

View File

@ -0,0 +1,42 @@
#!/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 ycm.client.base_request import BaseRequest, BuildRequestData
class EventNotification( BaseRequest ):
def __init__( self, event_name, extra_data = None ):
super( EventNotification, self ).__init__()
self._event_name = event_name
self._extra_data = extra_data
def Start( self ):
request_data = BuildRequestData()
if self._extra_data:
request_data.update( self._extra_data )
request_data[ 'event_name' ] = self._event_name
self.PostDataToHandler( request_data, 'event_notification' )
def SendEventNotificationAsync( event_name, extra_data = None ):
event = EventNotification( event_name, extra_data )
event.Start()

View File

@ -18,12 +18,14 @@
# along with YouCompleteMe. If not, see <http://www.gnu.org/licenses/>.
import os
import logging
import ycm_core
from collections import defaultdict
from ycm.completers.general_completer import GeneralCompleter
# from ycm.completers.general import syntax_parse
from ycm import utils
from ycm import server_responses
from ycm.utils import ToUtf8IfNeeded
from ycm.server import responses
MAX_IDENTIFIER_COMPLETIONS_RETURNED = 10
SYNTAX_FILENAME = 'YCM_PLACEHOLDER_FOR_SYNTAX'
@ -36,6 +38,7 @@ class IdentifierCompleter( GeneralCompleter ):
self.completer.EnableThreading()
self.tags_file_last_mtime = defaultdict( int )
self.filetypes_with_keywords_loaded = set()
self._logger = logging.getLogger( __name__ )
def ShouldUseNow( self, request_data ):
@ -44,8 +47,8 @@ class IdentifierCompleter( GeneralCompleter ):
def CandidatesForQueryAsync( self, request_data ):
self.completions_future = self.completer.CandidatesForQueryAndTypeAsync(
utils.SanitizeQuery( request_data[ 'query' ] ),
request_data[ 'filetypes' ][ 0 ] )
ToUtf8IfNeeded( utils.SanitizeQuery( request_data[ 'query' ] ) ),
ToUtf8IfNeeded( request_data[ 'filetypes' ][ 0 ] ) )
def AddIdentifier( self, identifier, request_data ):
@ -56,10 +59,11 @@ class IdentifierCompleter( GeneralCompleter ):
return
vector = ycm_core.StringVec()
vector.append( identifier )
vector.append( ToUtf8IfNeeded( identifier ) )
self._logger.info( 'Adding ONE buffer identifier for file: %s', filepath )
self.completer.AddIdentifiersToDatabase( vector,
filetype,
filepath )
ToUtf8IfNeeded( filetype ),
ToUtf8IfNeeded( filepath ) )
def AddPreviousIdentifier( self, request_data ):
@ -88,10 +92,11 @@ class IdentifierCompleter( GeneralCompleter ):
return
text = request_data[ 'file_data' ][ filepath ][ 'contents' ]
self._logger.info( 'Adding buffer identifiers for file: %s', filepath )
self.completer.AddIdentifiersToDatabaseFromBufferAsync(
text,
filetype,
filepath,
ToUtf8IfNeeded( text ),
ToUtf8IfNeeded( filetype ),
ToUtf8IfNeeded( filepath ),
collect_from_comments_and_strings )
@ -110,7 +115,7 @@ class IdentifierCompleter( GeneralCompleter ):
continue
self.tags_file_last_mtime[ tag_file ] = current_mtime
absolute_paths_to_tag_files.append( tag_file )
absolute_paths_to_tag_files.append( ToUtf8IfNeeded( tag_file ) )
if not absolute_paths_to_tag_files:
return
@ -161,7 +166,7 @@ class IdentifierCompleter( GeneralCompleter ):
completions = _RemoveSmallCandidates(
completions, self.user_options[ 'min_num_identifier_candidate_chars' ] )
return [ server_responses.BuildCompletionData( x ) for x in completions ]
return [ responses.BuildCompletionData( x ) for x in completions ]
def _PreviousIdentifier( min_num_completion_start_chars, request_data ):

View File

@ -20,7 +20,7 @@
from collections import defaultdict
import ycm_core
import logging
from ycm import server_responses
from ycm.server import responses
from ycm import extra_conf_store
from ycm.utils import ToUtf8IfNeeded
from ycm.completers.completer import Completer
@ -72,9 +72,10 @@ class ClangCompleter( Completer ):
continue
unsaved_file = ycm_core.UnsavedFile()
unsaved_file.contents_ = contents
unsaved_file.length_ = len( contents )
unsaved_file.filename_ = filename
utf8_contents = ToUtf8IfNeeded( contents )
unsaved_file.contents_ = utf8_contents
unsaved_file.length_ = len( utf8_contents )
unsaved_file.filename_ = ToUtf8IfNeeded( filename )
files.append( unsaved_file )
return files
@ -86,17 +87,17 @@ class ClangCompleter( Completer ):
if not filename:
return
if self.completer.UpdatingTranslationUnit( filename ):
if self.completer.UpdatingTranslationUnit( ToUtf8IfNeeded( filename ) ):
self.completions_future = None
self._logger.info( PARSING_FILE_MESSAGE )
return server_responses.BuildDisplayMessageResponse(
return responses.BuildDisplayMessageResponse(
PARSING_FILE_MESSAGE )
flags = self.flags.FlagsForFile( filename )
if not flags:
self.completions_future = None
self._logger.info( NO_COMPILE_FLAGS_MESSAGE )
return server_responses.BuildDisplayMessageResponse(
return responses.BuildDisplayMessageResponse(
NO_COMPILE_FLAGS_MESSAGE )
# TODO: sanitize query, probably in C++ code
@ -142,11 +143,11 @@ class ClangCompleter( Completer ):
command = arguments[ 0 ]
if command == 'GoToDefinition':
self._GoToDefinition( request_data )
return self._GoToDefinition( request_data )
elif command == 'GoToDeclaration':
self._GoToDeclaration( request_data )
return self._GoToDeclaration( request_data )
elif command == 'GoToDefinitionElseDeclaration':
self._GoToDefinitionElseDeclaration( request_data )
return self._GoToDefinitionElseDeclaration( request_data )
elif command == 'ClearCompilationFlagCache':
self._ClearCompilationFlagCache( request_data )
@ -155,20 +156,20 @@ class ClangCompleter( Completer ):
filename = request_data[ 'filepath' ]
if not filename:
self._logger.warning( INVALID_FILE_MESSAGE )
return server_responses.BuildDisplayMessageResponse(
return responses.BuildDisplayMessageResponse(
INVALID_FILE_MESSAGE )
flags = self.flags.FlagsForFile( filename )
if not flags:
self._logger.info( NO_COMPILE_FLAGS_MESSAGE )
return server_responses.BuildDisplayMessageResponse(
return responses.BuildDisplayMessageResponse(
NO_COMPILE_FLAGS_MESSAGE )
files = self.GetUnsavedFilesVector()
files = self.GetUnsavedFilesVector( request_data )
line = request_data[ 'line_num' ] + 1
column = request_data[ 'start_column' ] + 1
return getattr( self.completer, goto_function )(
filename,
ToUtf8IfNeeded( filename ),
line,
column,
files,
@ -180,7 +181,7 @@ class ClangCompleter( Completer ):
if not location or not location.IsValid():
raise RuntimeError( 'Can\'t jump to definition.' )
return server_responses.BuildGoToResponse( location.filename_,
return responses.BuildGoToResponse( location.filename_,
location.line_number_,
location.column_number_ )
@ -190,7 +191,7 @@ class ClangCompleter( Completer ):
if not location or not location.IsValid():
raise RuntimeError( 'Can\'t jump to declaration.' )
return server_responses.BuildGoToResponse( location.filename_,
return responses.BuildGoToResponse( location.filename_,
location.line_number_,
location.column_number_ )
@ -202,7 +203,7 @@ class ClangCompleter( Completer ):
if not location or not location.IsValid():
raise RuntimeError( 'Can\'t jump to definition or declaration.' )
return server_responses.BuildGoToResponse( location.filename_,
return responses.BuildGoToResponse( location.filename_,
location.line_number_,
location.column_number_ )
@ -223,10 +224,10 @@ class ClangCompleter( Completer ):
if not filename:
self._logger.warning( INVALID_FILE_MESSAGE )
return server_responses.BuildDisplayMessageResponse(
return responses.BuildDisplayMessageResponse(
INVALID_FILE_MESSAGE )
if self.completer.UpdatingTranslationUnit( filename ):
if self.completer.UpdatingTranslationUnit( ToUtf8IfNeeded( filename ) ):
self.extra_parse_desired = True
return
@ -234,11 +235,11 @@ class ClangCompleter( Completer ):
if not flags:
self.parse_future = None
self._logger.info( NO_COMPILE_FLAGS_MESSAGE )
return server_responses.BuildDisplayMessageResponse(
return responses.BuildDisplayMessageResponse(
NO_COMPILE_FLAGS_MESSAGE )
self.parse_future = self.completer.UpdateTranslationUnitAsync(
filename,
ToUtf8IfNeeded( filename ),
self.GetUnsavedFilesVector( request_data ),
flags )
@ -246,7 +247,8 @@ class ClangCompleter( Completer ):
def OnBufferUnload( self, request_data ):
self.completer.DeleteCachesForFileAsync( request_data[ 'unloaded_buffer' ] )
self.completer.DeleteCachesForFileAsync(
ToUtf8IfNeeded( request_data[ 'unloaded_buffer' ] ) )
def DiagnosticsForCurrentFileReady( self ):
@ -257,16 +259,18 @@ class ClangCompleter( Completer ):
def GettingCompletions( self, request_data ):
return self.completer.UpdatingTranslationUnit( request_data[ 'filepath' ] )
return self.completer.UpdatingTranslationUnit(
ToUtf8IfNeeded( request_data[ 'filepath' ] ) )
def GetDiagnosticsForCurrentFile( self, request_data ):
filename = request_data[ 'filepath' ]
if self.DiagnosticsForCurrentFileReady():
diagnostics = self.completer.DiagnosticsForFile( filename )
diagnostics = self.completer.DiagnosticsForFile(
ToUtf8IfNeeded( filename ) )
self.diagnostic_store = DiagnosticsToDiagStructure( diagnostics )
self.last_prepared_diagnostics = [
server_responses.BuildDiagnosticData( x ) for x in
responses.BuildDiagnosticData( x ) for x in
diagnostics[ : self.max_diagnostics_to_display ] ]
self.parse_future = None
@ -282,12 +286,12 @@ class ClangCompleter( Completer ):
current_file = request_data[ 'filepath' ]
if not self.diagnostic_store:
return server_responses.BuildDisplayMessageResponse(
return responses.BuildDisplayMessageResponse(
NO_DIAGNOSTIC_MESSAGE )
diagnostics = self.diagnostic_store[ current_file ][ current_line ]
if not diagnostics:
return server_responses.BuildDisplayMessageResponse(
return responses.BuildDisplayMessageResponse(
NO_DIAGNOSTIC_MESSAGE )
closest_diagnostic = None
@ -299,7 +303,7 @@ class ClangCompleter( Completer ):
distance_to_closest_diagnostic = distance
closest_diagnostic = diagnostic
return server_responses.BuildDisplayMessageResponse(
return responses.BuildDisplayMessageResponse(
closest_diagnostic.long_formatted_text_ )
@ -314,7 +318,7 @@ class ClangCompleter( Completer ):
return ''
flags = self.flags.FlagsForFile( filename ) or []
source = extra_conf_store.ModuleFileForSourceFile( filename )
return server_responses.BuildDisplayMessageResponse(
return responses.BuildDisplayMessageResponse(
'Flags for {0} loaded from {1}:\n{2}'.format( filename,
source,
list( flags ) ) )
@ -348,7 +352,7 @@ class ClangCompleter( Completer ):
def ConvertCompletionData( completion_data ):
return server_responses.BuildCompletionData(
return responses.BuildCompletionData(
insertion_text = completion_data.TextToInsertInBuffer(),
menu_text = completion_data.MainCompletionText(),
extra_menu_info = completion_data.ExtraMenuInfo(),

View File

@ -22,13 +22,13 @@ import os
from sys import platform
import glob
from ycm.completers.threaded_completer import ThreadedCompleter
from ycm import server_responses
from ycm.server import responses
from ycm import utils
import urllib2
import urllib
import urlparse
import json
import subprocess
import tempfile
import logging
@ -44,7 +44,7 @@ class CsharpCompleter( ThreadedCompleter ):
def __init__( self, user_options ):
super( CsharpCompleter, self ).__init__( user_options )
self._omnisharp_port = None
self._logger = logging.getLogger(__name__)
self._logger = logging.getLogger( __name__ )
# if self.user_options[ 'auto_start_csharp_server' ]:
# self._StartServer()
@ -62,7 +62,7 @@ class CsharpCompleter( ThreadedCompleter ):
def ComputeCandidates( self, request_data ):
return [ server_responses.BuildCompletionData(
return [ responses.BuildCompletionData(
completion[ 'CompletionText' ],
completion[ 'DisplayText' ],
completion[ 'Description' ] )
@ -135,8 +135,8 @@ class CsharpCompleter( ThreadedCompleter ):
command = [ omnisharp + ' -p ' + str( self._omnisharp_port ) + ' -s ' +
path_to_solutionfile ]
filename_format = ( tempfile.gettempdir() +
'/omnisharp_{port}_{sln}_{std}.log' )
filename_format = os.path.join( utils.PathToTempDir(),
'omnisharp_{port}_{sln}_{std}.log' )
self._filename_stdout = filename_format.format(
port=self._omnisharp_port, sln=solutionfile, std='stdout' )
@ -169,7 +169,7 @@ class CsharpCompleter( ThreadedCompleter ):
definition = self._GetResponse( '/gotodefinition',
self._DefaultParameters( request_data ) )
if definition[ 'FileName' ] != None:
return server_responses.BuildGoToResponse( definition[ 'FileName' ],
return responses.BuildGoToResponse( definition[ 'FileName' ],
definition[ 'Line' ],
definition[ 'Column' ] )
else:

View File

@ -22,7 +22,7 @@ import re
from ycm.completers.threaded_completer import ThreadedCompleter
from ycm.completers.cpp.clang_completer import InCFamilyFile
from ycm.completers.cpp.flags import Flags
from ycm import server_responses
from ycm.server import responses
class FilenameCompleter( ThreadedCompleter ):
"""
@ -146,7 +146,7 @@ def _GenerateCandidatesForPaths( absolute_paths ):
is_dir = os.path.isdir( absolute_path )
completion_dicts.append(
server_responses.BuildCompletionData( basename,
responses.BuildCompletionData( basename,
'[Dir]' if is_dir else '[File]' ) )
return completion_dicts

View File

@ -20,7 +20,7 @@
from ycm.completers.general_completer import GeneralCompleter
from UltiSnips import UltiSnips_Manager
from ycm import server_responses
from ycm.server import responses
class UltiSnipsCompleter( GeneralCompleter ):
@ -64,7 +64,7 @@ def _GetCandidates():
# UltiSnips_Manager._snips() returns a class instance where:
# class.trigger - name of snippet trigger word ( e.g. defn or testcase )
# class.description - description of the snippet
return [ server_responses.BuildCompletionData(
return [ responses.BuildCompletionData(
str( snip.trigger ),
str( '<snip> ' + snip.description.encode( 'utf-8' ) ) )
for snip in rawsnips ]

View File

@ -20,7 +20,7 @@
# along with YouCompleteMe. If not, see <http://www.gnu.org/licenses/>.
from ycm.completers.threaded_completer import ThreadedCompleter
from ycm import server_responses
from ycm.server import responses
import sys
from os.path import join, abspath, dirname
@ -65,7 +65,7 @@ class JediCompleter( ThreadedCompleter ):
def ComputeCandidates( self, request_data ):
script = self._GetJediScript( request_data )
return [ server_responses.BuildCompletionData(
return [ responses.BuildCompletionData(
str( completion.name ),
str( completion.description ),
str( completion.doc ) )
@ -140,7 +140,7 @@ class JediCompleter( ThreadedCompleter ):
else:
raise RuntimeError( 'Builtin modules cannot be displayed.' )
else:
return server_responses.BuildGoToResponse( definition.module_path,
return responses.BuildGoToResponse( definition.module_path,
definition.line -1,
definition.column )
else:
@ -148,11 +148,11 @@ class JediCompleter( ThreadedCompleter ):
defs = []
for definition in definition_list:
if definition.in_builtin_module():
defs.append( server_responses.BuildDescriptionOnlyGoToResponse(
defs.append( responses.BuildDescriptionOnlyGoToResponse(
'Builting ' + definition.description ) )
else:
defs.append(
server_responses.BuildGoToResponse( definition.module_path,
responses.BuildGoToResponse( definition.module_path,
definition.line -1,
definition.column,
definition.description ) )

View File

View File

@ -0,0 +1 @@
{ "filepath_completion_use_working_dir": 0, "min_num_of_chars_for_completion": 2, "semantic_triggers": {}, "collect_identifiers_from_comments_and_strings": 0, "filetype_specific_completion_to_disable": {}, "collect_identifiers_from_tags_files": 0, "extra_conf_globlist": [ "~\/repos\/*", "\/home\/strahinja\/googrepos\/*", "~\/local_googrepos\/*", "~\/.ycm_extra_conf.py" ], "global_ycm_extra_conf": "\/usr\/lib\/youcompleteme\/ycm_extra_conf.py", "confirm_extra_conf": 1, "complete_in_comments": 0, "complete_in_strings": 1, "min_num_identifier_candidate_chars": 0, "max_diagnostics_to_display": 30, "auto_stop_csharp_server": 1, "seed_identifiers_with_syntax": 0, "csharp_server_port": 2000, "filetype_whitelist": { "*": "1" }, "auto_start_csharp_server": 1, "filetype_blacklist": { "tagbar": "1", "notes": "1", "markdown": "1", "unite": "1", "text": "1" } }

View File

@ -18,6 +18,8 @@
# along with YouCompleteMe. If not, see <http://www.gnu.org/licenses/>.
# TODO: Move this file under server/ and rename it responses.py
def BuildGoToResponse( filepath, line_num, column_num, description = None ):
response = {
'filepath': filepath,

168
python/ycm/server/server.py Executable file
View File

@ -0,0 +1,168 @@
#!/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/>.
import sys
import os
# We want to have the YouCompleteMe/python directory on the Python PATH because
# all the code already assumes that it's there. This is a relic from before the
# client/server architecture.
# TODO: Fix things so that this is not needed anymore when we split ycmd into a
# separate repository.
sys.path.insert( 0, os.path.join(
os.path.dirname( os.path.abspath( __file__ ) ),
'../..' ) )
import logging
import time
import httplib
import json
import bottle
from bottle import run, request, response
import server_state
from ycm import extra_conf_store
from ycm import user_options_store
import argparse
# num bytes for the request body buffer; request.json only works if the request
# size is less than this
bottle.Request.MEMFILE_MAX = 300 * 1024
user_options_store.LoadDefaults()
SERVER_STATE = server_state.ServerState( user_options_store.GetAll() )
LOGGER = logging.getLogger( __name__ )
app = bottle.Bottle()
@app.post( '/event_notification' )
def EventNotification():
LOGGER.info( 'Received event notification')
request_data = request.json
event_name = request_data[ 'event_name' ]
LOGGER.debug( 'Event name: %s', event_name )
event_handler = 'On' + event_name
getattr( SERVER_STATE.GetGeneralCompleter(), event_handler )( request_data )
filetypes = request_data[ 'filetypes' ]
if SERVER_STATE.FiletypeCompletionUsable( filetypes ):
getattr( SERVER_STATE.GetFiletypeCompleter( filetypes ),
event_handler )( request_data )
if hasattr( extra_conf_store, event_handler ):
getattr( extra_conf_store, event_handler )( request_data )
# TODO: shut down the server on VimClose
@app.post( '/run_completer_command' )
def RunCompleterCommand():
LOGGER.info( 'Received command request')
request_data = request.json
completer_target = request_data[ 'completer_target' ]
if completer_target == 'identifier':
completer = SERVER_STATE.GetGeneralCompleter()
else:
completer = SERVER_STATE.GetFiletypeCompleter()
return _JsonResponse(
completer.OnUserCommand( request_data[ 'command_arguments' ],
request_data ) )
@app.post( '/get_completions' )
def GetCompletions():
LOGGER.info( 'Received completion request')
request_data = request.json
do_filetype_completion = SERVER_STATE.ShouldUseFiletypeCompleter(
request_data )
LOGGER.debug( 'Using filetype completion: %s', do_filetype_completion )
filetypes = request_data[ 'filetypes' ]
completer = ( SERVER_STATE.GetFiletypeCompleter( filetypes ) if
do_filetype_completion else
SERVER_STATE.GetGeneralCompleter() )
# This is necessary so that general_completer_store fills up
# _current_query_completers.
# TODO: Fix this.
completer.ShouldUseNow( request_data )
# TODO: This should not be async anymore, server is multi-threaded
completer.CandidatesForQueryAsync( request_data )
while not completer.AsyncCandidateRequestReady():
time.sleep( 0.03 )
return _JsonResponse( completer.CandidatesFromStoredRequest() )
@app.route( '/user_options' )
def UserOptions():
global SERVER_STATE
if request.method == 'GET':
LOGGER.info( 'Received user options GET request')
return SERVER_STATE.user_options
elif request.method == 'POST':
LOGGER.info( 'Received user options POST request')
data = request.json
SERVER_STATE = server_state.ServerState( data )
user_options_store.SetAll( data )
else:
response.status = httplib.BAD_REQUEST
@app.post( '/filetype_completion_available')
def FiletypeCompletionAvailable():
LOGGER.info( 'Received filetype completion available request')
return _JsonResponse( SERVER_STATE.FiletypeCompletionAvailable(
request.json[ 'filetypes' ] ) )
def _JsonResponse( data ):
response.set_header( 'Content-Type', 'application/json' )
return json.dumps( data )
def Main():
global LOGGER
parser = argparse.ArgumentParser()
parser.add_argument( '--host', type = str, default = 'localhost',
help='server hostname')
parser.add_argument( '--port', type = int, default = 6666,
help='server port')
parser.add_argument( '--log', type = str, default = 'info',
help='log level, one of '
'[debug|info|warning|error|critical]')
args = parser.parse_args()
numeric_level = getattr( logging, args.log.upper(), None )
if not isinstance( numeric_level, int ):
raise ValueError( 'Invalid log level: %s' % args.log )
logging.basicConfig( format = '%(asctime)s - %(levelname)s - %(message)s',
level = numeric_level )
LOGGER = logging.getLogger( __name__ )
run( app = app, host = args.host, port = args.port, server='cherrypy' )
if __name__ == "__main__":
Main()

View File

@ -0,0 +1,108 @@
#!/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/>.
import imp
import os
from ycm.completers.general.general_completer_store import GeneralCompleterStore
class ServerState( object ):
def __init__( self, user_options ):
self._user_options = user_options
self._filetype_completers = {}
self._gencomp = GeneralCompleterStore( self._user_options )
@property
def user_options( self ):
return self._user_options
def _GetFiletypeCompleterForFiletype( self, filetype ):
try:
return self._filetype_completers[ filetype ]
except KeyError:
pass
module_path = _PathToFiletypeCompleterPluginLoader( filetype )
completer = None
supported_filetypes = [ filetype ]
if os.path.exists( module_path ):
module = imp.load_source( filetype, module_path )
completer = module.GetCompleter( self._user_options )
if completer:
supported_filetypes.extend( completer.SupportedFiletypes() )
for supported_filetype in supported_filetypes:
self._filetype_completers[ supported_filetype ] = completer
return completer
def GetFiletypeCompleter( self, current_filetypes ):
completers = [ self._GetFiletypeCompleterForFiletype( filetype )
for filetype in current_filetypes ]
for completer in completers:
if completer:
return completer
return None
def FiletypeCompletionAvailable( self, filetypes ):
return bool( self.GetFiletypeCompleter( filetypes ) )
def FiletypeCompletionUsable( self, filetypes ):
return ( self.CurrentFiletypeCompletionEnabled( filetypes ) and
self.FiletypeCompletionAvailable( filetypes ) )
def ShouldUseGeneralCompleter( self, request_data ):
return self._gencomp.ShouldUseNow( request_data )
def ShouldUseFiletypeCompleter( self, request_data ):
filetypes = request_data[ 'filetypes' ]
if self.FiletypeCompletionUsable( filetypes ):
return self.GetFiletypeCompleter( filetypes ).ShouldUseNow( request_data )
return False
def GetGeneralCompleter( self ):
return self._gencomp
def CurrentFiletypeCompletionEnabled( self, current_filetypes ):
filetype_to_disable = self._user_options[
'filetype_specific_completion_to_disable' ]
return not all([ x in filetype_to_disable for x in current_filetypes ])
def _PathToCompletersFolder():
dir_of_current_script = os.path.dirname( os.path.abspath( __file__ ) )
return os.path.join( dir_of_current_script, '..', 'completers' )
def _PathToFiletypeCompleterPluginLoader( filetype ):
return os.path.join( _PathToCompletersFolder(), filetype, 'hook.py' )

View File

View File

@ -0,0 +1,74 @@
#!/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 webtest import TestApp
from .. import server
from ..responses import BuildCompletionData
from nose.tools import ok_, eq_
import bottle
bottle.debug( True )
def GetCompletions_IdentifierCompleterWorks_test():
app = TestApp( server.app )
event_data = {
'event_name': 'FileReadyToParse',
'filetypes': ['foo'],
'filepath': '/foo/bar',
'file_data': {
'/foo/bar': {
'contents': 'foo foogoo ba',
'filetypes': ['foo']
}
}
}
app.post_json( '/event_notification', event_data )
line_value = 'oo foo foogoo ba';
completion_data = {
'query': 'oo',
'filetypes': ['foo'],
'filepath': '/foo/bar',
'line_num': 0,
'column_num': 2,
'start_column': 0,
'line_value': line_value,
'file_data': {
'/foo/bar': {
'contents': line_value,
'filetypes': ['foo']
}
}
}
eq_( [ BuildCompletionData( 'foo' ),
BuildCompletionData( 'foogoo' ) ],
app.post_json( '/get_completions', completion_data ).json )
def FiletypeCompletionAvailable_Works_test():
app = TestApp( server.app )
request_data = {
'filetypes': ['cpp']
}
ok_( app.post_json( '/filetype_completion_available',
request_data ).json )

View File

@ -17,6 +17,8 @@
# You should have received a copy of the GNU General Public License
# along with YouCompleteMe. If not, see <http://www.gnu.org/licenses/>.
import json
import os
from ycm.frozendict import frozendict
_USER_OPTIONS = {}
@ -32,3 +34,16 @@ def GetAll():
def Value( key ):
return _USER_OPTIONS[ key ]
def LoadDefaults():
SetAll( _DefaultOptions() )
def _DefaultOptions():
settings_path = os.path.join(
os.path.dirname( os.path.abspath( __file__ ) ),
'server/default_settings.json' )
with open( settings_path ) as f:
return json.loads( f.read() )

View File

@ -17,6 +17,9 @@
# You should have received a copy of the GNU General Public License
# along with YouCompleteMe. If not, see <http://www.gnu.org/licenses/>.
import tempfile
import os
def IsIdentifierChar( char ):
return char.isalnum() or char == '_'
@ -29,3 +32,7 @@ def ToUtf8IfNeeded( string_or_unicode ):
if isinstance( string_or_unicode, unicode ):
return string_or_unicode.encode( 'utf8' )
return string_or_unicode
def PathToTempDir():
return os.path.join( tempfile.gettempdir(), 'ycm_temp' )

View File

@ -17,176 +17,53 @@
# You should have received a copy of the GNU General Public License
# along with YouCompleteMe. If not, see <http://www.gnu.org/licenses/>.
import imp
import os
import time
import vim
import ycm_core
import logging
import tempfile
import subprocess
from ycm import vimsupport
from ycm import base
from ycm import extra_conf_store
from ycm import utils
from ycm.completers.all.omni_completer import OmniCompleter
from ycm.completers.general.general_completer_store import GeneralCompleterStore
# TODO: Put the Request classes in separate files
class BaseRequest( object ):
def __init__( self ):
pass
def Start( self ):
pass
def Done( self ):
return True
def Response( self ):
return {}
class CompletionRequest( BaseRequest ):
def __init__( self, ycm_state ):
super( CompletionRequest, self ).__init__()
self._completion_start_column = base.CompletionStartColumn()
self._ycm_state = ycm_state
self._request_data = _BuildRequestData( self._completion_start_column )
self._do_filetype_completion = self._ycm_state.ShouldUseFiletypeCompleter(
self._request_data )
self._completer = ( self._ycm_state.GetFiletypeCompleter() if
self._do_filetype_completion else
self._ycm_state.GetGeneralCompleter() )
def ShouldComplete( self ):
return ( self._do_filetype_completion or
self._ycm_state.ShouldUseGeneralCompleter( self._request_data ) )
def CompletionStartColumn( self ):
return self._completion_start_column
def Start( self, query ):
self._request_data[ 'query' ] = query
self._completer.CandidatesForQueryAsync( self._request_data )
def Done( self ):
return self._completer.AsyncCandidateRequestReady()
def Results( self ):
try:
return [ _ConvertCompletionDataToVimData( x )
for x in self._completer.CandidatesFromStoredRequest() ]
except Exception as e:
vimsupport.PostVimMessage( str( e ) )
return []
class CommandRequest( BaseRequest ):
class ServerResponse( object ):
def __init__( self ):
pass
def Valid( self ):
return True
def __init__( self, ycm_state, arguments, completer_target = None ):
super( CommandRequest, self ).__init__()
if not completer_target:
completer_target = 'filetpe_default'
if completer_target == 'omni':
self._completer = ycm_state.GetOmniCompleter()
elif completer_target == 'identifier':
self._completer = ycm_state.GetGeneralCompleter()
else:
self._completer = ycm_state.GetFiletypeCompleter()
self._arguments = arguments
def Start( self ):
self._completer.OnUserCommand( self._arguments,
_BuildRequestData() )
def Response( self ):
# TODO: Call vimsupport.JumpToLocation if the user called a GoTo command...
# we may want to have specific subclasses of CommandRequest so that a
# GoToRequest knows it needs to jump after the data comes back.
#
# Also need to run the following on GoTo data:
# CAREFUL about line/column number 0-based/1-based confusion!
#
# defs = []
# defs.append( {'filename': definition.module_path.encode( 'utf-8' ),
# 'lnum': definition.line,
# 'col': definition.column + 1,
# 'text': definition.description.encode( 'utf-8' ) } )
# vim.eval( 'setqflist( %s )' % repr( defs ) )
# vim.eval( 'youcompleteme#OpenGoToList()' )
return self.ServerResponse()
class EventNotification( BaseRequest ):
def __init__( self, event_name, ycm_state, extra_data = None ):
super( EventNotification, self ).__init__()
self._ycm_state = ycm_state
self._event_name = event_name
self._request_data = _BuildRequestData()
if extra_data:
self._request_data.update( extra_data )
def Start( self ):
event_handler = 'On' + self._event_name
getattr( self._ycm_state.GetGeneralCompleter(),
event_handler )( self._request_data )
if self._ycm_state.FiletypeCompletionUsable():
getattr( self._ycm_state.GetFiletypeCompleter(),
event_handler )( self._request_data )
if hasattr( extra_conf_store, event_handler ):
getattr( extra_conf_store, event_handler )( self._request_data )
def SendEventNotificationAsync( event_name, ycm_state, extra_data = None ):
event = EventNotification( event_name, ycm_state, extra_data )
event.Start()
from ycm.client.base_request import BaseRequest
from ycm.client.command_request import CommandRequest
from ycm.client.completion_request import CompletionRequest
from ycm.client.event_notification import SendEventNotificationAsync
SERVER_PORT_RANGE_START = 10000
class YouCompleteMe( object ):
def __init__( self, user_options ):
# TODO: This should go into the server
# TODO: Use more logging like we do in cs_completer
self._logfile = tempfile.NamedTemporaryFile()
logging.basicConfig( format='%(asctime)s - %(levelname)s - %(message)s',
filename=self._logfile.name,
level=logging.DEBUG )
self._user_options = user_options
self._gencomp = GeneralCompleterStore( user_options )
self._omnicomp = OmniCompleter( user_options )
self._filetype_completers = {}
self._current_completion_request = None
server_port = SERVER_PORT_RANGE_START + os.getpid()
command = ''.join( [ 'python ',
_PathToServerScript(),
' --port=',
str( server_port ) ] )
BaseRequest.server_location = 'http://localhost:' + str( server_port )
filename_format = os.path.join( utils.PathToTempDir(),
'server_{port}_{std}.log' )
self._server_stdout = filename_format.format( port=server_port,
std='stdout' )
self._server_stderr = filename_format.format( port=server_port,
std='stderr' )
with open( self._server_stderr, 'w' ) as fstderr:
with open( self._server_stdout, 'w' ) as fstdout:
subprocess.Popen( command, stdout=fstdout, stderr=fstderr, shell=True )
def CreateCompletionRequest( self ):
# We have to store a reference to the newly created CompletionRequest
# because VimScript can't store a reference to a Python object across
# function calls... Thus we need to keep this request somewhere.
self._current_completion_request = CompletionRequest( self )
self._current_completion_request = CompletionRequest()
return self._current_completion_request
@ -204,72 +81,19 @@ class YouCompleteMe( object ):
return self._current_completion_request
def GetGeneralCompleter( self ):
return self._gencomp
def GetOmniCompleter( self ):
return self._omnicomp
def GetFiletypeCompleter( self ):
filetypes = vimsupport.CurrentFiletypes()
completers = [ self.GetFiletypeCompleterForFiletype( filetype )
for filetype in filetypes ]
if not completers:
return None
# Try to find a native completer first
for completer in completers:
if completer and completer is not self._omnicomp:
return completer
# Return the omni completer for the first filetype
return completers[ 0 ]
def GetFiletypeCompleterForFiletype( self, filetype ):
try:
return self._filetype_completers[ filetype ]
except KeyError:
pass
module_path = _PathToFiletypeCompleterPluginLoader( filetype )
completer = None
supported_filetypes = [ filetype ]
if os.path.exists( module_path ):
module = imp.load_source( filetype, module_path )
completer = module.GetCompleter( self._user_options )
if completer:
supported_filetypes.extend( completer.SupportedFiletypes() )
else:
completer = self._omnicomp
for supported_filetype in supported_filetypes:
self._filetype_completers[ supported_filetype ] = completer
return completer
def ShouldUseGeneralCompleter( self, request_data ):
return self._gencomp.ShouldUseNow( request_data )
def ShouldUseFiletypeCompleter( self, request_data ):
if self.FiletypeCompletionUsable():
return self.GetFiletypeCompleter().ShouldUseNow( request_data )
def NativeFiletypeCompletionAvailable( self ):
# TODO: Talk to server about this.
return False
def NativeFiletypeCompletionAvailable( self ):
completer = self.GetFiletypeCompleter()
return bool( completer ) and completer is not self._omnicomp
def FiletypeCompletionAvailable( self ):
return bool( self.GetFiletypeCompleter() )
# TODO: This may not be needed at all when the server is ready. Evaluate this
# later.
# def FiletypeCompletionAvailable( self ):
# return bool( self.GetFiletypeCompleter() )
def NativeFiletypeCompletionUsable( self ):
@ -277,9 +101,11 @@ class YouCompleteMe( object ):
self.NativeFiletypeCompletionAvailable() )
def FiletypeCompletionUsable( self ):
return ( self.CurrentFiletypeCompletionEnabled() and
self.FiletypeCompletionAvailable() )
# TODO: This may not be needed at all when the server is ready. Evaluate this
# later.
# def FiletypeCompletionUsable( self ):
# return ( self.CurrentFiletypeCompletionEnabled() and
# self.FiletypeCompletionAvailable() )
def OnFileReadyToParse( self ):
@ -290,51 +116,55 @@ class YouCompleteMe( object ):
# TODO: make this work again
# if self._user_options[ 'seed_identifiers_with_syntax' ]:
SendEventNotificationAsync( 'FileReadyToParse', self, extra_data )
SendEventNotificationAsync( 'FileReadyToParse', extra_data )
def OnBufferUnload( self, deleted_buffer_file ):
SendEventNotificationAsync( 'BufferUnload',
self,
{ 'unloaded_buffer': deleted_buffer_file } )
def OnBufferVisit( self ):
SendEventNotificationAsync( 'BufferVisit', self )
SendEventNotificationAsync( 'BufferVisit' )
def OnInsertLeave( self ):
SendEventNotificationAsync( 'InsertLeave', self )
SendEventNotificationAsync( 'InsertLeave' )
def OnVimLeave( self ):
SendEventNotificationAsync( 'VimLeave', self )
SendEventNotificationAsync( 'VimLeave' )
def OnCurrentIdentifierFinished( self ):
SendEventNotificationAsync( 'CurrentIdentifierFinished', self )
SendEventNotificationAsync( 'CurrentIdentifierFinished' )
# TODO: Make this work again.
def DiagnosticsForCurrentFileReady( self ):
if self.FiletypeCompletionUsable():
return self.GetFiletypeCompleter().DiagnosticsForCurrentFileReady()
# if self.FiletypeCompletionUsable():
# return self.GetFiletypeCompleter().DiagnosticsForCurrentFileReady()
return False
# TODO: Make this work again.
def GetDiagnosticsForCurrentFile( self ):
if self.FiletypeCompletionUsable():
return self.GetFiletypeCompleter().GetDiagnosticsForCurrentFile()
# if self.FiletypeCompletionUsable():
# return self.GetFiletypeCompleter().GetDiagnosticsForCurrentFile()
return []
# TODO: Make this work again.
def GetDetailedDiagnostic( self ):
if self.FiletypeCompletionUsable():
return self.GetFiletypeCompleter().GetDetailedDiagnostic()
# if self.FiletypeCompletionUsable():
# return self.GetFiletypeCompleter().GetDetailedDiagnostic()
pass
# TODO: Make this work again.
def GettingCompletions( self ):
if self.FiletypeCompletionUsable():
return self.GetFiletypeCompleter().GettingCompletions()
# if self.FiletypeCompletionUsable():
# return self.GetFiletypeCompleter().GettingCompletions()
return False
@ -366,51 +196,13 @@ class YouCompleteMe( object ):
return not all([ x in filetype_to_disable for x in filetypes ])
def _PathToCompletersFolder():
dir_of_current_script = os.path.dirname( os.path.abspath( __file__ ) )
return os.path.join( dir_of_current_script, 'completers' )
def _PathToFiletypeCompleterPluginLoader( filetype ):
return os.path.join( _PathToCompletersFolder(), filetype, 'hook.py' )
def _BuildRequestData( start_column = None, query = None ):
line, column = vimsupport.CurrentLineAndColumn()
request_data = {
'filetypes': vimsupport.CurrentFiletypes(),
'line_num': line,
'column_num': column,
'start_column': start_column,
'line_value': vim.current.line,
'filepath': vim.current.buffer.name,
'file_data': vimsupport.GetUnsavedAndCurrentBufferData()
}
if query:
request_data[ 'query' ] = query
return request_data
def _ConvertCompletionDataToVimData( completion_data ):
# see :h complete-items for a description of the dictionary fields
vim_data = {
'word' : completion_data[ 'insertion_text' ],
'dup' : 1,
}
if 'menu_text' in completion_data:
vim_data[ 'abbr' ] = completion_data[ 'menu_text' ]
if 'extra_menu_info' in completion_data:
vim_data[ 'menu' ] = completion_data[ 'extra_menu_info' ]
if 'kind' in completion_data:
vim_data[ 'kind' ] = completion_data[ 'kind' ]
if 'detailed_info' in completion_data:
vim_data[ 'info' ] = completion_data[ 'detailed_info' ]
return vim_data
def _GetTagFiles():
tag_files = vim.eval( 'tagfiles()' )
current_working_directory = os.getcwd()
return [ os.path.join( current_working_directory, x ) for x in tag_files ]
def _PathToServerScript():
dir_of_current_script = os.path.dirname( os.path.abspath( __file__ ) )
return os.path.join( dir_of_current_script, 'server/server.py' )