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 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() function! s:GetCompletions()
exec s:python_command "results = GetCompletionsInner()" return s:Pyeval( 'ycm_state.GetCompletions()' )
let results = s:Pyeval( 'results' )
return results
endfunction endfunction

View File

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

View File

@ -32,7 +32,7 @@ import signal
import base64 import base64
from subprocess import PIPE from subprocess import PIPE
from tempfile import NamedTemporaryFile from tempfile import NamedTemporaryFile
from ycm import paths, vimsupport from ycm import base, paths, vimsupport
from ycmd import utils from ycmd import utils
from ycmd import server_utils from ycmd import server_utils
from ycmd.request_wrap import RequestWrap from ycmd.request_wrap import RequestWrap
@ -234,6 +234,20 @@ class YouCompleteMe( object ):
return self._latest_completion_request 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 ): def SendCommandRequest( self, arguments, completer ):
if self.IsServerAlive(): if self.IsServerAlive():
return SendCommandRequest( arguments, completer ) return SendCommandRequest( arguments, completer )