Auto merge of #2707 - micbou:fix-omnifunc-cursor-move, r=bstaletic
[READY] Restore cursor position after omnifunc call When compiled without C-family support, YCM will use the default omnifunc from Vim (`ccomplete#Complete`) to provide semantic completion. This omnifunc calls [`searchdecl`](http://vimdoc.sourceforge.net/htmldoc/eval.html#searchdecl()) to find a declaration, which is supposed to move the cursor to that declaration. However, the cursor is not moved when called through the omni completion mapping (`CTRL-X CTRL-O`). Since PR https://github.com/Valloric/YouCompleteMe/pull/2657, YCM calls the omnifunc outside completion mode and thus the cursor is moved to the found declaration after typing `.` or `->`. Considering this `searchdecl` trick may be used by other omnifuncs, we fix the issue by always restoring the cursor position after calling the omnifunc. Fixes #2698. <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/valloric/youcompleteme/2707) <!-- Reviewable:end -->
This commit is contained in:
commit
d299f9eb70
@ -90,13 +90,22 @@ class OmniCompleter( Completer ):
|
|||||||
# because it affects the value returned by 'query'
|
# because it affects the value returned by 'query'
|
||||||
request_data[ 'start_column' ] = return_value + 1
|
request_data[ 'start_column' ] = return_value + 1
|
||||||
|
|
||||||
|
# Calling directly the omnifunc may move the cursor position. This is the
|
||||||
|
# case with the default Vim omnifunc for C-family languages
|
||||||
|
# (ccomplete#Complete) which calls searchdecl to find a declaration. This
|
||||||
|
# function is supposed to move the cursor to the found declaration but it
|
||||||
|
# doesn't when called through the omni completion mapping (CTRL-X CTRL-O).
|
||||||
|
# So, we restore the cursor position after calling the omnifunc.
|
||||||
|
line, column = vimsupport.CurrentLineAndColumn()
|
||||||
|
|
||||||
omnifunc_call = [ self._omnifunc,
|
omnifunc_call = [ self._omnifunc,
|
||||||
"(0,'",
|
"(0,'",
|
||||||
vimsupport.EscapeForVim( request_data[ 'query' ] ),
|
vimsupport.EscapeForVim( request_data[ 'query' ] ),
|
||||||
"')" ]
|
"')" ]
|
||||||
|
|
||||||
items = vim.eval( ''.join( omnifunc_call ) )
|
items = vim.eval( ''.join( omnifunc_call ) )
|
||||||
|
|
||||||
|
vimsupport.SetCurrentLineAndColumn( line, column )
|
||||||
|
|
||||||
if isinstance( items, dict ) and 'words' in items:
|
if isinstance( items, dict ) and 'words' in items:
|
||||||
items = items[ 'words' ]
|
items = items[ 'words' ]
|
||||||
|
|
||||||
|
@ -30,6 +30,7 @@ from ycm.tests.test_utils import ( ExpectedFailure, MockVimBuffers,
|
|||||||
MockVimModule, ToBytesOnPY2, VimBuffer )
|
MockVimModule, ToBytesOnPY2, VimBuffer )
|
||||||
MockVimModule()
|
MockVimModule()
|
||||||
|
|
||||||
|
from ycm import vimsupport
|
||||||
from ycm.tests import YouCompleteMeInstance
|
from ycm.tests import YouCompleteMeInstance
|
||||||
|
|
||||||
|
|
||||||
@ -621,3 +622,39 @@ def OmniCompleter_GetCompletions_Cache_ObjectListObject_Unicode_test( ycm ):
|
|||||||
'completion_start_column': 13
|
'completion_start_column': 13
|
||||||
} )
|
} )
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@YouCompleteMeInstance( { 'cache_omnifunc': 1 } )
|
||||||
|
def OmniCompleter_GetCompletions_RestoreCursorPositionAfterOmnifuncCall_test(
|
||||||
|
ycm ):
|
||||||
|
|
||||||
|
# This omnifunc moves the cursor to the test definition like
|
||||||
|
# ccomplete#Complete would.
|
||||||
|
def Omnifunc( findstart, base ):
|
||||||
|
if findstart:
|
||||||
|
return 5
|
||||||
|
vimsupport.SetCurrentLineAndColumn( 0, 0 )
|
||||||
|
return [ 'length' ]
|
||||||
|
|
||||||
|
current_buffer = VimBuffer( 'buffer',
|
||||||
|
contents = [ 'String test',
|
||||||
|
'',
|
||||||
|
'test.' ],
|
||||||
|
filetype = 'java',
|
||||||
|
omnifunc = Omnifunc )
|
||||||
|
|
||||||
|
with MockVimBuffers( [ current_buffer ], current_buffer, ( 3, 5 ) ):
|
||||||
|
# Make sure there is an omnifunc set up.
|
||||||
|
ycm.OnFileReadyToParse()
|
||||||
|
ycm.SendCompletionRequest()
|
||||||
|
assert_that(
|
||||||
|
vimsupport.CurrentLineAndColumn(),
|
||||||
|
contains( 2, 5 )
|
||||||
|
)
|
||||||
|
assert_that(
|
||||||
|
ycm.GetCompletionResponse(),
|
||||||
|
has_entries( {
|
||||||
|
'completions': ToBytesOnPY2( [ 'length' ] ),
|
||||||
|
'completion_start_column': 6
|
||||||
|
} )
|
||||||
|
)
|
||||||
|
@ -56,6 +56,12 @@ def CurrentLineAndColumn():
|
|||||||
return line, column
|
return line, column
|
||||||
|
|
||||||
|
|
||||||
|
def SetCurrentLineAndColumn( line, column ):
|
||||||
|
"""Sets the cursor position to the 0-based line and 0-based column."""
|
||||||
|
# Line from vim.current.window.cursor is 1-based.
|
||||||
|
vim.current.window.cursor = ( line + 1, column )
|
||||||
|
|
||||||
|
|
||||||
def CurrentColumn():
|
def CurrentColumn():
|
||||||
"""Returns the 0-based current column. Do NOT access the CurrentColumn in
|
"""Returns the 0-based current column. Do NOT access the CurrentColumn in
|
||||||
vim.current.line. It doesn't exist yet when the cursor is at the end of the
|
vim.current.line. It doesn't exist yet when the cursor is at the end of the
|
||||||
|
Loading…
x
Reference in New Issue
Block a user