summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Van Brunt <kmvanbrunt@gmail.com>2018-03-27 03:00:10 -0400
committerKevin Van Brunt <kmvanbrunt@gmail.com>2018-03-27 03:00:10 -0400
commit0ef0e9bde9d32728d6aabdbb7964dafe6e83efb7 (patch)
tree2ebfc6742226bd1082b6ea7021f50e748f543637
parentce7612051978393ca9eb19dc6ad1e7f003e7cc4d (diff)
downloadcmd2-git-0ef0e9bde9d32728d6aabdbb7964dafe6e83efb7.tar.gz
Fixed a case where display_matches wasn't being set. Added unit tests.
-rwxr-xr-xcmd2.py27
-rw-r--r--tests/test_completion.py54
2 files changed, 59 insertions, 22 deletions
diff --git a/cmd2.py b/cmd2.py
index 9235d7f5..87f4da2c 100755
--- a/cmd2.py
+++ b/cmd2.py
@@ -1330,8 +1330,8 @@ class Cmd(cmd.Cmd):
for cur_initial_token in initial_tokens:
- # Keep empty and quoted tokens
- if len(cur_initial_token) == 0 or cur_initial_token[0] in QUOTES:
+ # Save tokens up to 1 character in length or quoted tokens. No need to parse these.
+ if len(cur_initial_token) <= 1 or cur_initial_token[0] in QUOTES:
raw_tokens.append(cur_initial_token)
continue
@@ -2068,20 +2068,23 @@ class Cmd(cmd.Cmd):
self.completion_matches = []
return None
- # Check if we need to remove text from the beginning of tab completions
- if text_to_remove:
- self.completion_matches = [m.replace(text_to_remove, '', 1) for m in self.completion_matches]
-
- # Check if we need to restore a shortcut in the tab completions
- if shortcut_to_restore:
+ if text_to_remove or shortcut_to_restore:
# If self.display_matches is empty, then set it to self.completion_matches
- # before we restore the shortcut so the tab completion suggestions that display to
- # the user don't have the shortcut character.
+ # before we alter them. That way the suggestions will reflect how we parsed
+ # the token being completed and not how readline did.
if len(self.display_matches) == 0:
self.display_matches = self.completion_matches
- # Prepend all tab completions with the shortcut so it doesn't get erased from the command line
- self.completion_matches = [shortcut_to_restore + match for match in self.completion_matches]
+ # Check if we need to remove text from the beginning of tab completions
+ if text_to_remove:
+ self.completion_matches = \
+ [m.replace(text_to_remove, '', 1) for m in self.completion_matches]
+
+ # Check if we need to restore a shortcut in the tab completions
+ # so it doesn't get erased from the command line
+ if shortcut_to_restore:
+ self.completion_matches = \
+ [shortcut_to_restore + match for match in self.completion_matches]
# Check if the token being completed has an unclosed quote
if len(raw_completion_token) == 1:
diff --git a/tests/test_completion.py b/tests/test_completion.py
index 5817334e..8c2fd55d 100644
--- a/tests/test_completion.py
+++ b/tests/test_completion.py
@@ -177,18 +177,27 @@ def test_cmd2_help_completion_nomatch(cmd2_app):
assert cmd2_app.complete_help(text, line, begidx, endidx) == []
-def test_shell_command_completion(cmd2_app):
+def test_shell_command_completion_shortcut(cmd2_app):
+ # Made sure ! runs a shell command and all matches start with ! since there
+ # isn't a space between ! and the shell command. Display matches won't
+ # begin with the !.
if sys.platform == "win32":
- text = 'calc'
- expected = ['calc.exe']
+ text = '!calc'
+ expected = ['!calc.exe ']
+ expected_display = ['calc.exe']
else:
- text = 'egr'
- expected = ['egrep']
+ text = '!egr'
+ expected = ['!egrep ']
+ expected_display = ['egrep']
- line = 'shell {}'.format(text)
+ line = text
endidx = len(line)
- begidx = endidx - len(text)
- assert cmd2_app.complete_shell(text, line, begidx, endidx) == expected
+ begidx = 0
+
+ first_match = complete_tester(text, line, begidx, endidx, cmd2_app)
+ assert first_match is not None and \
+ cmd2_app.completion_matches == expected and \
+ cmd2_app.display_matches == expected_display
def test_shell_command_completion_doesnt_match_wildcards(cmd2_app):
if sys.platform == "win32":
@@ -742,7 +751,7 @@ def test_cmd2_help_subcommand_completion_nomatch(sc_app):
def test_subcommand_tab_completion(sc_app):
# This makes sure the correct completer for the sport subcommand is called
text = 'Foot'
- line = 'base sport Foot'
+ line = 'base sport {}'.format(text)
endidx = len(line)
begidx = endidx - len(text)
@@ -755,12 +764,37 @@ def test_subcommand_tab_completion_with_no_completer(sc_app):
# This tests what happens when a subcommand has no completer
# In this case, the foo subcommand has no completer defined
text = 'Foot'
- line = 'base foo Foot'
+ line = 'base foo {}'.format(text)
+ endidx = len(line)
+ begidx = endidx - len(text)
+
+ first_match = complete_tester(text, line, begidx, endidx, sc_app)
+ assert first_match is None
+
+def test_subcommand_tab_completion_add_quote(sc_app):
+ # This makes sure an opening quote is added to the readline line buffer
+ text = 'Space'
+ line = 'base sport {}'.format(text)
endidx = len(line)
begidx = endidx - len(text)
first_match = complete_tester(text, line, begidx, endidx, sc_app)
+
+ # No matches are returned when an opening quote is added to the screen
assert first_match is None
+ assert readline.get_line_buffer() == 'base sport "Space Ball" '
+
+def test_subcommand_tab_completion_space_in_text(sc_app):
+ text = 'B'
+ line = 'base sport "Space {}'.format(text)
+ endidx = len(line)
+ begidx = endidx - len(text)
+
+ first_match = complete_tester(text, line, begidx, endidx, sc_app)
+
+ assert first_match is not None and \
+ sc_app.completion_matches == ['Ball" '] and \
+ sc_app.display_matches == ['Space Ball']
class SecondLevel(cmd2.Cmd):
"""To be used as a second level command class. """