Skip to content

Commit 48b21fc

Browse files
committed
Allowing multiple redirectors when tab completing
1 parent 113da63 commit 48b21fc

1 file changed

Lines changed: 38 additions & 33 deletions

File tree

cmd2.py

Lines changed: 38 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1390,7 +1390,9 @@ def tokens_for_completion(self, line, begidx, endidx):
13901390

13911391
return tokens, raw_tokens
13921392

1393-
def basic_complete(self, text, line, begidx, endidx, match_against):
1393+
# noinspection PyUnusedLocal
1394+
@staticmethod
1395+
def basic_complete(text, line, begidx, endidx, match_against):
13941396
"""
13951397
Performs tab completion against a list
13961398
@@ -1406,10 +1408,10 @@ def basic_complete(self, text, line, begidx, endidx, match_against):
14061408
return []
14071409

14081410
# Perform matching and eliminate duplicates
1409-
completion_matches = [cur_match for cur_match in set(match_against) if cur_match.startswith(text)]
1411+
matches = [cur_match for cur_match in set(match_against) if cur_match.startswith(text)]
14101412

1411-
completion_matches.sort()
1412-
return completion_matches
1413+
matches.sort()
1414+
return matches
14131415

14141416
def flag_based_complete(self, text, line, begidx, endidx, flag_dict, all_else=None):
14151417
"""
@@ -1475,7 +1477,7 @@ def index_based_complete(self, text, line, begidx, endidx, index_dict, all_else=
14751477
if tokens is None:
14761478
return []
14771479

1478-
completion_matches = []
1480+
matches = []
14791481

14801482
# Get the index of the token being completed
14811483
index = len(tokens) - 1
@@ -1488,15 +1490,16 @@ def index_based_complete(self, text, line, begidx, endidx, index_dict, all_else=
14881490

14891491
# Perform tab completion using an Collection. These matches are already sorted.
14901492
if isinstance(match_against, Collection):
1491-
completion_matches = self.basic_complete(text, line, begidx, endidx, match_against)
1493+
matches = self.basic_complete(text, line, begidx, endidx, match_against)
14921494

14931495
# Perform tab completion using a function
14941496
elif callable(match_against):
1495-
completion_matches = match_against(text, line, begidx, endidx)
1496-
completion_matches.sort()
1497+
matches = match_against(text, line, begidx, endidx)
1498+
matches.sort()
14971499

1498-
return completion_matches
1500+
return matches
14991501

1502+
# noinspection PyUnusedLocal
15001503
def path_complete(self, text, line, begidx, endidx, dir_exe_only=False, dir_only=False):
15011504
"""Performs completion of local file system paths
15021505
@@ -1562,40 +1565,40 @@ def path_complete(self, text, line, begidx, endidx, dir_exe_only=False, dir_only
15621565
search_str = os.path.expanduser(search_str)
15631566

15641567
# Find all matching path completions
1565-
completion_matches = glob.glob(search_str)
1568+
matches = glob.glob(search_str)
15661569

15671570
# Filter based on type
15681571
if dir_exe_only:
1569-
completion_matches = [c for c in completion_matches if os.path.isdir(c) or os.access(c, os.X_OK)]
1572+
matches = [c for c in matches if os.path.isdir(c) or os.access(c, os.X_OK)]
15701573
elif dir_only:
1571-
completion_matches = [c for c in completion_matches if os.path.isdir(c)]
1574+
matches = [c for c in matches if os.path.isdir(c)]
15721575

15731576
# Don't append a space or closing quote to directory
1574-
if len(completion_matches) == 1 and not os.path.isfile(completion_matches[0]):
1577+
if len(matches) == 1 and not os.path.isfile(matches[0]):
15751578
self.allow_appended_space = False
15761579
self.allow_closing_quote = False
15771580

15781581
# Build display_matches and add a slash to directories
1579-
for index, cur_match in enumerate(completion_matches):
1582+
for index, cur_match in enumerate(matches):
15801583

15811584
# Display only the basename of this path in the tab-completion suggestions
15821585
self.display_matches.append(os.path.basename(cur_match))
15831586

15841587
# Add a separator after directories if the next character isn't already a separator
15851588
if os.path.isdir(cur_match) and add_trailing_sep_if_dir:
1586-
completion_matches[index] += os.path.sep
1589+
matches[index] += os.path.sep
15871590
self.display_matches[index] += os.path.sep
15881591

15891592
# Remove cwd if it was added
15901593
if cwd_added:
1591-
completion_matches = [cur_path.replace(cwd + os.path.sep, '', 1) for cur_path in completion_matches]
1594+
matches = [cur_path.replace(cwd + os.path.sep, '', 1) for cur_path in matches]
15921595

15931596
# Restore a tilde if we expanded one
15941597
if tilde_expanded:
1595-
completion_matches = [cur_path.replace(user_path, '~', 1) for cur_path in completion_matches]
1598+
matches = [cur_path.replace(user_path, '~', 1) for cur_path in matches]
15961599

1597-
completion_matches.sort()
1598-
return completion_matches
1600+
matches.sort()
1601+
return matches
15991602

16001603
@staticmethod
16011604
def get_exes_in_path(starts_with):
@@ -1668,7 +1671,7 @@ def _redirect_complete(self, text, line, begidx, endidx, compfunc):
16681671
if self.allow_redirection:
16691672

16701673
# Get all tokens through the one being completed. We want the raw tokens
1671-
# since we need to know if the redirection characters are quoted.
1674+
# so we can tell if redirection strings are quoted and ignore them.
16721675
_, raw_tokens = self.tokens_for_completion(line, begidx, endidx)
16731676
if raw_tokens is None:
16741677
return []
@@ -1678,16 +1681,13 @@ def _redirect_complete(self, text, line, begidx, endidx, compfunc):
16781681
# Build a list of all redirection tokens
16791682
all_redirects = REDIRECTION_CHARS + ['>>']
16801683

1681-
# Check how many redirectors have appeared before the token being completed
1684+
# Check if there are redirection strings prior to the token being completed
16821685
seen_pipe = False
1683-
num_redirectors = 0
1686+
has_redirection = False
16841687

16851688
for cur_token in raw_tokens[:-1]:
16861689
if cur_token in all_redirects:
1687-
num_redirectors += 1
1688-
if num_redirectors > 1:
1689-
# Too many redirectors on the line for tab completion
1690-
return []
1690+
has_redirection = True
16911691

16921692
if cur_token == '|':
16931693
seen_pipe = True
@@ -1703,6 +1703,11 @@ def _redirect_complete(self, text, line, begidx, endidx, compfunc):
17031703
elif prior_token in all_redirects or seen_pipe:
17041704
return self.path_complete(text, line, begidx, endidx)
17051705

1706+
# If there were redirection strings anywhere on the command line, then we
1707+
# are no longer tab completing for the current command
1708+
elif has_redirection:
1709+
return []
1710+
17061711
# Call the command's completer function
17071712
return compfunc(text, line, begidx, endidx)
17081713

@@ -2119,7 +2124,7 @@ def complete_help(self, text, line, begidx, endidx):
21192124
if tokens is None:
21202125
return []
21212126

2122-
completion_matches = []
2127+
matches = []
21232128

21242129
# Get the index of the token being completed
21252130
index = len(tokens) - 1
@@ -2131,16 +2136,16 @@ def complete_help(self, text, line, begidx, endidx):
21312136
topics = set(self.get_help_topics())
21322137
visible_commands = set(self.get_visible_commands())
21332138
strs_to_match = list(topics | visible_commands)
2134-
completion_matches = self.basic_complete(text, line, begidx, endidx, strs_to_match)
2139+
matches = self.basic_complete(text, line, begidx, endidx, strs_to_match)
21352140

21362141
# Check if we are completing a subcommand
21372142
elif index == subcmd_index:
21382143

21392144
# Match subcommands if any exist
21402145
command = tokens[cmd_index]
2141-
completion_matches = self.basic_complete(text, line, begidx, endidx, self.get_subcommands(command))
2146+
matches = self.basic_complete(text, line, begidx, endidx, self.get_subcommands(command))
21422147

2143-
return completion_matches
2148+
return matches
21442149

21452150
# noinspection PyUnusedLocal
21462151
def sigint_handler(self, signum, frame):
@@ -3014,7 +3019,7 @@ def complete_print(self, text, line, begidx, endidx):
30143019
if tokens is None:
30153020
return []
30163021

3017-
completion_matches = []
3022+
matches = []
30183023

30193024
# Get the index of the token being completed
30203025
index = len(tokens) - 1
@@ -3047,11 +3052,11 @@ def complete_print(self, text, line, begidx, endidx):
30473052
completer = 'complete_{}_{}'.format(base, subcommand)
30483053
try:
30493054
compfunc = getattr(self, completer)
3050-
completion_matches = compfunc(text, line, begidx, endidx)
3055+
matches = compfunc(text, line, begidx, endidx)
30513056
except AttributeError:
30523057
pass
30533058

3054-
return completion_matches
3059+
return matches
30553060

30563061
# noinspection PyBroadException
30573062
def do_py(self, arg):

0 commit comments

Comments
 (0)