forked from VimPlug/jedi
simplify repl completion support, only use the jedi one, because the builtin completion (rlcompleter) is not context sensitive and makes the whole thing really complicated.
This commit is contained in:
110
jedi/utils.py
110
jedi/utils.py
@@ -2,92 +2,12 @@
|
||||
Utilities for end-users.
|
||||
"""
|
||||
|
||||
from rlcompleter import Completer
|
||||
from __future__ import absolute_import
|
||||
import __main__
|
||||
|
||||
from jedi import Interpreter
|
||||
|
||||
|
||||
_NON_DELIMS = ' \t\n()'
|
||||
"""
|
||||
:class:`rcompleter.Completer` assumes these characters to be delimiter
|
||||
(i.e., :meth:`rcompleter.Completer.complete` does not expect these
|
||||
characters) but :class:`JediRLCompleter` can handle them.
|
||||
"""
|
||||
|
||||
try:
|
||||
import readline
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
_READLINE_DEFAULT_DELIMS = readline.get_completer_delims()
|
||||
_READLINE_JEDI_DELIMS = ''.join(
|
||||
set(_READLINE_DEFAULT_DELIMS) - set(_NON_DELIMS))
|
||||
|
||||
|
||||
class JediRLCompleter(Completer):
|
||||
|
||||
"""
|
||||
:class:`rlcompleter.Completer` enhanced by Jedi.
|
||||
|
||||
This class tries matchers defined in :class:`.Completer` first.
|
||||
If they fail, :class:`jedi.Interpreter` is used.
|
||||
|
||||
>>> import os
|
||||
>>> completer = JediRLCompleter(locals())
|
||||
>>> completer.complete('os.path.joi', 0) # completion w/o Jedi
|
||||
'os.path.join('
|
||||
>>> completer.complete('os.path.join().s', 0) # completion with Jedi
|
||||
'os.path.join().split'
|
||||
|
||||
"""
|
||||
|
||||
def _jedi_matches(self, text):
|
||||
completions = Interpreter(text, [self.namespace]).completions()
|
||||
return [text + c.complete for c in completions]
|
||||
|
||||
@staticmethod
|
||||
def _split_for_default_matcher(text, delims=_NON_DELIMS):
|
||||
"""
|
||||
Split `text` before passing it to :meth:`Completer.attr_matches` etc.
|
||||
|
||||
>>> JediRLCompleter._split_for_default_matcher('f(')
|
||||
('f(', '')
|
||||
>>> JediRLCompleter._split_for_default_matcher('f().g')
|
||||
('f()', '.g')
|
||||
|
||||
"""
|
||||
import re
|
||||
m = re.match(r"(.*[{0}])([^{0}]*)".format(re.escape(delims)), text)
|
||||
if not m:
|
||||
return ('', text)
|
||||
return m.groups()
|
||||
|
||||
def _find_matches(self, default_matcher, text):
|
||||
"""
|
||||
Common part for :meth:`attr_matches` and :meth:`global_matches`.
|
||||
|
||||
Try `default_matcher` first and return what it returns if
|
||||
it is not empty. Otherwise, try :meth:`_jedi_matches`.
|
||||
|
||||
:arg default_matcher: :meth:`.Completer.attr_matches` or
|
||||
:meth:`.Completer.global_matches`.
|
||||
:arg str text: code to complete
|
||||
"""
|
||||
(pre, body) = self._split_for_default_matcher(text)
|
||||
matches = default_matcher(self, body)
|
||||
if matches:
|
||||
return [pre + m for m in matches]
|
||||
return self._jedi_matches(text)
|
||||
|
||||
def attr_matches(self, text):
|
||||
# NOTE: Completer is old type class so `super` cannot be used here
|
||||
return self._find_matches(Completer.attr_matches, text)
|
||||
|
||||
def global_matches(self, text):
|
||||
# NOTE: Completer is old type class so `super` cannot be used here
|
||||
return self._find_matches(Completer.global_matches, text)
|
||||
|
||||
|
||||
def setup_readline():
|
||||
"""
|
||||
Install Jedi completer to :mod:`readline`.
|
||||
@@ -105,6 +25,28 @@ def setup_readline():
|
||||
except ImportError:
|
||||
print("Module readline not available.")
|
||||
else:
|
||||
readline.set_completer(JediRLCompleter().complete)
|
||||
class JediRL():
|
||||
def complete(self, text, state):
|
||||
"""
|
||||
This complete stuff is pretty weird, a generator would make
|
||||
a lot more sense, but probably due to backwards compatibility
|
||||
this is still the way how it works.
|
||||
|
||||
The only important part is the ``Interpreter`` call, everything
|
||||
else hsa been copied from the ``rlcompleter`` std. library
|
||||
module.
|
||||
"""
|
||||
if state == 0:
|
||||
namespace = __main__.__dict__
|
||||
completions = Interpreter(text, [namespace]).completions()
|
||||
self.matches = [text + c.complete for c in completions]
|
||||
try:
|
||||
return self.matches[state]
|
||||
except IndexError:
|
||||
return None
|
||||
|
||||
readline.set_completer(JediRL().get_item)
|
||||
|
||||
readline.parse_and_bind("tab: complete")
|
||||
readline.set_completer_delims(_READLINE_JEDI_DELIMS)
|
||||
# No delimiters, Jedi handles that.
|
||||
readline.set_completer_delims('')
|
||||
|
||||
Reference in New Issue
Block a user