remove typo completion, add subsequence completion

This commit is contained in:
adam j hartz 2016-06-08 01:29:15 -04:00
parent cf3105e1ab
commit d027432e3b
3 changed files with 70 additions and 12 deletions

View file

@ -13,6 +13,8 @@ Current Developments
attempted to load.
* Only show the prompt for the wizard if we did not attempt to load any run
control files (as opposed to if none were successfully loaded).
* Tab completion of paths now includes zsh-style path expansion (subsequence
matching)
**Deprecated:** None

View file

@ -151,9 +151,57 @@ def _quote_paths(paths, start, end):
return out
def fuzzy_match(ref, typed):
thresh = builtins.__xonsh_env__['SUGGEST_THRESHOLD']
return levenshtein(ref, typed, thresh) <= thresh
def joinpath(path):
if path is None:
return ''
if len(path) == 0:
return ''
if path == ('',):
return get_sep()
elif path[0] == '':
return get_sep() + _normpath(os.path.join(*path))
else:
return _normpath(os.path.join(*path))
def splitpath(path):
path = _normpath(path)
if path.startswith(get_sep()):
pre = ('', )
else:
pre = ()
return pre + _splitpath(path, ())
def _splitpath(path, sofar=()):
folder, path = os.path.split(path)
if path == "":
return sofar[::-1]
elif folder == "":
return (sofar + (path, ))[::-1]
else:
return _splitpath(folder, sofar + (path, ))
def expanded_match(ref, typed):
if len(typed) == 0:
return True
elif len(ref) == 0:
return False
elif ref[0] == typed[0]:
return expanded_match(ref[1:], typed[1:])
else:
return expanded_match(ref[1:], typed)
def _expand_one(sofar, nextone):
out = set()
for i in sofar:
for j in iglobpath(os.path.join(joinpath(i), '*') if i is not None else '*'):
j = os.path.basename(j)
if expanded_match(j, nextone):
out.add((i or ()) + (j, ))
return out
def complete_path(prefix, line, start, end, ctx, cdpath=True):
@ -174,15 +222,18 @@ def complete_path(prefix, line, start, end, ctx, cdpath=True):
csc = env.get('CASE_SENSITIVE_COMPLETIONS')
for s in iglobpath(prefix + '*', ignore_case=(not csc)):
paths.add(s)
if len(paths) == 0:
for s in iglobpath(os.path.join(os.path.dirname(prefix), '*'),
ignore_case=(not csc)):
bname = os.path.basename(prefix)
lenb = len(bname)
if csc and fuzzy_match(s, bname):
paths.add(os.path.join(os.path.dirname(prefix), s))
if (not csc) and fuzzy_match(s.lower(), prefix.lower()):
paths.add(os.path.join(os.path.dirname(prefix), s))
if env.get('FUZZY_PATH_COMPLETION'):
p = splitpath(prefix)
if len(p) != 0:
if p[0] == '':
basedir = ('', )
p = p[1:]
else:
basedir = None
matches_so_far = {basedir}
for i in p:
matches_so_far = _expand_one(matches_so_far, i)
paths |= {joinpath(i) for i in matches_so_far}
if tilde in prefix:
home = os.path.expanduser(tilde)
paths = {s.replace(home, tilde) for s in paths}

View file

@ -92,6 +92,7 @@ DEFAULT_ENSURERS = {
'DYNAMIC_CWD_WIDTH': (is_dynamic_cwd_width, to_dynamic_cwd_tuple,
dynamic_cwd_tuple_to_str),
'FORCE_POSIX_PATHS': (is_bool, to_bool, bool_to_str),
'FUZZY_PATH_COMPLETION': (is_bool, to_bool, bool_to_str),
'HISTCONTROL': (is_string_set, csv_to_set, set_to_csv),
'IGNOREEOF': (is_bool, to_bool, bool_to_str),
'INTENSIFY_COLORS_ON_WIN':(always_false, intensify_colors_on_win_setter,
@ -202,6 +203,7 @@ DEFAULT_VALUES = {
'DYNAMIC_CWD_WIDTH': (float('inf'), 'c'),
'EXPAND_ENV_VARS': True,
'FORCE_POSIX_PATHS': False,
'FUZZY_PATH_COMPLETION': True,
'HISTCONTROL': set(),
'IGNOREEOF': False,
'INDENT': ' ',
@ -350,6 +352,9 @@ DEFAULT_DOCS = {
"and $TITLE. See 'Customizing the Prompt' "
'http://xon.sh/tutorial.html#customizing-the-prompt',
configurable=False, default='xonsh.environ.FORMATTER_DICT'),
'FUZZY_PATH_COMPLETION': VarDocs(
"Causes path completion to use subsequence matching rather than "
"substring matching."),
'HISTCONTROL': VarDocs(
'A set of strings (comma-separated list in string form) of options '
'that determine what commands are saved to the history list. By '