From eed0434e39802fc978c9200128cbd2887873ea9e Mon Sep 17 00:00:00 2001 From: Stephen Sugden Date: Fri, 8 Feb 2013 00:22:28 -0800 Subject: [PATCH] Refactor jedi-completer to use a worker thread --- python/completers/python/jedi_completer.py | 102 +++++++++++++++------ python/jedi | 1 - 2 files changed, 76 insertions(+), 27 deletions(-) delete mode 160000 python/jedi diff --git a/python/completers/python/jedi_completer.py b/python/completers/python/jedi_completer.py index 81b2b316..f04d623f 100644 --- a/python/completers/python/jedi_completer.py +++ b/python/completers/python/jedi_completer.py @@ -16,8 +16,9 @@ # along with YouCompleteMe. If not, see . import vim +from threading import Thread, Event from completers.completer import Completer -from vimsupport import PostVimMessage, CurrentLineAndColumn +from vimsupport import CurrentLineAndColumn import sys from os.path import join, abspath, dirname @@ -29,40 +30,89 @@ sys.path.insert(0, join(abspath(dirname(__file__)), 'jedi')) from jedi import Script sys.path.pop(0) -class JediCompleter( Completer ): + +class JediCompleter(Completer): """ - A Completer that uses the Jedi completion engine + A Completer that uses the Jedi completion engine. https://jedi.readthedocs.org/en/latest/ """ - def __init__( self ): - self.candidates = None + def __init__(self): + super(JediCompleter, self).__init__() + self._query_ready = Event() + self._candidates_ready = Event() + self._query = None + self._candidates = None + self._exit = False + self._start_completion_thread() - def SupportedFiletypes( self ): + def _start_completion_thread(self): + self._completion_thread = Thread(target=self.SetCandidates) + self._completion_thread.start() + + def SupportedFiletypes(self): """ Just python """ return ['python'] - def ShouldUseNow(self, start_column): - """ Only use jedi-completion after a . """ - line = vim.current.line - return len(line) >= start_column and line[start_column - 1] == '.' + def ShouldUseNowInner(self, start_column): + """ + Use Jedi if we are completing an identifier immediately after a dot. + """ + line = str(vim.current.line) + result = line[start_column - 1] == '.' + return result - def CandidatesFromStoredRequest( self ): - return self.candidates - - def OnFileReadyToParse(self): - pass + def CandidatesForQueryAsyncInner(self, query): + self._query = query + self._candidates_ready.clear() + self._query_ready.set() - def AsyncCandidateRequestReady(self): - return self.candidates is not None + def AsyncCandidateRequestReadyInner(self): + if self._completion_thread.is_alive(): + return WaitAndClear(self._candidates_ready, timeout=0.005) + else: + self._start_completion_thread() + return True - def CandidatesFromStoredRequest(self): - return self.candidates + def CandidatesFromStoredRequestInner(self): + return self._candidates or [] - def CandidatesForQueryAsync( self, query ): - buffer = vim.current.buffer - filename = buffer.name - line, column = CurrentLineAndColumn() - script = Script("\n".join(buffer), line + 1, column, filename) - self.candidates = [completion.word for completion - in script.complete() if completion.word.startswith(query)] + def SetCandidates(self): + while True: + WaitAndClear(self._query_ready) + + if self._exit: + return + + filename = vim.current.buffer.name + query = self._query + line, column = CurrentLineAndColumn() + lines = map(str, vim.current.buffer) + if query is not None and lines[line]: + before, after = lines[line].rsplit('.', 1) + lines[line] = before + '.' + column = len(before) + 1 + + source = "\n".join(lines) + + script = Script(source, line + 1, column, filename) + + self._candidates = [{'word': str(completion.word), + 'menu': str(completion.description), + 'info': str(completion.doc)} + for completion in script.complete()] + + self._candidates_ready.set() + + def OnInsertLeave(self): + """ Tell the worker thread to exit """ + self._exit = True + self._query_ready.set() + self._candidates = None + + +def WaitAndClear(event, timeout=None): + ret = event.wait(timeout) + if ret: + event.clear() + return ret diff --git a/python/jedi b/python/jedi deleted file mode 160000 index 23f36c86..00000000 --- a/python/jedi +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 23f36c86d7d7c5b890fef9eb9eb46cd1fe553329