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/>.
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

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