Skip to content

Commit bebf547

Browse files
committed
Added delimiter_complete function
1 parent 48b21fc commit bebf547

1 file changed

Lines changed: 58 additions & 0 deletions

File tree

cmd2.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1413,6 +1413,64 @@ def basic_complete(text, line, begidx, endidx, match_against):
14131413
matches.sort()
14141414
return matches
14151415

1416+
def delimiter_complete(self, text, line, begidx, endidx, match_against, delimiter):
1417+
"""
1418+
Performs tab completion against a list but each match is split on a delimiter and only
1419+
the portion of the match being tab completed is shown as the completion suggestions.
1420+
This is useful if you match against strings that are hierarchical in nature and have a
1421+
common delimiter.
1422+
1423+
An easy way to illustrate this concept is path completion since paths are just directories/files
1424+
delimited by a slash. If you are tab completing items in /home/user you don't get the following
1425+
as suggestions:
1426+
1427+
/home/user/file.txt /home/user/program.c
1428+
/home/user/maps/ /home/user/cmd2.py
1429+
1430+
Instead you are shown:
1431+
1432+
file.txt program.c
1433+
maps/ cmd2.py
1434+
1435+
For a large set of data, this can be visually more pleasing and easier to search.
1436+
1437+
Another example would be strings formatted with the following syntax: company::department::name
1438+
In this case the delimiter would be :: and the user could easily narrow down what they are looking
1439+
for if they were only shown suggestions in the category they are at in the string.
1440+
1441+
:param text: str - the string prefix we are attempting to match (all returned matches must begin with it)
1442+
:param line: str - the current input line with leading whitespace removed
1443+
:param begidx: int - the beginning index of the prefix text
1444+
:param endidx: int - the ending index of the prefix text
1445+
:param match_against: Collection - the list being matched against
1446+
:param delimiter: str - what delimits each portion of the matches (ex: paths are delimited by a slash)
1447+
:return: List[str] - a sorted list of possible tab completions
1448+
"""
1449+
matches = self.basic_complete(text, line, begidx, endidx, match_against)
1450+
1451+
# Display only the portion of the match that's being completed based on delimiter
1452+
if len(matches) > 0:
1453+
1454+
# Get the common beginning for the matches
1455+
common_prefix = os.path.commonprefix(matches)
1456+
prefix_tokens = common_prefix.split(delimiter)
1457+
1458+
# Calculate what portion of the match we are completing
1459+
display_token_index = 0
1460+
if len(prefix_tokens) > 0:
1461+
display_token_index = len(prefix_tokens) - 1
1462+
1463+
# Get this portion for each match and store them in self.display_matches
1464+
for cur_match in matches:
1465+
match_tokens = cur_match.split(delimiter)
1466+
display_token = match_tokens[display_token_index]
1467+
1468+
if len(display_token) == 0:
1469+
display_token = delimiter
1470+
self.display_matches.append(display_token)
1471+
1472+
return matches
1473+
14161474
def flag_based_complete(self, text, line, begidx, endidx, flag_dict, all_else=None):
14171475
"""
14181476
Tab completes based on a particular flag preceding the token being completed

0 commit comments

Comments
 (0)