Recompute starting column on auto-wrapping
When auto-wrapping is enabled, Vim wraps the current line after the completion request is sent but before calling the completefunc. The starting column returned by the server is invalid in that case and must be recomputed.
This commit is contained in:
parent
e412ee465b
commit
eba717553f
@ -23,11 +23,9 @@ set cpo&vim
|
|||||||
let s:script_folder_path = escape( expand( '<sfile>:p:h' ), '\' )
|
let s:script_folder_path = escape( expand( '<sfile>:p:h' ), '\' )
|
||||||
let s:force_semantic = 0
|
let s:force_semantic = 0
|
||||||
let s:completion_stopped = 0
|
let s:completion_stopped = 0
|
||||||
let s:default_completion = {
|
" These two variables are initialized in youcompleteme#Enable.
|
||||||
\ 'start_column': -1,
|
let s:default_completion = {}
|
||||||
\ 'candidates': []
|
let s:completion = {}
|
||||||
\ }
|
|
||||||
let s:completion = s:default_completion
|
|
||||||
let s:previous_allowed_buffer_number = 0
|
let s:previous_allowed_buffer_number = 0
|
||||||
let s:pollers = {
|
let s:pollers = {
|
||||||
\ 'completion': {
|
\ 'completion': {
|
||||||
@ -147,6 +145,9 @@ function! youcompleteme#Enable()
|
|||||||
let s:pollers.server_ready.id = timer_start(
|
let s:pollers.server_ready.id = timer_start(
|
||||||
\ s:pollers.server_ready.wait_milliseconds,
|
\ s:pollers.server_ready.wait_milliseconds,
|
||||||
\ function( 's:PollServerReady' ) )
|
\ function( 's:PollServerReady' ) )
|
||||||
|
|
||||||
|
let s:default_completion = s:Pyeval( 'vimsupport.NO_COMPLETIONS' )
|
||||||
|
let s:completion = s:default_completion
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
@ -811,11 +812,7 @@ function! s:PollCompletion( ... )
|
|||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let response = s:Pyeval( 'ycm_state.GetCompletionResponse()' )
|
let s:completion = s:Pyeval( 'ycm_state.GetCompletionResponse()' )
|
||||||
let s:completion = {
|
|
||||||
\ 'start_column': response.completion_start_column,
|
|
||||||
\ 'candidates': response.completions
|
|
||||||
\ }
|
|
||||||
call s:Complete()
|
call s:Complete()
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
@ -824,16 +821,17 @@ function! s:Complete()
|
|||||||
" Do not call user's completion function if the start column is after the
|
" Do not call user's completion function if the start column is after the
|
||||||
" current column or if there are no candidates. Close the completion menu
|
" current column or if there are no candidates. Close the completion menu
|
||||||
" instead. This avoids keeping the user in completion mode.
|
" instead. This avoids keeping the user in completion mode.
|
||||||
if s:completion.start_column > col( '.' ) || empty( s:completion.candidates )
|
if s:completion.completion_start_column > s:completion.column ||
|
||||||
|
\ empty( s:completion.completions )
|
||||||
call s:CloseCompletionMenu()
|
call s:CloseCompletionMenu()
|
||||||
else
|
else
|
||||||
" <c-x><c-u> invokes the user's completion function (which we have set to
|
" <c-x><c-u> invokes the user's completion function (which we have set to
|
||||||
" youcompleteme#CompleteFunc), and <c-p> tells Vim to select the previous
|
" youcompleteme#CompleteFunc), and <c-p> tells Vim to select the previous
|
||||||
" completion candidate. This is necessary because by default, Vim selects the
|
" completion candidate. This is necessary because by default, Vim selects
|
||||||
" first candidate when completion is invoked, and selecting a candidate
|
" the first candidate when completion is invoked, and selecting a candidate
|
||||||
" automatically replaces the current text with it. Calling <c-p> forces Vim to
|
" automatically replaces the current text with it. Calling <c-p> forces Vim
|
||||||
" deselect the first candidate and in turn preserve the user's current text
|
" to deselect the first candidate and in turn preserve the user's current
|
||||||
" until he explicitly chooses to replace it with a completion.
|
" text until he explicitly chooses to replace it with a completion.
|
||||||
call s:SendKeys( "\<C-X>\<C-U>\<C-P>" )
|
call s:SendKeys( "\<C-X>\<C-U>\<C-P>" )
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
@ -841,9 +839,25 @@ endfunction
|
|||||||
|
|
||||||
function! youcompleteme#CompleteFunc( findstart, base )
|
function! youcompleteme#CompleteFunc( findstart, base )
|
||||||
if a:findstart
|
if a:findstart
|
||||||
return s:completion.start_column - 1
|
" When auto-wrapping is enabled, Vim wraps the current line after the
|
||||||
|
" completion request is sent but before calling this function. The starting
|
||||||
|
" column returned by the server is invalid in that case and must be
|
||||||
|
" recomputed.
|
||||||
|
if s:completion.line != line( '.' )
|
||||||
|
" Given
|
||||||
|
" scb: column where the completion starts before auto-wrapping
|
||||||
|
" cb: cursor column before auto-wrapping
|
||||||
|
" sca: column where the completion starts after auto-wrapping
|
||||||
|
" ca: cursor column after auto-wrapping
|
||||||
|
" we have
|
||||||
|
" ca - sca = cb - scb
|
||||||
|
" sca = scb + ca - cb
|
||||||
|
let s:completion.completion_start_column +=
|
||||||
|
\ col( '.' ) - s:completion.column
|
||||||
endif
|
endif
|
||||||
return s:completion.candidates
|
return s:completion.completion_start_column - 1
|
||||||
|
endif
|
||||||
|
return s:completion.completions
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ from ycmd.utils import ToUnicode
|
|||||||
from ycm.client.base_request import ( BaseRequest, DisplayServerException,
|
from ycm.client.base_request import ( BaseRequest, DisplayServerException,
|
||||||
MakeServerException )
|
MakeServerException )
|
||||||
from ycm import vimsupport
|
from ycm import vimsupport
|
||||||
|
from ycm.vimsupport import NO_COMPLETIONS
|
||||||
|
|
||||||
_logger = logging.getLogger( __name__ )
|
_logger = logging.getLogger( __name__ )
|
||||||
|
|
||||||
@ -56,12 +57,12 @@ class CompletionRequest( BaseRequest ):
|
|||||||
|
|
||||||
def RawResponse( self ):
|
def RawResponse( self ):
|
||||||
if not self._response_future:
|
if not self._response_future:
|
||||||
return { 'completions': [], 'completion_start_column': -1 }
|
return NO_COMPLETIONS
|
||||||
|
|
||||||
response = self.HandleFuture( self._response_future,
|
response = self.HandleFuture( self._response_future,
|
||||||
truncate_message = True )
|
truncate_message = True )
|
||||||
if not response:
|
if not response:
|
||||||
return { 'completions': [], 'completion_start_column': -1 }
|
return NO_COMPLETIONS
|
||||||
|
|
||||||
# Vim may not be able to convert the 'errors' entry to its internal format
|
# Vim may not be able to convert the 'errors' entry to its internal format
|
||||||
# so we remove it from the response.
|
# so we remove it from the response.
|
||||||
@ -71,6 +72,8 @@ class CompletionRequest( BaseRequest ):
|
|||||||
_logger.error( exception )
|
_logger.error( exception )
|
||||||
DisplayServerException( exception, truncate_message = True )
|
DisplayServerException( exception, truncate_message = True )
|
||||||
|
|
||||||
|
response[ 'line' ] = self.request_data[ 'line_num' ]
|
||||||
|
response[ 'column' ] = self.request_data[ 'column_num' ]
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@ -41,15 +41,19 @@ class OmniCompletionRequest( CompletionRequest ):
|
|||||||
|
|
||||||
def RawResponse( self ):
|
def RawResponse( self ):
|
||||||
return {
|
return {
|
||||||
'completions': _ConvertVimDatasToCompletionDatas( self._results ),
|
'line': self.request_data[ 'line_num' ],
|
||||||
'completion_start_column': self.request_data[ 'start_column' ]
|
'column': self.request_data[ 'column_num' ],
|
||||||
|
'completion_start_column': self.request_data[ 'start_column' ],
|
||||||
|
'completions': _ConvertVimDatasToCompletionDatas( self._results )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def Response( self ):
|
def Response( self ):
|
||||||
return {
|
return {
|
||||||
'completions': self._results,
|
'line': self.request_data[ 'line_num' ],
|
||||||
'completion_start_column': self.request_data[ 'start_column' ]
|
'column': self.request_data[ 'column_num' ],
|
||||||
|
'completion_start_column': self.request_data[ 'start_column' ],
|
||||||
|
'completions': self._results
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -34,6 +34,8 @@ def BuildOmnicompletionRequest( results, start_column = 1 ):
|
|||||||
omni_completer.ComputeCandidates = MagicMock( return_value = results )
|
omni_completer.ComputeCandidates = MagicMock( return_value = results )
|
||||||
|
|
||||||
request_data = {
|
request_data = {
|
||||||
|
'line_num': 1,
|
||||||
|
'column_num': 1,
|
||||||
'start_column': start_column
|
'start_column': start_column
|
||||||
}
|
}
|
||||||
request = OmniCompletionRequest( omni_completer, request_data )
|
request = OmniCompletionRequest( omni_completer, request_data )
|
||||||
@ -53,8 +55,10 @@ def Response_FromOmniCompleter_test():
|
|||||||
request = BuildOmnicompletionRequest( results )
|
request = BuildOmnicompletionRequest( results )
|
||||||
|
|
||||||
eq_( request.Response(), {
|
eq_( request.Response(), {
|
||||||
'completions': results,
|
'line': 1,
|
||||||
'completion_start_column': 1
|
'column': 1,
|
||||||
|
'completion_start_column': 1,
|
||||||
|
'completions': results
|
||||||
} )
|
} )
|
||||||
|
|
||||||
|
|
||||||
|
@ -59,6 +59,13 @@ SIGN_ID_FOR_BUFFER = defaultdict( lambda: SIGN_BUFFER_ID_INITIAL_VALUE )
|
|||||||
SIGN_PLACE_REGEX = re.compile(
|
SIGN_PLACE_REGEX = re.compile(
|
||||||
r"^.*=(?P<line>\d+).*=(?P<id>\d+).*=(?P<name>Ycm\w+)$" )
|
r"^.*=(?P<line>\d+).*=(?P<id>\d+).*=(?P<name>Ycm\w+)$" )
|
||||||
|
|
||||||
|
NO_COMPLETIONS = {
|
||||||
|
'line': -1,
|
||||||
|
'column': -1,
|
||||||
|
'completion_start_column': -1,
|
||||||
|
'completions': []
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def CurrentLineAndColumn():
|
def CurrentLineAndColumn():
|
||||||
"""Returns the 0-based current line and 0-based current column."""
|
"""Returns the 0-based current line and 0-based current column."""
|
||||||
|
Loading…
Reference in New Issue
Block a user