Event and completion request are now async
This results in a much snappier Vim.
This commit is contained in:
parent
e08dd4ab33
commit
9d0a6c96d7
@ -40,6 +40,8 @@ function! youcompleteme#Enable()
|
||||
py import sys
|
||||
py import vim
|
||||
exe 'python sys.path.insert( 0, "' . s:script_folder_path . '/../python" )'
|
||||
py from ycm import utils
|
||||
py utils.AddThirdPartyFoldersToSysPath()
|
||||
py from ycm import base
|
||||
py from ycm import vimsupport
|
||||
py from ycm import user_options_store
|
||||
@ -497,13 +499,11 @@ python << EOF
|
||||
def GetCompletions( query ):
|
||||
request = ycm_state.GetCurrentCompletionRequest()
|
||||
request.Start( query )
|
||||
results_ready = False
|
||||
while not results_ready:
|
||||
results_ready = request.Done()
|
||||
while not request.Done():
|
||||
if bool( int( vim.eval( 'complete_check()' ) ) ):
|
||||
return { 'words' : [], 'refresh' : 'always'}
|
||||
|
||||
results = base.AdjustCandidateInsertionText( request.Results() )
|
||||
results = base.AdjustCandidateInsertionText( request.Response() )
|
||||
return { 'words' : results, 'refresh' : 'always' }
|
||||
EOF
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
import vim
|
||||
import json
|
||||
import requests
|
||||
from requests_futures.sessions import FuturesSession
|
||||
from ycm import vimsupport
|
||||
|
||||
HEADERS = {'content-type': 'application/json'}
|
||||
@ -46,22 +47,22 @@ class BaseRequest( object ):
|
||||
return {}
|
||||
|
||||
|
||||
# This is the blocking version of the method. See below for async.
|
||||
@staticmethod
|
||||
def PostDataToHandler( data, handler ):
|
||||
response = requests.post( _BuildUri( handler ),
|
||||
return JsonFromFuture( BaseRequest.PostDataToHandlerAsync( data,
|
||||
handler ) )
|
||||
|
||||
|
||||
# This returns a future! Use JsonFromFuture to get the value.
|
||||
@staticmethod
|
||||
def PostDataToHandlerAsync( data, handler ):
|
||||
return BaseRequest.session.post( _BuildUri( handler ),
|
||||
data = json.dumps( data ),
|
||||
headers = HEADERS )
|
||||
if response.status_code == requests.codes.server_error:
|
||||
raise ServerError( response.json()[ 'message' ] )
|
||||
|
||||
# We let Requests handle the other status types, we only handle the 500
|
||||
# error code.
|
||||
response.raise_for_status()
|
||||
|
||||
if response.text:
|
||||
return response.json()
|
||||
return None
|
||||
|
||||
session = FuturesSession( max_workers = 4 )
|
||||
server_location = 'http://localhost:6666'
|
||||
|
||||
|
||||
@ -83,6 +84,20 @@ def BuildRequestData( start_column = None, query = None ):
|
||||
return request_data
|
||||
|
||||
|
||||
def JsonFromFuture( future ):
|
||||
response = future.result()
|
||||
if response.status_code == requests.codes.server_error:
|
||||
raise ServerError( response.json()[ 'message' ] )
|
||||
|
||||
# We let Requests handle the other status types, we only handle the 500
|
||||
# error code.
|
||||
response.raise_for_status()
|
||||
|
||||
if response.text:
|
||||
return response.json()
|
||||
return None
|
||||
|
||||
|
||||
def _BuildUri( handler ):
|
||||
return ''.join( [ BaseRequest.server_location, '/', handler ] )
|
||||
|
||||
|
@ -18,7 +18,6 @@
|
||||
# along with YouCompleteMe. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import vim
|
||||
import time
|
||||
from ycm.client.base_request import BaseRequest, BuildRequestData, ServerError
|
||||
from ycm import vimsupport
|
||||
from ycm.utils import ToUtf8IfNeeded
|
||||
@ -70,10 +69,8 @@ class CommandRequest( BaseRequest ):
|
||||
|
||||
def SendCommandRequest( arguments, completer ):
|
||||
request = CommandRequest( arguments, completer )
|
||||
# This is a blocking call.
|
||||
request.Start()
|
||||
while not request.Done():
|
||||
time.sleep( 0.1 )
|
||||
|
||||
request.RunPostCommandActionsIfNeeded()
|
||||
return request.Response()
|
||||
|
||||
|
@ -19,7 +19,8 @@
|
||||
|
||||
from ycm import base
|
||||
from ycm import vimsupport
|
||||
from ycm.client.base_request import BaseRequest, BuildRequestData
|
||||
from ycm.client.base_request import ( BaseRequest, BuildRequestData,
|
||||
JsonFromFuture )
|
||||
|
||||
|
||||
class CompletionRequest( BaseRequest ):
|
||||
@ -30,27 +31,26 @@ class CompletionRequest( BaseRequest ):
|
||||
self._request_data = BuildRequestData( self._completion_start_column )
|
||||
|
||||
|
||||
# TODO: Do we need this anymore?
|
||||
# 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,
|
||||
self._response_future = self.PostDataToHandlerAsync( self._request_data,
|
||||
'get_completions' )
|
||||
|
||||
|
||||
def Results( self ):
|
||||
if not self._response:
|
||||
def Done( self ):
|
||||
return self._response_future.done()
|
||||
|
||||
|
||||
def Response( self ):
|
||||
if not self._response_future:
|
||||
return []
|
||||
try:
|
||||
return [ _ConvertCompletionDataToVimData( x ) for x in self._response ]
|
||||
return [ _ConvertCompletionDataToVimData( x )
|
||||
for x in JsonFromFuture( self._response_future ) ]
|
||||
except Exception as e:
|
||||
vimsupport.PostVimMessage( str( e ) )
|
||||
return []
|
||||
|
@ -41,7 +41,7 @@ class EventNotification( BaseRequest ):
|
||||
# quietly to the Vim message log because nothing bad will happen if the
|
||||
# server misses some events and we don't want to annoy the user.
|
||||
try:
|
||||
self.PostDataToHandler( request_data, 'event_notification' )
|
||||
self.PostDataToHandlerAsync( request_data, 'event_notification' )
|
||||
except:
|
||||
vimsupport.EchoText( traceback.format_exc() )
|
||||
|
||||
|
@ -30,6 +30,9 @@ sys.path.insert( 0, os.path.join(
|
||||
os.path.dirname( os.path.abspath( __file__ ) ),
|
||||
'../..' ) )
|
||||
|
||||
from ycm import utils
|
||||
utils.AddThirdPartyFoldersToSysPath()
|
||||
|
||||
import logging
|
||||
import json
|
||||
import bottle
|
||||
|
@ -52,3 +52,15 @@ def TerminateProcess( pid ):
|
||||
ctypes.windll.kernel32.CloseHandle( handle )
|
||||
else:
|
||||
os.kill( pid, signal.SIGTERM )
|
||||
|
||||
|
||||
def AddThirdPartyFoldersToSysPath():
|
||||
path_to_third_party = os.path.join(
|
||||
os.path.dirname( os.path.abspath( __file__ ) ),
|
||||
'../../third_party' )
|
||||
|
||||
for folder in os.listdir( path_to_third_party ):
|
||||
sys.path.insert( 0, os.path.realpath( os.path.join( path_to_third_party,
|
||||
folder ) ) )
|
||||
|
||||
|
||||
|
@ -165,6 +165,7 @@ class YouCompleteMe( object ):
|
||||
|
||||
|
||||
def OnVimLeave( self ):
|
||||
# TODO: There should be a faster way of shutting down the server
|
||||
self._server_popen.terminate()
|
||||
os.remove( self._temp_options_filename )
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user