Auto merge of #2190 - micbou:goto-set-quickfix-list, r=Valloric
[READY] Use SetQuickFixList function for GoTo* subcommands From discussion in PR #2101, we reuse the `SetQuickFixList` function for the `GoTo*` subcommands. This automatically makes the quickfix window height equal to the number of locations. Unfortunately, there is no Vim option to change the default height (10) of the quickfix window so we can't really use the heuristic `min(number of Locations, default height)` because users would not be able to change the default height (and we don't want to add another option). However, there are still solutions to set a default height. For instance, a user could add the following line in its vimrc: ```viml autocmd FileType qf exe "20wincmd _" ``` to set the default height to 20. This will override YCM behavior. I didn't reproduce the `lazyredraw` boilerplate from `youcompleteme#OpenGoToList`. I guess it was used to avoid flickering but I didn't experienced any without it. In addition, it was not properly implemented because the `lazyredraw` state was not preserved if the option was already set. I also threw away the `cclose` command. It resets the quickfix window to its default position if already opened, which I think is not a desirable behavior. Closes #2101. <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="35" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/valloric/youcompleteme/2190) <!-- Reviewable:end -->
This commit is contained in:
commit
871387bd2a
31
README.md
31
README.md
@ -33,6 +33,7 @@ YouCompleteMe: a code-completion engine for Vim
|
||||
- [Refactoring and FixIt Commands](#refactoring-and-fixit-commands)
|
||||
- [Miscellaneous Commands](#miscellaneous-commands)
|
||||
- [Functions](#functions)
|
||||
- [Autocommands](#autocommands)
|
||||
- [Options](#options)
|
||||
- [FAQ](#faq)
|
||||
- [Contributor Code of Conduct](#contributor-code-of-conduct)
|
||||
@ -1178,7 +1179,11 @@ maps the `<leader>jd` sequence to the longer subcommand invocation.
|
||||
These commands are useful for jumping around and exploring code. When moving
|
||||
the cursor, the subcommands add entries to Vim's `jumplist` so you can use
|
||||
`CTRL-O` to jump back to where you where before invoking the command (and
|
||||
`CTRL-I` to jump forward; see `:h jumplist` for details).
|
||||
`CTRL-I` to jump forward; see `:h jumplist` for details). If there is more
|
||||
than one destination, the quickfix list (see `:h quickfix`) is populated with
|
||||
the available locations and opened to full width at the bottom of the screen.
|
||||
You can change this behavior by using [the `YcmQuickFixOpened`
|
||||
autocommand](#the-ycmquickfixopened-autocommand).
|
||||
|
||||
#### The `GoToInclude` subcommand
|
||||
|
||||
@ -1399,7 +1404,9 @@ you that this is about to happen.
|
||||
Once the modifications have been made, the quickfix list (see `:help quickfix`)
|
||||
is opened and populated with the locations of all modifications. This can be
|
||||
used to review all automatic changes made. Typically, use the `CTRL-W
|
||||
<enter>` combination to open the selected file in a new split.
|
||||
<enter>` combination to open the selected file in a new split. It is possible
|
||||
to customize how the quickfix window is opened by using [the `YcmQuickFixOpened`
|
||||
autocommand](#the-ycmquickfixopened-autocommand).
|
||||
|
||||
The buffers are *not* saved automatically. That is, you must save the modified
|
||||
buffers manually after reviewing the changes from the quickfix list. Changes
|
||||
@ -1496,6 +1503,26 @@ For example:
|
||||
call youcompleteme#GetWarningCount()
|
||||
```
|
||||
|
||||
Autocommands
|
||||
------------
|
||||
|
||||
### The `YcmQuickFixOpened` autocommand
|
||||
|
||||
This `User` autocommand is fired when YCM opens the quickfix window in response
|
||||
to the `GoTo*` and `RefactorRename` subcommands. By default, the quickfix window
|
||||
is opened to full width at the bottom of the screen and its height is set to fit
|
||||
all entries. This behavior can be overridden by using the `YcmQuickFixOpened`
|
||||
autocommand. For instance:
|
||||
```viml
|
||||
function s:CustomizeYcmQuickFixWindow()
|
||||
" Move the window at the top of the screen.
|
||||
execute "wincmd K"
|
||||
" Set the window height to 5.
|
||||
execute "5wincmd _"
|
||||
endfunction
|
||||
|
||||
autocmd User YcmQuickFixOpened call s:CustomizeYcmQuickFixWindow()
|
||||
```
|
||||
|
||||
Options
|
||||
-------
|
||||
|
@ -826,12 +826,10 @@ endfunction
|
||||
|
||||
|
||||
function! youcompleteme#OpenGoToList()
|
||||
set lazyredraw
|
||||
cclose
|
||||
execute 'belowright copen 3'
|
||||
set nolazyredraw
|
||||
au WinLeave <buffer> q " automatically leave, if an option is chosen
|
||||
redraw!
|
||||
exec s:python_command "vimsupport.PostVimMessage("
|
||||
\ "'WARNING: youcompleteme#OpenGoToList function is deprecated."
|
||||
\ "Do NOT use it.')"
|
||||
exec s:python_command "vimsupport.OpenQuickFixList( True, True )"
|
||||
endfunction
|
||||
|
||||
|
||||
|
@ -74,7 +74,9 @@ Contents ~
|
||||
8. Functions |youcompleteme-functions|
|
||||
1. The |youcompleteme#GetErrorCount| function
|
||||
2. The |youcompleteme#GetWarningCount| function
|
||||
9. Options |youcompleteme-options|
|
||||
9. Autocommands |youcompleteme-autocommands|
|
||||
1. The |YcmQuickFixOpened| autocommand
|
||||
10. Options |youcompleteme-options|
|
||||
1. The |g:ycm_min_num_of_chars_for_completion| option
|
||||
2. The |g:ycm_min_num_identifier_candidate_chars| option
|
||||
3. The |g:ycm_auto_trigger| option
|
||||
@ -121,7 +123,7 @@ Contents ~
|
||||
44. The |g:ycm_goto_buffer_command| option
|
||||
45. The |g:ycm_disable_for_files_larger_than_kb| option
|
||||
46. The |g:ycm_python_binary_path| option
|
||||
10. FAQ |youcompleteme-faq|
|
||||
11. FAQ |youcompleteme-faq|
|
||||
1. I used to be able to 'import vim' in '.ycm_extra_conf.py', but now can't |import-vim|
|
||||
2. On very rare occasions Vim crashes when I tab through the completion menu |youcompleteme-on-very-rare-occasions-vim-crashes-when-i-tab-through-completion-menu|
|
||||
3. I get |ImportError| exceptions that mention 'PyInit_ycm_core' or 'initycm_core'
|
||||
@ -139,7 +141,7 @@ Contents ~
|
||||
15. I get 'libpython2.7.a [...] relocation R_X86_64_32' when compiling |libpython2.7.a-...-relocation-R_X86_64_32|
|
||||
16. I get 'Vim: Caught deadly signal SEGV' on Vim startup |Vim:-Caught-deadly-signal-SEGV|
|
||||
17. I get 'Fatal Python error: PyThreadState_Get: no current thread' on startup |Fatal-Python-error:-PyThreadState_Get:-no-current-thread|
|
||||
11. |install.py| says python must be compiled with '--enable-framework'. Wat?
|
||||
12. |install.py| says python must be compiled with '--enable-framework'. Wat?
|
||||
1. YCM does not read identifiers from my tags files |youcompleteme-ycm-does-not-read-identifiers-from-my-tags-files|
|
||||
2. 'CTRL-U' in insert mode does not work |CTRL-sub-U|
|
||||
3. YCM conflicts with UltiSnips TAB key usage |youcompleteme-ycm-conflicts-with-ultisnips-tab-key-usage|
|
||||
@ -160,10 +162,10 @@ attempt to load the C runtime library incorrectly.' |R6034-An-application-has-ma
|
||||
16. I hear that YCM only supports Python 2, is that true? |youcompleteme-i-hear-that-ycm-only-supports-python-2-is-that-true|
|
||||
17. On Windows I get "E887: Sorry, this command is disabled, the Python's site
|
||||
module could not be loaded" |E887:-Sorry-this-command-is-disabled-the-Python-s-site-module-could-not-be-loaded|
|
||||
12. Contributor Code of Conduct |youcompleteme-contributor-code-of-conduct|
|
||||
13. Contact |youcompleteme-contact|
|
||||
14. License |youcompleteme-license|
|
||||
15. References |youcompleteme-references|
|
||||
13. Contributor Code of Conduct |youcompleteme-contributor-code-of-conduct|
|
||||
14. Contact |youcompleteme-contact|
|
||||
15. License |youcompleteme-license|
|
||||
16. References |youcompleteme-references|
|
||||
|
||||
===============================================================================
|
||||
*youcompleteme-introduction*
|
||||
@ -208,6 +210,7 @@ Image: Build Status [1] Image: Build status [3]
|
||||
- Miscellaneous Commands
|
||||
|
||||
- Functions
|
||||
- Autocommands
|
||||
- Options
|
||||
- FAQ
|
||||
- Contributor Code of Conduct
|
||||
@ -1446,7 +1449,10 @@ GoTo Commands ~
|
||||
These commands are useful for jumping around and exploring code. When moving
|
||||
the cursor, the subcommands add entries to Vim's 'jumplist' so you can use
|
||||
'CTRL-O' to jump back to where you where before invoking the command (and
|
||||
'CTRL-I' to jump forward; see ':h jumplist' for details).
|
||||
'CTRL-I' to jump forward; see ':h jumplist' for details). If there is more than
|
||||
one destination, the quickfix list (see ':h quickfix') is populated with the
|
||||
available locations and opened to full width at the bottom of the screen. You
|
||||
can change this behavior by using the |YcmQuickFixOpened| autocommand.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
The *GoToInclude* subcommand
|
||||
@ -1683,7 +1689,9 @@ you that this is about to happen.
|
||||
Once the modifications have been made, the quickfix list (see ':help quickfix')
|
||||
is opened and populated with the locations of all modifications. This can be
|
||||
used to review all automatic changes made. Typically, use the 'CTRL-W <enter>'
|
||||
combination to open the selected file in a new split.
|
||||
combination to open the selected file in a new split. It is possible to
|
||||
customize how the quickfix window is opened by using the |YcmQuickFixOpened|
|
||||
autocommand.
|
||||
|
||||
The buffers are _not_ saved automatically. That is, you must save the modified
|
||||
buffers manually after reviewing the changes from the quickfix list. Changes
|
||||
@ -1786,6 +1794,28 @@ For example:
|
||||
>
|
||||
call youcompleteme#GetWarningCount()
|
||||
<
|
||||
===============================================================================
|
||||
*youcompleteme-autocommands*
|
||||
Autocommands ~
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
The *YcmQuickFixOpened* autocommand
|
||||
|
||||
This 'User' autocommand is fired when YCM opens the quickfix window in response
|
||||
to the 'GoTo*' and 'RefactorRename' subcommands. By default, the quickfix
|
||||
window is opened to full width at the bottom of the screen and its height is
|
||||
set to fit all entries. This behavior can be overridden by using the
|
||||
|YcmQuickFixOpened| autocommand. For instance:
|
||||
>
|
||||
function s:CustomizeYcmQuickFixWindow()
|
||||
" Move the window at the top of the screen.
|
||||
execute "wincmd K"
|
||||
" Set the window height to 5.
|
||||
execute "5wincmd _"
|
||||
endfunction
|
||||
|
||||
autocmd User YcmQuickFixOpened call s:CustomizeYcmQuickFixWindow()
|
||||
<
|
||||
===============================================================================
|
||||
*youcompleteme-options*
|
||||
Options ~
|
||||
|
@ -24,7 +24,6 @@ standard_library.install_aliases()
|
||||
from builtins import * # noqa
|
||||
|
||||
from requests.exceptions import ReadTimeout
|
||||
import vim
|
||||
|
||||
from ycmd.responses import ServerError
|
||||
from ycm.client.base_request import ( BaseRequest, BuildRequestData,
|
||||
@ -93,8 +92,9 @@ class CommandRequest( BaseRequest ):
|
||||
def _HandleGotoResponse( self ):
|
||||
if isinstance( self._response, list ):
|
||||
vimsupport.SetQuickFixList(
|
||||
[ _BuildQfListItem( x ) for x in self._response ] )
|
||||
vim.eval( 'youcompleteme#OpenGoToList()' )
|
||||
[ _BuildQfListItem( x ) for x in self._response ],
|
||||
focus = True,
|
||||
autoclose = True )
|
||||
else:
|
||||
vimsupport.JumpToLocation( self._response[ 'filepath' ],
|
||||
self._response[ 'line_num' ],
|
||||
|
@ -23,7 +23,7 @@ from future import standard_library
|
||||
standard_library.install_aliases()
|
||||
from builtins import * # noqa
|
||||
|
||||
from ycm.test_utils import MockVimModule
|
||||
from ycm.test_utils import ExtendedMock, MockVimModule
|
||||
MockVimModule()
|
||||
|
||||
import json
|
||||
@ -88,16 +88,30 @@ class GoToResponse_QuickFix_test( object ):
|
||||
} ] )
|
||||
|
||||
|
||||
@patch( 'vim.eval' )
|
||||
def _CheckGoToList( self, completer_response, expected_qf_list, vim_eval ):
|
||||
@patch( 'ycm.vimsupport.VariableExists', return_value = True )
|
||||
@patch( 'ycm.vimsupport.SetFittingHeightForCurrentWindow' )
|
||||
@patch( 'vim.command', new_callable = ExtendedMock )
|
||||
@patch( 'vim.eval', new_callable = ExtendedMock )
|
||||
def _CheckGoToList( self,
|
||||
completer_response,
|
||||
expected_qf_list,
|
||||
vim_eval,
|
||||
vim_command,
|
||||
set_fitting_height,
|
||||
variable_exists ):
|
||||
self._request._response = completer_response
|
||||
|
||||
self._request.RunPostCommandActionsIfNeeded()
|
||||
|
||||
vim_eval.assert_has_calls( [
|
||||
call( 'setqflist( {0} )'.format( json.dumps( expected_qf_list ) ) ),
|
||||
call( 'youcompleteme#OpenGoToList()' ),
|
||||
vim_eval.assert_has_exact_calls( [
|
||||
call( 'setqflist( {0} )'.format( json.dumps( expected_qf_list ) ) )
|
||||
] )
|
||||
vim_command.assert_has_exact_calls( [
|
||||
call( 'botright copen' ),
|
||||
call( 'au WinLeave <buffer> q' ),
|
||||
call( 'doautocmd User YcmQuickFixOpened' )
|
||||
] )
|
||||
set_fitting_height.assert_called_once_with()
|
||||
|
||||
|
||||
class Response_Detection_test( object ):
|
||||
@ -244,12 +258,10 @@ class Response_Detection_test( object ):
|
||||
# GoToResponse_QuickFix_test, so here we just check that the right call is
|
||||
# made
|
||||
with patch( 'ycm.vimsupport.SetQuickFixList' ) as set_qf_list:
|
||||
with patch( 'vim.eval' ) as vim_eval:
|
||||
request = CommandRequest( [ command ] )
|
||||
request._response = response
|
||||
request.RunPostCommandActionsIfNeeded()
|
||||
ok_( set_qf_list.called )
|
||||
ok_( vim_eval.called )
|
||||
request = CommandRequest( [ command ] )
|
||||
request._response = response
|
||||
request.RunPostCommandActionsIfNeeded()
|
||||
ok_( set_qf_list.called )
|
||||
|
||||
basic_goto = {
|
||||
'filepath': 'test',
|
||||
|
@ -723,6 +723,8 @@ class MockBuffer( object ):
|
||||
return [ ToUnicode( x ) for x in self.lines ]
|
||||
|
||||
|
||||
@patch( 'ycm.vimsupport.VariableExists', return_value = False )
|
||||
@patch( 'ycm.vimsupport.SetFittingHeightForCurrentWindow' )
|
||||
@patch( 'ycm.vimsupport.GetBufferNumberForFilename',
|
||||
return_value=1,
|
||||
new_callable=ExtendedMock )
|
||||
@ -738,7 +740,9 @@ def ReplaceChunks_SingleFile_Open_test( vim_command,
|
||||
echo_text_vim_width,
|
||||
open_filename,
|
||||
buffer_is_visible,
|
||||
get_buffer_number_for_filename ):
|
||||
get_buffer_number_for_filename,
|
||||
set_fitting_height,
|
||||
variable_exists ):
|
||||
|
||||
chunks = [
|
||||
_BuildChunk( 1, 1, 2, 1, 'replacement', 'single_file' )
|
||||
@ -788,9 +792,11 @@ def ReplaceChunks_SingleFile_Open_test( vim_command,
|
||||
'type': 'F'
|
||||
} ] ) ) ),
|
||||
] )
|
||||
vim_command.assert_has_calls( [
|
||||
call( 'copen 1' )
|
||||
vim_command.assert_has_exact_calls( [
|
||||
call( 'botright copen' ),
|
||||
call( 'silent! wincmd p' )
|
||||
] )
|
||||
set_fitting_height.assert_called_once_with()
|
||||
|
||||
# And it is ReplaceChunks that prints the message showing the number of
|
||||
# changes
|
||||
@ -799,6 +805,8 @@ def ReplaceChunks_SingleFile_Open_test( vim_command,
|
||||
] )
|
||||
|
||||
|
||||
@patch( 'ycm.vimsupport.VariableExists', return_value = False )
|
||||
@patch( 'ycm.vimsupport.SetFittingHeightForCurrentWindow' )
|
||||
@patch( 'ycm.vimsupport.GetBufferNumberForFilename',
|
||||
side_effect=[ -1, -1, 1 ],
|
||||
new_callable=ExtendedMock )
|
||||
@ -819,7 +827,9 @@ def ReplaceChunks_SingleFile_NotOpen_test( vim_command,
|
||||
echo_text_vim_width,
|
||||
open_filename,
|
||||
buffer_is_visible,
|
||||
get_buffer_number_for_filename ):
|
||||
get_buffer_number_for_filename,
|
||||
set_fitting_height,
|
||||
variable_exists ):
|
||||
|
||||
chunks = [
|
||||
_BuildChunk( 1, 1, 2, 1, 'replacement', 'single_file' )
|
||||
@ -872,13 +882,14 @@ def ReplaceChunks_SingleFile_NotOpen_test( vim_command,
|
||||
'size': 10
|
||||
} )
|
||||
|
||||
# And close it again, then show the preview window (note, we don't check exact
|
||||
# calls because there are other calls which are checked elsewhere)
|
||||
vim_command.assert_has_calls( [
|
||||
# And close it again, then show the quickfix window.
|
||||
vim_command.assert_has_exact_calls( [
|
||||
call( 'lclose' ),
|
||||
call( 'hide' ),
|
||||
call( 'copen 1' ),
|
||||
call( 'botright copen' ),
|
||||
call( 'silent! wincmd p' )
|
||||
] )
|
||||
set_fitting_height.assert_called_once_with()
|
||||
|
||||
# And update the quickfix list
|
||||
vim_eval.assert_has_exact_calls( [
|
||||
@ -1048,6 +1059,8 @@ def ReplaceChunks_User_Aborts_Opening_File_test(
|
||||
echo_text_vim_width.assert_not_called()
|
||||
|
||||
|
||||
@patch( 'ycm.vimsupport.VariableExists', return_value = False )
|
||||
@patch( 'ycm.vimsupport.SetFittingHeightForCurrentWindow' )
|
||||
@patch( 'ycm.vimsupport.GetBufferNumberForFilename', side_effect=[
|
||||
22, # first_file (check)
|
||||
-1, # another_file (check)
|
||||
@ -1080,7 +1093,9 @@ def ReplaceChunks_MultiFile_Open_test( vim_command,
|
||||
echo_text_vim_width,
|
||||
open_filename,
|
||||
buffer_is_visible,
|
||||
get_buffer_number_for_filename ):
|
||||
get_buffer_number_for_filename,
|
||||
set_fitting_height,
|
||||
variable_exists ):
|
||||
|
||||
# Chunks are split across 2 files, one is already open, one isn't
|
||||
|
||||
@ -1137,13 +1152,14 @@ def ReplaceChunks_MultiFile_Open_test( vim_command,
|
||||
'size': 10
|
||||
} )
|
||||
|
||||
# And close it again, then show the preview window (note, we don't check exact
|
||||
# calls because there are other calls which are checked elsewhere)
|
||||
vim_command.assert_has_calls( [
|
||||
# And close it again, then show the quickfix window.
|
||||
vim_command.assert_has_exact_calls( [
|
||||
call( 'lclose' ),
|
||||
call( 'hide' ),
|
||||
call( 'copen 2' ),
|
||||
call( 'botright copen' ),
|
||||
call( 'silent! wincmd p' )
|
||||
] )
|
||||
set_fitting_height.assert_called_once_with()
|
||||
|
||||
# And update the quickfix list with each entry
|
||||
vim_eval.assert_has_exact_calls( [
|
||||
|
@ -253,15 +253,44 @@ def SetLocationList( diagnostics ):
|
||||
vim.eval( 'setloclist( 0, {0} )'.format( json.dumps( diagnostics ) ) )
|
||||
|
||||
|
||||
def SetQuickFixList( quickfix_list, display=False ):
|
||||
"""list should be in qflist format: see ":h setqflist" for details"""
|
||||
def SetQuickFixList( quickfix_list, focus = False, autoclose = False ):
|
||||
"""Populate the quickfix list and open it. List should be in qflist format:
|
||||
see ":h setqflist" for details. When focus is set to True, the quickfix
|
||||
window becomes the active window. When autoclose is set to True, the quickfix
|
||||
window is automatically closed after an entry is selected."""
|
||||
vim.eval( 'setqflist( {0} )'.format( json.dumps( quickfix_list ) ) )
|
||||
OpenQuickFixList( focus, autoclose )
|
||||
|
||||
if display:
|
||||
vim.command( 'copen {0}'.format( len( quickfix_list ) ) )
|
||||
|
||||
def OpenQuickFixList( focus = False, autoclose = False ):
|
||||
"""Open the quickfix list to full width at the bottom of the screen with its
|
||||
height automatically set to fit all entries. This behavior can be overridden
|
||||
by using the YcmQuickFixOpened autocommand.
|
||||
See the SetQuickFixList function for the focus and autoclose options."""
|
||||
vim.command( 'botright copen' )
|
||||
|
||||
SetFittingHeightForCurrentWindow()
|
||||
|
||||
if autoclose:
|
||||
# This autocommand is automatically removed when the quickfix window is
|
||||
# closed.
|
||||
vim.command( 'au WinLeave <buffer> q' )
|
||||
|
||||
if VariableExists( '#User#YcmQuickFixOpened' ):
|
||||
vim.command( 'doautocmd User YcmQuickFixOpened' )
|
||||
|
||||
if not focus:
|
||||
JumpToPreviousWindow()
|
||||
|
||||
|
||||
def SetFittingHeightForCurrentWindow():
|
||||
window_width = GetIntValue( 'winwidth( 0 )' )
|
||||
fitting_height = 0
|
||||
for line in vim.current.buffer:
|
||||
fitting_height += len( line ) // window_width + 1
|
||||
vim.command( '{0}wincmd _'.format( fitting_height ) )
|
||||
|
||||
|
||||
def ConvertDiagnosticsToQfList( diagnostics ):
|
||||
def ConvertDiagnosticToQfFormat( diagnostic ):
|
||||
# See :h getqflist for a description of the dictionary fields.
|
||||
@ -641,7 +670,7 @@ def ReplaceChunks( chunks ):
|
||||
|
||||
# Open the quickfix list, populated with entries for each location we changed.
|
||||
if locations:
|
||||
SetQuickFixList( locations, True )
|
||||
SetQuickFixList( locations )
|
||||
|
||||
EchoTextVimWidth( "Applied " + str( len( chunks ) ) + " changes" )
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user