Auto merge of #2329 - micbou:keyboard-interrupt, r=vheon

[READY] Handle keyboard interruption when evaluating Vim expression with user input

When evaluating a Vim expression in Python that involves code expecting user input (e.g. `input()`, `inputlist()`, `complete_check()`, etc.), if this evaluation is interrupted by the user (with `CTRL-C` for instance), Vim will pass the interruption to the Python interpreter which in turn will raise a `KeyboardInterrupt` exception. We don't want these exceptions to be displayed to the user (because the way Vim handles Python exceptions is really annoying) so we catch them where appropriate.

Fixes #2289.

<!-- 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/2329)
<!-- Reviewable:end -->
This commit is contained in:
Homu 2016-09-15 00:02:26 +09:00
commit 6bafb6c272
3 changed files with 23 additions and 21 deletions

View File

@ -728,23 +728,8 @@ function! s:InvokeCompletion()
endfunction
exec s:python_until_eof
def GetCompletionsInner():
request = ycm_state.GetCurrentCompletionRequest()
request.Start()
while not request.Done():
if bool( int( vim.eval( 'complete_check()' ) ) ):
return { 'words' : [], 'refresh' : 'always'}
results = base.AdjustCandidateInsertionText( request.Response() )
return { 'words' : results, 'refresh' : 'always' }
EOF
function! s:GetCompletions()
exec s:python_command "results = GetCompletionsInner()"
let results = s:Pyeval( 'results' )
return results
return s:Pyeval( 'ycm_state.GetCompletions()' )
endfunction

View File

@ -506,7 +506,10 @@ def PresentDialog( message, choices, default_choice_index = 0 ):
EscapeForVim( ToUnicode( message ) ),
EscapeForVim( ToUnicode( "\n" .join( choices ) ) ),
default_choice_index + 1 )
return int( vim.eval( to_eval ) ) - 1
try:
return GetIntValue( to_eval ) - 1
except KeyboardInterrupt:
return -1
def Confirm( message ):
@ -554,9 +557,9 @@ def SelectFromList( prompt, items ):
# See :help input() for explanation of the use of inputsave() and inpput
# restore(). It is done in try/finally in case vim.eval ever throws an
# exception (such as KeyboardInterrupt)
selected = int( vim.eval( "inputlist( "
+ json.dumps( vim_items )
+ " )" ) ) - 1
selected = GetIntValue( "inputlist( " + json.dumps( vim_items ) + " )" ) - 1
except KeyboardInterrupt:
selected = -1
finally:
vim.eval( 'inputrestore()' )

View File

@ -32,7 +32,7 @@ import signal
import base64
from subprocess import PIPE
from tempfile import NamedTemporaryFile
from ycm import paths, vimsupport
from ycm import base, paths, vimsupport
from ycmd import utils
from ycmd import server_utils
from ycmd.request_wrap import RequestWrap
@ -234,6 +234,20 @@ class YouCompleteMe( object ):
return self._latest_completion_request
def GetCompletions( self ):
request = self.GetCurrentCompletionRequest()
request.Start()
while not request.Done():
try:
if vimsupport.GetBoolValue( 'complete_check()' ):
return { 'words' : [], 'refresh' : 'always' }
except KeyboardInterrupt:
return { 'words' : [], 'refresh' : 'always' }
results = base.AdjustCandidateInsertionText( request.Response() )
return { 'words' : results, 'refresh' : 'always' }
def SendCommandRequest( self, arguments, completer ):
if self.IsServerAlive():
return SendCommandRequest( arguments, completer )