diff options
| author | Kevin Van Brunt <kmvanbrunt@gmail.com> | 2018-03-18 22:31:59 -0400 |
|---|---|---|
| committer | Kevin Van Brunt <kmvanbrunt@gmail.com> | 2018-03-18 22:31:59 -0400 |
| commit | 51b9056e5edfe3419873562948739dee339cf888 (patch) | |
| tree | 07c87d19394b4bd36b421a86ebd913c4230f6a4b | |
| parent | 1c59c1586718d005ba0087d4cec8eb79e60a9e66 (diff) | |
| download | cmd2-git-51b9056e5edfe3419873562948739dee339cf888.tar.gz | |
Updated remaining completion functions to handle spaces within quotes
| -rwxr-xr-x | cmd2.py | 72 | ||||
| -rw-r--r-- | tests/test_completion.py | 22 |
2 files changed, 56 insertions, 38 deletions
@@ -249,10 +249,17 @@ def basic_complete(text, line, begidx, endidx, match_against): if len(tokens) == 0: return [] - completions = [cur_str for cur_str in match_against if cur_str.startswith(text)] + completion_token = tokens[-1] - # Check if we should add a space to the end of the line - if len(completions) == 1 and not unclosed_quote and endidx == len(line): + # We will only keep where the text value starts + starting_index = len(completion_token) - len(text) + completions = [cur_str[starting_index:] for cur_str in match_against if cur_str.startswith(completion_token)] + + # Check if we should add a closing quote/space to a match at end of the line + if len(completions) == 1 and endidx == len(line): + # Check if we need to close the quote + if unclosed_quote: + completions[0] += unclosed_quote completions[0] += ' ' completions.sort() @@ -293,10 +300,17 @@ def flag_based_complete(text, line, begidx, endidx, flag_dict, all_else=None): # Perform tab completion using an iterable if isinstance(match_against, collections.Iterable): - completions = [cur_str for cur_str in match_against if cur_str.startswith(text)] + completion_token = tokens[-1] + + # We will only keep where the text value starts + starting_index = len(completion_token) - len(text) + completions = [cur_str[starting_index:] for cur_str in match_against if cur_str.startswith(completion_token)] - # Check if we should add a space to the end of the line - if len(completions) == 1 and not unclosed_quote and endidx == len(line): + # Check if we should add a closing quote/space to a match at end of the line + if len(completions) == 1 and endidx == len(line): + # Check if we need to close the quote + if unclosed_quote: + completions[0] += unclosed_quote completions[0] += ' ' # Perform tab completion using a function @@ -343,10 +357,17 @@ def index_based_complete(text, line, begidx, endidx, index_dict, all_else=None): # Perform tab completion using an iterable if isinstance(match_against, collections.Iterable): - completions = [cur_str for cur_str in match_against if cur_str.startswith(text)] + completion_token = tokens[-1] - # Check if we should add a space to the end of the line - if len(completions) == 1 and not unclosed_quote and endidx == len(line): + # We will only keep where the text value starts + starting_index = len(completion_token) - len(text) + completions = [cur_str[starting_index:] for cur_str in match_against if cur_str.startswith(completion_token)] + + # Check if we should add a closing quote/space to a match at end of the line + if len(completions) == 1 and endidx == len(line): + # Check if we need to close the quote + if unclosed_quote: + completions[0] += unclosed_quote completions[0] += ' ' # Perform tab completion using a function @@ -379,40 +400,40 @@ def path_complete(text, line, begidx, endidx, dir_exe_only=False, dir_only=False if endidx == len(line) or (endidx < len(line) and line[endidx] != os.path.sep): add_trailing_sep_if_dir = True - token_being_completed = tokens[-1] + completion_token = tokens[-1] # If the token being completed is blank, then search in the CWD for * - if not token_being_completed: + if not completion_token: search_str = os.path.join(os.getcwd(), '*') else: # Purposely don't match any path containing wildcards - what we are doing is complicated enough! wildcards = ['*', '?'] for wildcard in wildcards: - if wildcard in token_being_completed: + if wildcard in completion_token: return [] # Used if we need to prepend a directory to the search string dirname = '' # If the user only entered a '~', then complete it with a slash - if token_being_completed == '~': + if completion_token == '~': return [os.path.sep] - elif token_being_completed.startswith('~'): + elif completion_token.startswith('~'): # Tilde without separator between path is invalid - if not token_being_completed.startswith('~' + os.path.sep): + if not completion_token.startswith('~' + os.path.sep): return [] # Expand "~" to the real user directory - token_being_completed = os.path.expanduser(token_being_completed) + completion_token = os.path.expanduser(completion_token) # If the token does not have a directory, then use the cwd - elif not os.path.dirname(token_being_completed): + elif not os.path.dirname(completion_token): dirname = os.getcwd() # Build the search string - search_str = os.path.join(dirname, token_being_completed + '*') + search_str = os.path.join(dirname, completion_token + '*') # Find all matching path completions path_completions = glob.glob(search_str) @@ -425,7 +446,7 @@ def path_complete(text, line, begidx, endidx, dir_exe_only=False, dir_only=False # Extract just the completed text portion of the paths completions = [] - starting_index = len(os.path.basename(token_being_completed)) - len(text) + starting_index = len(os.path.basename(completion_token)) - len(text) for c in path_completions: return_str = os.path.basename(c)[starting_index:] @@ -2403,16 +2424,13 @@ Usage: Usage: unalias [-a] name [name ...] # to find the shell command executables cmd_token = tokens[index] - # Look for path characters in the token + # If there are no path characters are in this token, it is OK to try shell command completion. if not (cmd_token.startswith('~') or os.path.sep in cmd_token): - # No path characters are in this token, it is OK to try shell command completion. - exes = self._get_exes_in_path(cmd_token) - - if exes: - # Extract just the completed text portion of the exes - starting_index = len(cmd_token) - len(text) - completions = [c[starting_index:] for c in exes] + # We will only keep where the text value starts + starting_index = len(cmd_token) - len(text) + completions = [cur_str[starting_index:] for cur_str in self._get_exes_in_path(cmd_token)] + if completions: # Check if we should add a closing quote/space to a shell command at end of the line if len(completions) == 1 and endidx == len(line): # Check if we need to close the quote diff --git a/tests/test_completion.py b/tests/test_completion.py index 28e3fe50..5e6aa13d 100644 --- a/tests/test_completion.py +++ b/tests/test_completion.py @@ -482,9 +482,9 @@ def test_basic_completion_single_end(): def test_basic_completion_single_mid(): text = 'Pi' - line = 'list_food -f Pi' - begidx = len(line) - len(text) - endidx = begidx + 1 + line = 'list_food -f Piz' + begidx = len(line) - 3 + endidx = begidx + len(text) assert basic_complete(text, line, begidx, endidx, food_item_strs) == ['Pizza'] @@ -515,9 +515,9 @@ def test_flag_based_completion_single_end(): def test_flag_based_completion_single_mid(): text = 'Pi' - line = 'list_food -f Pi' - begidx = len(line) - len(text) - endidx = begidx + 1 + line = 'list_food -f Piz' + begidx = len(line) - 3 + endidx = begidx + len(text) assert flag_based_complete(text, line, begidx, endidx, flag_dict) == ['Pizza'] @@ -567,7 +567,7 @@ def test_flag_based_completion_quotes(): endidx = len(line) begidx = endidx - len(text) - assert flag_based_complete(text, line, begidx, endidx, flag_dict) == ['Pizza'] + assert flag_based_complete(text, line, begidx, endidx, flag_dict) == ['Pizza" '] def test_flag_based_completion_no_tokens(): text = '' @@ -595,10 +595,10 @@ def test_index_based_completion_single_end(): assert index_based_complete(text, line, begidx, endidx, index_dict) == ['Football '] def test_index_based_completion_single_mid(): - text = 'Foo' + text = 'Fo' line = 'command Pizza Foo' - begidx = len(line) - len(text) - endidx = begidx + 1 + begidx = len(line) - 3 + endidx = begidx + len(text) assert index_based_complete(text, line, begidx, endidx, index_dict) == ['Football'] @@ -646,7 +646,7 @@ def test_index_based_completion_quotes(): endidx = len(line) begidx = endidx - len(text) - assert index_based_complete(text, line, begidx, endidx, index_dict) == ['Pizza'] + assert index_based_complete(text, line, begidx, endidx, index_dict) == ["Pizza' "] def test_parseline_command_and_args(cmd2_app): |
