Merge pull request #756 from icholy/master
Fix issues with tab completion.
This commit is contained in:
commit
8d6f9c3d84
@ -53,6 +53,11 @@ if PY3:
|
||||
else:
|
||||
long_type = long # NOQA
|
||||
|
||||
if PY3:
|
||||
string_types = str,
|
||||
else:
|
||||
string_types = basestring, # NOQA
|
||||
|
||||
if PY3:
|
||||
exec('def raise_empty(t, *args): raise t(*args) from None')
|
||||
else:
|
||||
|
@ -220,12 +220,12 @@ def run_repl(hr=None, spy=False):
|
||||
sys.ps1 = "=> "
|
||||
sys.ps2 = "... "
|
||||
|
||||
ns = {}
|
||||
namespace = {'__name__': '__console__', '__doc__': ''}
|
||||
|
||||
with completion(Completer(namespace=ns)):
|
||||
with completion(Completer(namespace)):
|
||||
|
||||
if not hr:
|
||||
hr = HyREPL(spy, locals=ns)
|
||||
hr = HyREPL(spy, namespace)
|
||||
|
||||
hr.interact("{appname} {version} using "
|
||||
"{py}({build}) {pyversion} on {os}".format(
|
||||
|
@ -29,6 +29,7 @@ import os
|
||||
import re
|
||||
import sys
|
||||
from contextlib import contextmanager
|
||||
from hy._compat import string_types
|
||||
|
||||
docomplete = True
|
||||
|
||||
@ -53,27 +54,31 @@ import hy.compiler
|
||||
|
||||
from hy._compat import builtins
|
||||
|
||||
PATH = [hy.compiler._compile_table,
|
||||
hy.macros._hy_macros,
|
||||
builtins.__dict__]
|
||||
|
||||
|
||||
class Completer(object):
|
||||
def __init__(self, namespace=None):
|
||||
if namespace and not isinstance(namespace, dict):
|
||||
raise TypeError('namespace must be a dictionary')
|
||||
|
||||
def __init__(self, namespace={}):
|
||||
if not isinstance(namespace, dict):
|
||||
raise TypeError('namespace must be a dictionary')
|
||||
self.namespace = namespace
|
||||
self.path = [hy.compiler._compile_table,
|
||||
builtins.__dict__,
|
||||
hy.macros._hy_macros[None],
|
||||
namespace]
|
||||
self.reader_path = [hy.macros._hy_reader[None]]
|
||||
if '__name__' in namespace:
|
||||
module_name = namespace['__name__']
|
||||
self.path.append(hy.macros._hy_macros[module_name])
|
||||
self.reader_path.append(hy.macros._hy_reader[module_name])
|
||||
|
||||
def attr_matches(self, text):
|
||||
# Borrowed from IPython's completer
|
||||
|
||||
# Another option, seems to work great. Catches things like ''.<tab>
|
||||
m = re.match(r"(\S+(\.\w+)*)\.([\w-]*)$", text)
|
||||
m = re.match(r"(\S+(\.[\w-]+)*)\.([\w-]*)$", text)
|
||||
|
||||
if m:
|
||||
expr, attr = m.group(1, 3)
|
||||
attr = attr.replace("-", "_")
|
||||
expr = expr.replace("-", "_")
|
||||
else:
|
||||
return []
|
||||
|
||||
@ -83,29 +88,38 @@ class Completer(object):
|
||||
except Exception:
|
||||
return []
|
||||
|
||||
# Build match list to return
|
||||
n = len(attr)
|
||||
matches = []
|
||||
for w in words:
|
||||
if w[:n] == attr:
|
||||
matches.append("%s.%s" % (expr, w.replace("_", "-")))
|
||||
matches.append("{}.{}".format(
|
||||
expr.replace("_", "-"), w.replace("_", "-")))
|
||||
return matches
|
||||
|
||||
def global_matches(self, text):
|
||||
path = PATH
|
||||
if self.namespace:
|
||||
path.append(self.namespace)
|
||||
|
||||
matches = []
|
||||
for p in path:
|
||||
p = filter(lambda x: isinstance(x, str), p.keys())
|
||||
p = [x.replace("_", "-") for x in p]
|
||||
[matches.append(x) for x in
|
||||
filter(lambda x: x.startswith(text), p)]
|
||||
for p in self.path:
|
||||
for k in p.keys():
|
||||
if isinstance(k, string_types):
|
||||
k = k.replace("_", "-")
|
||||
if k.startswith(text):
|
||||
matches.append(k)
|
||||
return matches
|
||||
|
||||
def reader_matches(self, text):
|
||||
text = text[1:]
|
||||
matches = []
|
||||
for p in self.reader_path:
|
||||
for k in p.keys():
|
||||
if isinstance(k, string_types):
|
||||
if k.startswith(text):
|
||||
matches.append("#{}".format(k))
|
||||
return matches
|
||||
|
||||
def complete(self, text, state):
|
||||
if "." in text:
|
||||
if text.startswith("#"):
|
||||
matches = self.reader_matches(text)
|
||||
elif "." in text:
|
||||
matches = self.attr_matches(text)
|
||||
else:
|
||||
matches = self.global_matches(text)
|
||||
|
Loading…
Reference in New Issue
Block a user