Refactor jedi-completer to use a worker thread

This commit is contained in:
Stephen Sugden 2013-02-08 00:22:28 -08:00
parent da46be7044
commit eed0434e39
2 changed files with 76 additions and 27 deletions

View File

@ -16,8 +16,9 @@
# along with YouCompleteMe. If not, see <http://www.gnu.org/licenses/>. # along with YouCompleteMe. If not, see <http://www.gnu.org/licenses/>.
import vim import vim
from threading import Thread, Event
from completers.completer import Completer from completers.completer import Completer
from vimsupport import PostVimMessage, CurrentLineAndColumn from vimsupport import CurrentLineAndColumn
import sys import sys
from os.path import join, abspath, dirname from os.path import join, abspath, dirname
@ -29,40 +30,89 @@ sys.path.insert(0, join(abspath(dirname(__file__)), 'jedi'))
from jedi import Script from jedi import Script
sys.path.pop(0) 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/ https://jedi.readthedocs.org/en/latest/
""" """
def __init__( self ): def __init__(self):
self.candidates = None 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 """ """ Just python """
return ['python'] return ['python']
def ShouldUseNow(self, start_column): def ShouldUseNowInner(self, start_column):
""" Only use jedi-completion after a . """ """
line = vim.current.line Use Jedi if we are completing an identifier immediately after a dot.
return len(line) >= start_column and line[start_column - 1] == '.' """
line = str(vim.current.line)
result = line[start_column - 1] == '.'
return result
def CandidatesFromStoredRequest( self ): def CandidatesForQueryAsyncInner(self, query):
return self.candidates self._query = query
self._candidates_ready.clear()
self._query_ready.set()
def OnFileReadyToParse(self): def AsyncCandidateRequestReadyInner(self):
pass if self._completion_thread.is_alive():
return WaitAndClear(self._candidates_ready, timeout=0.005)
else:
self._start_completion_thread()
return True
def AsyncCandidateRequestReady(self): def CandidatesFromStoredRequestInner(self):
return self.candidates is not None return self._candidates or []
def CandidatesFromStoredRequest(self): def SetCandidates(self):
return self.candidates while True:
WaitAndClear(self._query_ready)
def CandidatesForQueryAsync( self, query ): if self._exit:
buffer = vim.current.buffer return
filename = buffer.name
line, column = CurrentLineAndColumn() filename = vim.current.buffer.name
script = Script("\n".join(buffer), line + 1, column, filename) query = self._query
self.candidates = [completion.word for completion line, column = CurrentLineAndColumn()
in script.complete() if completion.word.startswith(query)] 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

@ -1 +0,0 @@
Subproject commit 23f36c86d7d7c5b890fef9eb9eb46cd1fe553329