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