From e28968e90bd8df75af5445d078af3279e96e32b0 Mon Sep 17 00:00:00 2001 From: Morten Enemark Lund Date: Wed, 15 Jun 2016 23:37:53 +0200 Subject: [PATCH 1/8] Fixed quoted paths not being recognized as directories --- xonsh/completers/path.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xonsh/completers/path.py b/xonsh/completers/path.py index 2020f74f2..1b1d2514d 100644 --- a/xonsh/completers/path.py +++ b/xonsh/completers/path.py @@ -279,4 +279,4 @@ def complete_path(prefix, line, start, end, ctx, cdpath=True): def complete_dir(prefix, line, start, end, ctx, cdpath=False): o, lp = complete_path(prefix, line, start, end, cdpath) - return {i for i in o if os.path.isdir(i)}, lp + return {i for i in o if os.path.isdir(i.strip(''''"'''))}, lp From 70acb5d793bd7398df0b36999d0e70e98cbf7313 Mon Sep 17 00:00:00 2001 From: Morten Enemark Lund Date: Thu, 16 Jun 2016 10:59:19 +0200 Subject: [PATCH 2/8] Use regex expression to find unquoted version of the strings. --- xonsh/completers/path.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/xonsh/completers/path.py b/xonsh/completers/path.py index 1b1d2514d..dbb00a31c 100644 --- a/xonsh/completers/path.py +++ b/xonsh/completers/path.py @@ -277,6 +277,14 @@ def complete_path(prefix, line, start, end, ctx, cdpath=True): return paths, lprefix +RE_UNQUOTE = re.compile("""(?:[rub](?P["'])|(?P["']?))(.+)(?:(?P=q1)|(?P=q2))$""") + + def complete_dir(prefix, line, start, end, ctx, cdpath=False): - o, lp = complete_path(prefix, line, start, end, cdpath) - return {i for i in o if os.path.isdir(i.strip(''''"'''))}, lp + paths, lp = complete_path(prefix, line, start, end, cdpath) + dirs = set() + for path in paths: + m = RE_UNQUOTE.match(path) + if m and os.path.isdir(m.group(2)): + dirs.add(path) + return dirs, lp From c703315f36f2c85137cb8617718a354614fcba55 Mon Sep 17 00:00:00 2001 From: Morten Enemark Lund Date: Thu, 16 Jun 2016 11:12:30 +0200 Subject: [PATCH 3/8] Add changelog entry --- news/quoted_path_completions.rst | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 news/quoted_path_completions.rst diff --git a/news/quoted_path_completions.rst b/news/quoted_path_completions.rst new file mode 100644 index 000000000..650d6c85b --- /dev/null +++ b/news/quoted_path_completions.rst @@ -0,0 +1,14 @@ +**Added:** None + +**Changed:** None + +**Deprecated:** None + +**Removed:** None + +**Fixed:** + +* Fixed missing completions for ``cd`` and ```rmdir`` when directories had spaces + in their names. + +**Security:** None From 14d818b3c5e5fb435dffb7a21c4394743dd1cce4 Mon Sep 17 00:00:00 2001 From: Morten Enemark Lund Date: Thu, 16 Jun 2016 12:23:17 +0200 Subject: [PATCH 4/8] Support triple quotes. RegEx craziness. --- xonsh/completers/path.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/xonsh/completers/path.py b/xonsh/completers/path.py index dbb00a31c..46b29a385 100644 --- a/xonsh/completers/path.py +++ b/xonsh/completers/path.py @@ -277,7 +277,9 @@ def complete_path(prefix, line, start, end, ctx, cdpath=True): return paths, lprefix -RE_UNQUOTE = re.compile("""(?:[rub](?P["'])|(?P["']?))(.+)(?:(?P=q1)|(?P=q2))$""") +RE_UNQUOTE = re.compile("""(?:[r](?P(?P"[^"]|'[^']|\"""|'''))|""" + """(?P(?P=quotes)?))""" + """(?P.+)(?:(?P=raw)|(?P=normal))$""") def complete_dir(prefix, line, start, end, ctx, cdpath=False): From cec182f8f03c35dabbfc45819b919d158485f3c8 Mon Sep 17 00:00:00 2001 From: Morten Enemark Lund Date: Thu, 16 Jun 2016 14:23:52 +0200 Subject: [PATCH 5/8] Fix wrong group reference --- xonsh/completers/path.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xonsh/completers/path.py b/xonsh/completers/path.py index 46b29a385..0c2466a75 100644 --- a/xonsh/completers/path.py +++ b/xonsh/completers/path.py @@ -287,6 +287,6 @@ def complete_dir(prefix, line, start, end, ctx, cdpath=False): dirs = set() for path in paths: m = RE_UNQUOTE.match(path) - if m and os.path.isdir(m.group(2)): + if m and os.path.isdir(m.group(3)): dirs.add(path) return dirs, lp From 0597c97d1242316fd5f5482b03b95ac284d5a38a Mon Sep 17 00:00:00 2001 From: Morten Enemark Lund Date: Fri, 17 Jun 2016 12:50:56 +0200 Subject: [PATCH 6/8] Changed to a much simpler solution where it isdir() is run before quoting the paths names. --- xonsh/completers/path.py | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/xonsh/completers/path.py b/xonsh/completers/path.py index 0c2466a75..c50529c80 100644 --- a/xonsh/completers/path.py +++ b/xonsh/completers/path.py @@ -225,7 +225,7 @@ def _expand_one(sofar, nextone, csc): return out -def complete_path(prefix, line, start, end, ctx, cdpath=True): +def complete_path(prefix, line, start, end, ctx, cdpath=True, filtfunc=None): """Completes based on a path name.""" # string stuff for automatic quoting path_str_start = '' @@ -269,24 +269,16 @@ def complete_path(prefix, line, start, end, ctx, cdpath=True): paths = {s.replace(home, tilde) for s in paths} if cdpath: _add_cdpaths(paths, prefix) + _add_env(paths, prefix) + _add_dots(paths, prefix) + if filtfunc is not None: + paths = {p for p in paths if filtfunc(p)} paths = _quote_paths({_normpath(s) for s in paths}, path_str_start, path_str_end) - _add_env(paths, prefix) - _add_dots(paths, prefix) return paths, lprefix -RE_UNQUOTE = re.compile("""(?:[r](?P(?P"[^"]|'[^']|\"""|'''))|""" - """(?P(?P=quotes)?))""" - """(?P.+)(?:(?P=raw)|(?P=normal))$""") - - def complete_dir(prefix, line, start, end, ctx, cdpath=False): - paths, lp = complete_path(prefix, line, start, end, cdpath) - dirs = set() - for path in paths: - m = RE_UNQUOTE.match(path) - if m and os.path.isdir(m.group(3)): - dirs.add(path) - return dirs, lp + return complete_path(prefix, line, start, end, cdpath, + filtfunc=os.path.isdir) From d458eb1a9a34837f886b4ce0a11f85f053eb1ed7 Mon Sep 17 00:00:00 2001 From: Morten Enemark Lund Date: Fri, 17 Jun 2016 13:55:21 +0200 Subject: [PATCH 7/8] Also apply filtfunc to stuff we add after the quoting --- xonsh/completers/path.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/xonsh/completers/path.py b/xonsh/completers/path.py index c50529c80..a65cc4d70 100644 --- a/xonsh/completers/path.py +++ b/xonsh/completers/path.py @@ -80,12 +80,13 @@ def _startswithnorm(x, start, startlow=None): return x.startswith(start) -def _add_env(paths, prefix): +def _env(prefix): if prefix.startswith('$'): key = prefix[1:] - paths.update({'$' + k - for k in builtins.__xonsh_env__ - if get_filter_function()(k, key)}) + return {'$' + k + for k in builtins.__xonsh_env__ + if get_filter_function()(k, key)} + return () def _add_dots(paths, prefix): @@ -132,7 +133,7 @@ def _quote_paths(paths, start, end): (backslash in s and slash != backslash))): start = end = _quote_to_use(s) if os.path.isdir(expand_path(s)): - _tail = slash + _tail = '' if s.endswith('/') else slash elif end == '': _tail = space else: @@ -269,13 +270,12 @@ def complete_path(prefix, line, start, end, ctx, cdpath=True, filtfunc=None): paths = {s.replace(home, tilde) for s in paths} if cdpath: _add_cdpaths(paths, prefix) - _add_env(paths, prefix) _add_dots(paths, prefix) - if filtfunc is not None: - paths = {p for p in paths if filtfunc(p)} + paths = set(filter(filtfunc, paths)) paths = _quote_paths({_normpath(s) for s in paths}, path_str_start, path_str_end) + paths.update(filter(filtfunc, _env(prefix))) return paths, lprefix From b7d1c57add83ca92124be9760f1c3d88574bb2d4 Mon Sep 17 00:00:00 2001 From: Morten Enemark Lund Date: Fri, 17 Jun 2016 14:24:05 +0200 Subject: [PATCH 8/8] Final updates --- xonsh/completers/path.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/xonsh/completers/path.py b/xonsh/completers/path.py index a65cc4d70..99c14c77b 100644 --- a/xonsh/completers/path.py +++ b/xonsh/completers/path.py @@ -89,11 +89,16 @@ def _env(prefix): return () -def _add_dots(paths, prefix): +def _dots(prefix): + slash = get_sep() + if slash == '\\': + slash = '' if prefix in {'', '.'}: - paths.update({'./', '../'}) - if prefix == '..': - paths.add('../') + return ('.'+slash, '..'+slash) + elif prefix == '..': + return ('..'+slash,) + else: + return () def _add_cdpaths(paths, prefix): @@ -133,7 +138,7 @@ def _quote_paths(paths, start, end): (backslash in s and slash != backslash))): start = end = _quote_to_use(s) if os.path.isdir(expand_path(s)): - _tail = '' if s.endswith('/') else slash + _tail = slash elif end == '': _tail = space else: @@ -270,11 +275,11 @@ def complete_path(prefix, line, start, end, ctx, cdpath=True, filtfunc=None): paths = {s.replace(home, tilde) for s in paths} if cdpath: _add_cdpaths(paths, prefix) - _add_dots(paths, prefix) paths = set(filter(filtfunc, paths)) paths = _quote_paths({_normpath(s) for s in paths}, path_str_start, path_str_end) + paths.update(filter(filtfunc, _dots(prefix))) paths.update(filter(filtfunc, _env(prefix))) return paths, lprefix