Auto merge of #3091 - micbou:completer-command-mods, r=Valloric

[READY] Support modifiers for GoTo commands

This PR allows users to customize how a window is split when running the `GoTo*` commands by prefixing them with the modifiers `:aboveleft`, `:belowright`, `:botright`, etc. (see `:h mods` for the complete list). For instance, to split a window vertically at the right of the screen, one could do:
```viml
:botright vertical YcmCompleter GoTo
```
The `'horizontal-split'` and `'vertical-split'` values of the `g:ycm_goto_buffer_command` option are replaced by `'split'` since a vertical split can be obtained by prefixing the `:vertical` modifier. Those values are still kept for backward compatibility.

A new value is added `'split-or-existing-window'` that is equivalent to `new-or-existing-tab` when the `:tab` modifier is used. Without the `:tab` modifier, the `GoTo*` commands only jump to an existing window if that window is in the current tab page.

Closes https://github.com/Valloric/YouCompleteMe/pull/3090.

<!-- 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/3091)
<!-- Reviewable:end -->
This commit is contained in:
zzbot 2018-07-25 13:46:18 -07:00 committed by GitHub
commit 1e9c59abfa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 242 additions and 74 deletions

View File

@ -2896,13 +2896,30 @@ let g:ycm_use_ultisnips_completer = 1
### The `g:ycm_goto_buffer_command` option
Defines where `GoTo*` commands result should be opened.
Can take one of the following values:
`[ 'same-buffer', 'horizontal-split', 'vertical-split', 'new-tab',
'new-or-existing-tab' ]`
Defines where `GoTo*` commands result should be opened. Can take one of the
following values:
`[ 'same-buffer', 'split', 'split-or-existing-window' ]`
If this option is set to the `'same-buffer'` but current buffer can not
be switched (when buffer is modified and `nohidden` option is set),
then result will be opened in horizontal split.
then result will be opened in a split. When the option is set to
`'split-or-existing-window'`, if the result is already open in a window of the
current tab page (or any tab pages with the `:tab` modifier; see below), it
will jump to that window. Otherwise, the result will be opened in a split as if
the option was set to `'split'`.
To customize the way a new window is split, prefix the `GoTo*` command with one
of the following modifiers: `:aboveleft`, `:belowright`, `:botright`,
`:leftabove`, `:rightbelow`, `:topleft`, and `:vertical`. For instance, to
split vertically to the right of the current window, run the command:
```viml
:rightbelow vertical YcmCompleter GoTo
```
To open in a new tab page, use the `:tab` modifier with the `'split'` or
`'split-or-existing-window'` options e.g.:
```viml
:tab YcmCompleter GoTo
```
Default: `'same-buffer'`

View File

@ -845,7 +845,8 @@ function! s:SetUpCommands()
command! -nargs=* -complete=custom,youcompleteme#LogsComplete
\ YcmToggleLogs call s:ToggleLogs(<f-args>)
command! -nargs=* -complete=custom,youcompleteme#SubCommandsComplete -range
\ YcmCompleter call s:CompleterCommand(<count>,
\ YcmCompleter call s:CompleterCommand(<q-mods>,
\ <count>,
\ <line1>,
\ <line2>,
\ <f-args>)
@ -889,7 +890,7 @@ function! youcompleteme#LogsComplete( arglead, cmdline, cursorpos )
endfunction
function! s:CompleterCommand( count, line1, line2, ... )
function! s:CompleterCommand( mods, count, line1, line2, ... )
" CompleterCommand will call the OnUserCommand function of a completer. If
" the first arguments is of the form "ft=..." it can be used to specify the
" completer to use (for example "ft=cpp"). Else the native filetype completer
@ -910,6 +911,7 @@ function! s:CompleterCommand( count, line1, line2, ... )
exec s:python_command "ycm_state.SendCommandRequest(" .
\ "vim.eval( 'l:arguments' )," .
\ "vim.eval( 'l:completer' )," .
\ "vim.eval( 'a:mods' )," .
\ "vimsupport.GetBoolValue( 'a:count != -1' )," .
\ "vimsupport.GetIntValue( 'a:line1' )," .
\ "vimsupport.GetIntValue( 'a:line2' ) )"

View File

@ -3133,11 +3133,27 @@ Default: '1'
The *g:ycm_goto_buffer_command* option
Defines where 'GoTo*' commands result should be opened. Can take one of the
following values: "[ 'same-buffer', 'horizontal-split', 'vertical-split', 'new-
tab', 'new-or-existing-tab' ]" If this option is set to the "'same-buffer'" but
current buffer can not be switched (when buffer is modified and 'nohidden'
option is set), then result will be opened in horizontal split.
following values: "[ 'same-buffer', 'split', 'split-or-existing-window' ]" If
this option is set to the "'same-buffer'" but current buffer can not be
switched (when buffer is modified and 'nohidden' option is set), then result
will be opened in a split. When the option is set to "'split-or-existing-
window'", if the result is already open in a window of the current tab page (or
any tab pages with the ':tab' modifier; see below), it will jump to that
window. Otherwise, the result will be opened in a split as if the option was
set to "'split'".
To customize the way a new window is split, prefix the 'GoTo*' command with one
of the following modifiers: ':aboveleft', ':belowright', ':botright',
':leftabove', ':rightbelow', ':topleft', and ':vertical'. For instance, to
split vertically to the right of the current window, run the command:
>
:rightbelow vertical YcmCompleter GoTo
<
To open in a new tab page, use the ':tab' modifier with the "'split'" or
"'split-or-existing-window'" options e.g.:
>
:tab YcmCompleter GoTo
<
Default: "'same-buffer'"
>
let g:ycm_goto_buffer_command = 'same-buffer'

View File

@ -60,7 +60,7 @@ class CommandRequest( BaseRequest ):
return self._response
def RunPostCommandActionsIfNeeded( self ):
def RunPostCommandActionsIfNeeded( self, modifiers ):
if not self.Done() or self._response is None:
return
@ -82,10 +82,10 @@ class CommandRequest( BaseRequest ):
# The only other type of response we understand is GoTo, and that is the
# only one that we can't detect just by inspecting the response (it should
# either be a single location or a list)
return self._HandleGotoResponse()
return self._HandleGotoResponse( modifiers )
def _HandleGotoResponse( self ):
def _HandleGotoResponse( self, modifiers ):
if isinstance( self._response, list ):
vimsupport.SetQuickFixList(
[ _BuildQfListItem( x ) for x in self._response ] )
@ -93,7 +93,8 @@ class CommandRequest( BaseRequest ):
else:
vimsupport.JumpToLocation( self._response[ 'filepath' ],
self._response[ 'line_num' ],
self._response[ 'column_num' ] )
self._response[ 'column_num' ],
modifiers )
def _HandleFixitResponse( self ):
@ -131,11 +132,11 @@ class CommandRequest( BaseRequest ):
vimsupport.WriteToPreviewWindow( self._response[ 'detailed_info' ] )
def SendCommandRequest( arguments, completer, extra_data = None ):
def SendCommandRequest( arguments, completer, modifiers, extra_data = None ):
request = CommandRequest( arguments, completer, extra_data )
# This is a blocking call.
request.Start()
request.RunPostCommandActionsIfNeeded()
request.RunPostCommandActionsIfNeeded( modifiers )
return request.Response()

View File

@ -100,7 +100,7 @@ class GoToResponse_QuickFix_test( object ):
variable_exists ):
self._request._response = completer_response
self._request.RunPostCommandActionsIfNeeded()
self._request.RunPostCommandActionsIfNeeded( 'aboveleft' )
vim_eval.assert_has_exact_calls( [
call( 'setqflist( {0} )'.format( json.dumps( expected_qf_list ) ) )
@ -120,7 +120,7 @@ class Response_Detection_test( object ):
with patch( 'vim.command' ) as vim_command:
request = CommandRequest( [ command ] )
request._response = response
request.RunPostCommandActionsIfNeeded()
request.RunPostCommandActionsIfNeeded( 'belowright' )
vim_command.assert_called_with( "echo '{0}'".format( response ) )
tests = [
@ -144,7 +144,7 @@ class Response_Detection_test( object ):
request._response = {
'fixits': []
}
request.RunPostCommandActionsIfNeeded()
request.RunPostCommandActionsIfNeeded( 'botright' )
post_vim_message.assert_called_with(
'No fixits found for current line', warning = False )
@ -163,7 +163,7 @@ class Response_Detection_test( object ):
return_value = selection ):
request = CommandRequest( [ command ] )
request._response = response
request.RunPostCommandActionsIfNeeded()
request.RunPostCommandActionsIfNeeded( 'leftabove' )
replace_chunks.assert_called_with( chunks, silent = silent )
post_vim_message.assert_not_called()
@ -222,7 +222,7 @@ class Response_Detection_test( object ):
with patch( 'ycm.vimsupport.PostVimMessage' ) as post_vim_message:
request = CommandRequest( [ command ] )
request._response = { 'message': message }
request.RunPostCommandActionsIfNeeded()
request.RunPostCommandActionsIfNeeded( 'rightbelow' )
post_vim_message.assert_called_with( message, warning = False )
tests = [
@ -243,7 +243,7 @@ class Response_Detection_test( object ):
with patch( 'ycm.vimsupport.WriteToPreviewWindow' ) as write_to_preview:
request = CommandRequest( [ command ] )
request._response = { 'detailed_info': info }
request.RunPostCommandActionsIfNeeded()
request.RunPostCommandActionsIfNeeded( 'topleft' )
write_to_preview.assert_called_with( info )
tests = [
@ -263,11 +263,12 @@ class Response_Detection_test( object ):
with patch( 'ycm.vimsupport.JumpToLocation' ) as jump_to_location:
request = CommandRequest( [ command ] )
request._response = response
request.RunPostCommandActionsIfNeeded()
request.RunPostCommandActionsIfNeeded( 'rightbelow' )
jump_to_location.assert_called_with(
response[ 'filepath' ],
response[ 'line_num' ],
response[ 'column_num' ] )
response[ 'column_num' ],
'rightbelow' )
def GoToListTest( command, response ):
# Note: the detail of these called are tested by
@ -277,7 +278,7 @@ class Response_Detection_test( object ):
with patch( 'ycm.vimsupport.OpenQuickFixList' ) as open_qf_list:
request = CommandRequest( [ command ] )
request._response = response
request.RunPostCommandActionsIfNeeded()
request.RunPostCommandActionsIfNeeded( 'tab' )
ok_( set_qf_list.called )
ok_( open_qf_list.called )

View File

@ -36,13 +36,14 @@ def SendCommandRequest_ExtraConfVimData_Works_test( ycm ):
current_buffer = VimBuffer( 'buffer' )
with MockVimBuffers( [ current_buffer ], [ current_buffer ] ):
with patch( 'ycm.youcompleteme.SendCommandRequest' ) as send_request:
ycm.SendCommandRequest( [ 'GoTo' ], 'python', False, 1, 1 )
ycm.SendCommandRequest( [ 'GoTo' ], 'python', 'aboveleft', False, 1, 1 )
assert_that(
# Positional arguments passed to SendCommandRequest.
send_request.call_args[ 0 ],
contains(
contains( 'GoTo' ),
'python',
'aboveleft',
has_entries( {
'options': has_entries( {
'tab_size': 2,
@ -61,13 +62,14 @@ def SendCommandRequest_ExtraConfData_UndefinedValue_test( ycm ):
current_buffer = VimBuffer( 'buffer' )
with MockVimBuffers( [ current_buffer ], [ current_buffer ] ):
with patch( 'ycm.youcompleteme.SendCommandRequest' ) as send_request:
ycm.SendCommandRequest( [ 'GoTo' ], 'python', False, 1, 1 )
ycm.SendCommandRequest( [ 'GoTo' ], 'python', 'belowright', False, 1, 1 )
assert_that(
# Positional arguments passed to SendCommandRequest.
send_request.call_args[ 0 ],
contains(
contains( 'GoTo' ),
'python',
'belowright',
has_entries( {
'options': has_entries( {
'tab_size': 2,
@ -84,10 +86,11 @@ def SendCommandRequest_BuildRange_NoVisualMarks_test( ycm, *args ):
'second line' ] )
with MockVimBuffers( [ current_buffer ], [ current_buffer ] ):
with patch( 'ycm.youcompleteme.SendCommandRequest' ) as send_request:
ycm.SendCommandRequest( [ 'GoTo' ], 'python', True, 1, 2 )
ycm.SendCommandRequest( [ 'GoTo' ], 'python', '', True, 1, 2 )
send_request.assert_called_once_with(
[ 'GoTo' ],
'python',
'',
{
'options': {
'tab_size': 2,
@ -116,10 +119,11 @@ def SendCommandRequest_BuildRange_VisualMarks_test( ycm, *args ):
visual_end = [ 2, 8 ] )
with MockVimBuffers( [ current_buffer ], [ current_buffer ] ):
with patch( 'ycm.youcompleteme.SendCommandRequest' ) as send_request:
ycm.SendCommandRequest( [ 'GoTo' ], 'python', True, 1, 2 )
ycm.SendCommandRequest( [ 'GoTo' ], 'python', 'tab', True, 1, 2 )
send_request.assert_called_once_with(
[ 'GoTo' ],
'python',
'tab',
{
'options': {
'tab_size': 2,

View File

@ -1619,7 +1619,10 @@ def JumpToLocation_SameFile_SameBuffer_NoSwapFile_test( vim_command ):
# bytes on Python 2 but unicode on Python 3.
current_buffer = VimBuffer( 'uni¢𐍈d€' )
with MockVimBuffers( [ current_buffer ], [ current_buffer ] ) as vim:
vimsupport.JumpToLocation( os.path.realpath( u'uni¢𐍈d€' ), 2, 5 )
vimsupport.JumpToLocation( os.path.realpath( u'uni¢𐍈d€' ),
2,
5,
'aboveleft' )
assert_that( vim.current.window.cursor, equal_to( ( 2, 4 ) ) )
vim_command.assert_has_exact_calls( [
@ -1636,12 +1639,12 @@ def JumpToLocation_DifferentFile_SameBuffer_Unmodified_test( vim_command ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ] ) as vim:
target_name = os.path.realpath( u'different_uni¢𐍈d€' )
vimsupport.JumpToLocation( target_name, 2, 5 )
vimsupport.JumpToLocation( target_name, 2, 5, 'belowright' )
assert_that( vim.current.window.cursor, equal_to( ( 2, 4 ) ) )
vim_command.assert_has_exact_calls( [
call( 'normal! m\'' ),
call( u'keepjumps edit {0}'.format( target_name ) ),
call( u'keepjumps belowright edit {0}'.format( target_name ) ),
call( 'normal! zz' )
] )
@ -1656,12 +1659,12 @@ def JumpToLocation_DifferentFile_SameBuffer_Modified_CannotHide_test(
with MockVimBuffers( [ current_buffer ], [ current_buffer ] ) as vim:
target_name = os.path.realpath( u'different_uni¢𐍈d€' )
vimsupport.JumpToLocation( target_name, 2, 5 )
vimsupport.JumpToLocation( target_name, 2, 5, 'botright' )
assert_that( vim.current.window.cursor, equal_to( ( 2, 4 ) ) )
vim_command.assert_has_exact_calls( [
call( 'normal! m\'' ),
call( u'keepjumps split {0}'.format( target_name ) ),
call( u'keepjumps botright split {0}'.format( target_name ) ),
call( 'normal! zz' )
] )
@ -1676,12 +1679,12 @@ def JumpToLocation_DifferentFile_SameBuffer_Modified_CanHide_test(
with MockVimBuffers( [ current_buffer ], [ current_buffer ] ) as vim:
target_name = os.path.realpath( u'different_uni¢𐍈d€' )
vimsupport.JumpToLocation( target_name, 2, 5 )
vimsupport.JumpToLocation( target_name, 2, 5, 'leftabove' )
assert_that( vim.current.window.cursor, equal_to( ( 2, 4 ) ) )
vim_command.assert_has_exact_calls( [
call( 'normal! m\'' ),
call( u'keepjumps edit {0}'.format( target_name ) ),
call( u'keepjumps leftabove edit {0}'.format( target_name ) ),
call( 'normal! zz' )
] )
@ -1697,7 +1700,7 @@ def JumpToLocation_DifferentFile_SameBuffer_SwapFile_Unexpected_test(
with MockVimBuffers( [ current_buffer ], [ current_buffer ] ):
assert_that(
calling( vimsupport.JumpToLocation ).with_args(
os.path.realpath( u'different_uni¢𐍈d€' ), 2, 5 ),
os.path.realpath( u'different_uni¢𐍈d€' ), 2, 5, 'rightbelow' ),
raises( VimError, 'Unknown code' )
)
@ -1712,11 +1715,11 @@ def JumpToLocation_DifferentFile_SameBuffer_SwapFile_Quit_test( vim_command ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ] ):
target_name = os.path.realpath( u'different_uni¢𐍈d€' )
vimsupport.JumpToLocation( target_name, 2, 5 )
vimsupport.JumpToLocation( target_name, 2, 5, 'topleft' )
vim_command.assert_has_exact_calls( [
call( 'normal! m\'' ),
call( u'keepjumps edit {0}'.format( target_name ) )
call( u'keepjumps topleft edit {0}'.format( target_name ) )
] )
@ -1730,14 +1733,109 @@ def JumpToLocation_DifferentFile_SameBuffer_SwapFile_Abort_test( vim_command ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ] ):
target_name = os.path.realpath( u'different_uni¢𐍈d€' )
vimsupport.JumpToLocation( target_name, 2, 5 )
vimsupport.JumpToLocation( target_name, 2, 5, 'vertical' )
vim_command.assert_has_exact_calls( [
call( 'normal! m\'' ),
call( u'keepjumps edit {0}'.format( target_name ) )
call( u'keepjumps vertical edit {0}'.format( target_name ) )
] )
@patch( 'ycmd.user_options_store._USER_OPTIONS',
{ 'goto_buffer_command': 'split-or-existing-window' } )
@patch( 'vim.command', new_callable = ExtendedMock )
def JumpToLocation_DifferentFile_Split_CurrentTab_NotAlreadyOpened_test(
vim_command ):
current_buffer = VimBuffer( 'uni¢𐍈d€' )
current_window = MagicMock( buffer = current_buffer )
current_tab = MagicMock( windows = [ current_window ] )
with MockVimBuffers( [ current_buffer ], [ current_buffer ] ) as vim:
vim.current.tabpage = current_tab
target_name = os.path.realpath( u'different_uni¢𐍈d€' )
vimsupport.JumpToLocation( target_name, 2, 5, 'aboveleft' )
vim_command.assert_has_exact_calls( [
call( 'normal! m\'' ),
call( u'keepjumps aboveleft split {0}'.format( target_name ) ),
call( 'normal! zz' )
] )
@patch( 'ycmd.user_options_store._USER_OPTIONS',
{ 'goto_buffer_command': 'split-or-existing-window' } )
@patch( 'vim.command', new_callable = ExtendedMock )
def JumpToLocation_DifferentFile_Split_CurrentTab_AlreadyOpened_test(
vim_command ):
current_buffer = VimBuffer( 'uni¢𐍈d€' )
different_buffer = VimBuffer( 'different_uni¢𐍈d€' )
current_window = MagicMock( buffer = current_buffer )
different_window = MagicMock( buffer = different_buffer )
current_tab = MagicMock( windows = [ current_window, different_window ] )
with MockVimBuffers( [ current_buffer, different_buffer ],
[ current_buffer ] ) as vim:
vim.current.tabpage = current_tab
vimsupport.JumpToLocation( os.path.realpath( u'different_uni¢𐍈d€' ),
2, 5, 'belowright' )
assert_that( vim.current.tabpage, equal_to( current_tab ) )
assert_that( vim.current.window, equal_to( different_window ) )
assert_that( vim.current.window.cursor, equal_to( ( 2, 4 ) ) )
vim_command.assert_has_exact_calls( [
call( 'normal! m\'' ),
call( 'normal! zz' )
] )
@patch( 'ycmd.user_options_store._USER_OPTIONS',
{ 'goto_buffer_command': 'split-or-existing-window' } )
@patch( 'vim.command', new_callable = ExtendedMock )
def JumpToLocation_DifferentFile_Split_AllTabs_NotAlreadyOpened_test(
vim_command ):
current_buffer = VimBuffer( 'uni¢𐍈d€' )
with MockVimBuffers( [ current_buffer ], [ current_buffer ] ):
target_name = os.path.realpath( u'different_uni¢𐍈d€' )
vimsupport.JumpToLocation( target_name, 2, 5, 'tab' )
vim_command.assert_has_exact_calls( [
call( 'normal! m\'' ),
call( u'keepjumps tab split {0}'.format( target_name ) ),
call( 'normal! zz' )
] )
@patch( 'ycmd.user_options_store._USER_OPTIONS',
{ 'goto_buffer_command': 'split-or-existing-window' } )
@patch( 'vim.command', new_callable = ExtendedMock )
def JumpToLocation_DifferentFile_Split_AllTabs_AlreadyOpened_test(
vim_command ):
current_buffer = VimBuffer( 'uni¢𐍈d€' )
different_buffer = VimBuffer( 'different_uni¢𐍈d€' )
current_window = MagicMock( buffer = current_buffer )
different_window = MagicMock( buffer = different_buffer )
current_tab = MagicMock( windows = [ current_window, different_window ] )
with patch( 'vim.tabpages', [ current_tab ] ):
with MockVimBuffers( [ current_buffer, different_buffer ],
[ current_buffer ] ) as vim:
vimsupport.JumpToLocation( os.path.realpath( u'different_uni¢𐍈d€' ),
2, 5, 'tab' )
assert_that( vim.current.tabpage, equal_to( current_tab ) )
assert_that( vim.current.window, equal_to( different_window ) )
assert_that( vim.current.window.cursor, equal_to( ( 2, 4 ) ) )
vim_command.assert_has_exact_calls( [
call( 'normal! m\'' ),
call( 'normal! zz' )
] )
@patch( 'ycmd.user_options_store._USER_OPTIONS',
{ 'goto_buffer_command': 'new-or-existing-tab' } )
@patch( 'vim.command', new_callable = ExtendedMock )
@ -1748,11 +1846,11 @@ def JumpToLocation_DifferentFile_NewOrExistingTab_NotAlreadyOpened_test(
with MockVimBuffers( [ current_buffer ], [ current_buffer ] ):
target_name = os.path.realpath( u'different_uni¢𐍈d€' )
vimsupport.JumpToLocation( target_name, 2, 5 )
vimsupport.JumpToLocation( target_name, 2, 5, 'aboveleft vertical' )
vim_command.assert_has_exact_calls( [
call( 'normal! m\'' ),
call( u'keepjumps tabedit {0}'.format( target_name ) ),
call( u'keepjumps aboveleft vertical tabedit {0}'.format( target_name ) ),
call( 'normal! zz' )
] )
@ -1772,7 +1870,7 @@ def JumpToLocation_DifferentFile_NewOrExistingTab_AlreadyOpened_test(
with MockVimBuffers( [ current_buffer, different_buffer ],
[ current_buffer ] ) as vim:
vimsupport.JumpToLocation( os.path.realpath( u'different_uni¢𐍈d€' ),
2, 5 )
2, 5, 'belowright tab' )
assert_that( vim.current.tabpage, equal_to( current_tab ) )
assert_that( vim.current.window, equal_to( different_window ) )

View File

@ -34,6 +34,9 @@ from ycmd.utils import ( ByteOffsetToCodepointOffset, GetCurrentDirectory,
from ycmd import user_options_store
BUFFER_COMMAND_MAP = { 'same-buffer' : 'edit',
'split' : 'split',
# These commands are obsolete. :vertical or :tab should
# be used with the 'split' command instead.
'horizontal-split' : 'split',
'vertical-split' : 'vsplit',
'new-tab' : 'tabedit' }
@ -439,19 +442,25 @@ def EscapeFilepathForVimCommand( filepath ):
# Both |line| and |column| need to be 1-based
def TryJumpLocationInOpenedTab( filename, line, column ):
filepath = os.path.realpath( filename )
def TryJumpLocationInTab( tab, filename, line, column ):
for win in tab.windows:
if GetBufferFilepath( win.buffer ) == filename:
vim.current.tabpage = tab
vim.current.window = win
vim.current.window.cursor = ( line, column - 1 )
# Center the screen on the jumped-to location
vim.command( 'normal! zz' )
return True
# 'filename' is not opened in this tab page
return False
# Both |line| and |column| need to be 1-based
def TryJumpLocationInTabs( filename, line, column ):
for tab in vim.tabpages:
for win in tab.windows:
if GetBufferFilepath( win.buffer ) == filepath:
vim.current.tabpage = tab
vim.current.window = win
vim.current.window.cursor = ( line, column - 1 )
# Center the screen on the jumped-to location
vim.command( 'normal! zz' )
return True
if TryJumpLocationInTab( tab, filename, line, column ):
return True
# 'filename' is not opened in any tab pages
return False
@ -464,8 +473,30 @@ def GetVimCommand( user_command, default = 'edit' ):
return vim_command
def JumpToFile( filename, command, modifiers ):
vim_command = GetVimCommand( command )
try:
escaped_filename = EscapeFilepathForVimCommand( filename )
vim.command( 'keepjumps {} {} {}'.format( modifiers,
vim_command,
escaped_filename ) )
# When the file we are trying to jump to has a swap file
# Vim opens swap-exists-choices dialog and throws vim.error with E325 error,
# or KeyboardInterrupt after user selects one of the options.
except vim.error as e:
if 'E325' not in str( e ):
raise
# Do nothing if the target file is still not opened (user chose (Q)uit).
if filename != GetCurrentBufferFilepath():
return False
# Thrown when user chooses (A)bort in .swp message box.
except KeyboardInterrupt:
return False
return True
# Both |line| and |column| need to be 1-based
def JumpToLocation( filename, line, column ):
def JumpToLocation( filename, line, column, modifiers ):
# Add an entry to the jumplist
vim.command( "normal! m'" )
@ -478,27 +509,24 @@ def JumpToLocation( filename, line, column ):
# jumplist.
user_command = user_options_store.Value( 'goto_buffer_command' )
if user_command == 'split-or-existing-window':
if 'tab' in modifiers:
if TryJumpLocationInTabs( filename, line, column ):
return
elif TryJumpLocationInTab( vim.current.tabpage, filename, line, column ):
return
user_command = 'split'
# This command is kept for backward compatibility. :tab should be used with
# the 'split-or-existing-window' command instead.
if user_command == 'new-or-existing-tab':
if TryJumpLocationInOpenedTab( filename, line, column ):
if TryJumpLocationInTabs( filename, line, column ):
return
user_command = 'new-tab'
vim_command = GetVimCommand( user_command )
try:
escaped_filename = EscapeFilepathForVimCommand( filename )
vim.command( 'keepjumps {0} {1}'.format( vim_command, escaped_filename ) )
# When the file we are trying to jump to has a swap file
# Vim opens swap-exists-choices dialog and throws vim.error with E325 error,
# or KeyboardInterrupt after user selects one of the options.
except vim.error as e:
if 'E325' not in str( e ):
raise
# Do nothing if the target file is still not opened (user chose (Q)uit)
if filename != GetCurrentBufferFilepath():
return
# Thrown when user chooses (A)bort in .swp message box
except KeyboardInterrupt:
if not JumpToFile( filename, user_command, modifiers ):
return
vim.current.window.cursor = ( line, column - 1 )
# Center the screen on the jumped-to location

View File

@ -322,6 +322,7 @@ class YouCompleteMe( object ):
def SendCommandRequest( self,
arguments,
completer,
modifiers,
has_range,
start_line,
end_line ):
@ -334,7 +335,7 @@ class YouCompleteMe( object ):
if has_range:
extra_data.update( vimsupport.BuildRange( start_line, end_line ) )
self._AddExtraConfDataIfNeeded( extra_data )
return SendCommandRequest( arguments, completer, extra_data )
return SendCommandRequest( arguments, completer, modifiers, extra_data )
def GetDefinedSubcommands( self ):