diff options
-rwxr-xr-x | cmd2/cmd2.py | 2 | ||||
-rw-r--r-- | cmd2/parsing.py | 15 | ||||
-rw-r--r-- | tests/test_cmd2.py | 2 | ||||
-rw-r--r-- | tests/test_shlexparsing.py | 41 |
4 files changed, 36 insertions, 24 deletions
diff --git a/cmd2/cmd2.py b/cmd2/cmd2.py index d9cbd2b0..8165f411 100755 --- a/cmd2/cmd2.py +++ b/cmd2/cmd2.py @@ -2181,7 +2181,7 @@ class Cmd(cmd.Cmd): # raise EmptyStatement() # statement = self.parser_manager.parsed(line) # deleteme statement = self.command_parser.parseString(line) - while statement.multilineCommand and (statement.terminator == ''): + while statement.multilineCommand and not statement.terminator: line = '%s\n%s' % (statement.raw, self.pseudo_raw_input(self.continuation_prompt)) statement = self.command_parser.parseString(line) diff --git a/cmd2/parsing.py b/cmd2/parsing.py index f4f9a6a3..2c01fb70 100644 --- a/cmd2/parsing.py +++ b/cmd2/parsing.py @@ -7,6 +7,8 @@ import shlex import cmd2 +BLANK_LINE = '\n\n' + class Statement(str): """String subclass with additional attributes to store the results of parsing. @@ -85,13 +87,19 @@ class CommandParser(): line = line.replace(shortcut, expansion, 1) break + # handle the special case/hardcoded terminator of a blank line + # we have to do this before we shlex on whitespace because it + # destroys all unquoted whitespace in the input + terminator = None + if line[-2:] == BLANK_LINE: + terminator = BLANK_LINE + s = shlex.shlex(line, posix=False) s.whitespace_split = True tokens = self.split_on_punctuation(list(s)) # of the valid terminators, find the first one to occur in the input terminator_pos = len(tokens)+1 - terminator = None for test_terminator in self.terminators: try: pos = tokens.index(test_terminator) @@ -104,7 +112,10 @@ class CommandParser(): pass if terminator: - terminator_pos = tokens.index(terminator) + if terminator == BLANK_LINE: + terminator_pos = len(tokens)+1 + else: + terminator_pos = tokens.index(terminator) # everything before the first terminator is the command and the args (command, args) = self._command_and_args(tokens[:terminator_pos]) #terminator = tokens[terminator_pos] diff --git a/tests/test_cmd2.py b/tests/test_cmd2.py index f2ee16af..068ea08f 100644 --- a/tests/test_cmd2.py +++ b/tests/test_cmd2.py @@ -1358,7 +1358,7 @@ def test_multiline_complete_statement_without_terminator(multiline_app): line = '{} {}'.format(command, args) statement = multiline_app._complete_statement(line) assert statement == args - assert statement.parsed.command == command + assert statement.command == command def test_clipboard_failure(capsys): diff --git a/tests/test_shlexparsing.py b/tests/test_shlexparsing.py index d0907820..269a5753 100644 --- a/tests/test_shlexparsing.py +++ b/tests/test_shlexparsing.py @@ -232,9 +232,10 @@ def test_parse_multiline_command_ignores_redirectors_within_it(parser): # """A terminator within a comment will be ignored and won't terminate a multiline command. # Un-closed comments effectively comment out everything after the start.""" # line = 'multiline command /* with comment in progress;' -# results = parser.parseString(line) -# assert results.multilineCommand == 'multiline' -# assert not 'args' in results +# statement = parser.parseString(line) +# assert statement.multilineCommand == 'multiline' +# assert statement.args == 'command' +# assert not statement.terminator def test_parse_multiline_with_complete_comment(parser): line = 'multiline command /* with comment complete */ is done;' @@ -243,23 +244,23 @@ def test_parse_multiline_with_complete_comment(parser): assert results.args == 'command is done' assert results.terminator == ';' -# def test_parse_multiline_termninated_by_empty_line(parser): -# line = 'multiline command ends\n\n' -# results = parser.parseString(line) -# assert results.multilineCommand == 'multiline' -# assert results.args == 'command ends' -# assert len(results.terminator) == 2 -# assert results.terminator[0] == '\n' -# assert results.terminator[1] == '\n' - -# def test_parse_multiline_ignores_terminators_in_comments(parser): -# line = 'multiline command "with term; ends" now\n\n' -# results = parser.parseString(line) -# assert results.multilineCommand == 'multiline' -# assert results.args == 'command "with term; ends" now' -# assert len(results.terminator) == 2 -# assert results.terminator[0] == '\n' -# assert results.terminator[1] == '\n' +def test_parse_multiline_termninated_by_empty_line(parser): + line = 'multiline command ends\n\n' + results = parser.parseString(line) + assert results.multilineCommand == 'multiline' + assert results.args == 'command ends' + assert len(results.terminator) == 2 + assert results.terminator[0] == '\n' + assert results.terminator[1] == '\n' + +def test_parse_multiline_ignores_terminators_in_comments(parser): + line = 'multiline command "with term; ends" now\n\n' + results = parser.parseString(line) + assert results.multilineCommand == 'multiline' + assert results.args == 'command "with term; ends" now' + assert len(results.terminator) == 2 + assert results.terminator[0] == '\n' + assert results.terminator[1] == '\n' def test_parse_command_with_unicode_args(parser): line = 'drink café' |