use builtin repl completion after all, but written by us not the std lib module, which doesn't seem to work really, #280

This commit is contained in:
David Halter
2013-08-15 12:47:10 +04:30
parent 306dbf12e4
commit 9a3ea38b1c
4 changed files with 47 additions and 12 deletions

View File

@@ -173,3 +173,8 @@ def u(string):
elif not isinstance(string, unicode):
return unicode(str(string), 'UTF-8')
return string
try:
import builtins # module name in python 3
except ImportError:
import __builtin__ as builtins

View File

@@ -91,7 +91,7 @@ class Script(object):
path = self._module.get_path_until_cursor()
if re.search('^\.|\.\.$', path):
return []
path, dot, like = self._get_completion_parts(path)
path, dot, like = self._get_completion_parts()
completion_line = self._module.get_line(self.pos[0])[:self.pos[1]]
try:
@@ -506,11 +506,12 @@ class Script(object):
kill_count=kill_count, direct_resolve=True)
return i, cur_name_part
def _get_completion_parts(self, path):
def _get_completion_parts(self):
"""
Returns the parts for the completion
:return: tuple - (path, dot, like)
"""
path = self._module.get_path_until_cursor()
match = re.match(r'^(.*?)(\.|)(\w?[\w\d]*)$', path, flags=re.S)
return match.groups()

View File

@@ -95,13 +95,13 @@ class ModuleWithCursor(Module):
def __init__(self, path, source, position):
super(ModuleWithCursor, self).__init__(path, source)
self.position = position
self.source = source
self._path_until_cursor = None
# this two are only used, because there is no nonlocal in Python 2
self._line_temp = None
self._relevant_temp = None
self.source = source
@property
def parser(self):
""" get the parser lazy """
@@ -121,9 +121,10 @@ class ModuleWithCursor(Module):
def get_path_until_cursor(self):
""" Get the path under the cursor. """
result = self._get_path_until_cursor()
self._start_cursor_pos = self._start_cursor_pos_temp
return result
if self._path_until_cursor is None: # small caching
self._path_until_cursor = self._get_path_until_cursor()
self._start_cursor_pos = self._start_cursor_pos_temp
return self._path_until_cursor
def _get_path_until_cursor(self, start_pos=None):
def fetch_line():

View File

@@ -4,7 +4,9 @@ Utilities for end-users.
from __future__ import absolute_import
import __main__
import re
from jedi._compatibility import builtins
from jedi import Interpreter
@@ -61,20 +63,46 @@ def setup_readline():
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.
The only important part is stuff in the ``state == 0`` flow,
everything else has 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]
interpreter = Interpreter(text, [namespace])
# The following part is a bit hackish, because it tries to
# directly access some jedi internals. The goal is to just
# use the "default" completion with ``getattr`` if
# possible.
path, dot, like = interpreter._get_completion_parts()
if re.match('^[\w][\w\d.]*$', path):
paths = path.split('.') if path else []
namespaces = (namespace, builtins)
for p in paths:
old, namespaces = namespaces, []
for n in old:
try:
namespaces.append(getattr(n, p))
except AttributeError:
pass
self.matches = []
for n in namespaces:
for name in dir(n):
if name.lower().startswith(like.lower()):
self.matches.append(path + dot + name)
else:
completions = interpreter.completions()
self.matches = [text + c.complete for c in completions]
try:
return self.matches[state]
except IndexError:
return None
readline.set_completer(JediRL().complete)
j = JediRL()
j.complete('r', 0)
readline.parse_and_bind("tab: complete")
# No delimiters, Jedi handles that.