summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd2/parsing.py18
-rw-r--r--tests/test_parsing.py23
2 files changed, 26 insertions, 15 deletions
diff --git a/cmd2/parsing.py b/cmd2/parsing.py
index 0d480f0f..475554b0 100644
--- a/cmd2/parsing.py
+++ b/cmd2/parsing.py
@@ -152,25 +152,23 @@ class StatementParser:
# double or single quotes.
#
# this big regular expression can be broken down into 3 regular
- # expressions that are OR'ed together.
+ # expressions that are OR'ed together with a pipe character
#
- # /\*.*?(\*/|$) matches C-style comments, with an optional
- # closing '*/'. The optional closing '*/' is
- # there to retain backward compatibility with
- # the pyparsing implementation of cmd2 < 0.9.0
- # \'(?:\\.|[^\\\'])*\' matches a single quoted string, allowing
+ # /\*.*\*/ Matches C-style comments (i.e. /* comment */)
+ # does not match unclosed comments.
+ # \'(?:\\.|[^\\\'])*\' Matches a single quoted string, allowing
# for embedded backslash escaped single quote
- # marks
- # "(?:\\.|[^\\"])*" matches a double quoted string, allowing
+ # marks.
+ # "(?:\\.|[^\\"])*" Matches a double quoted string, allowing
# for embedded backslash escaped double quote
- # marks
+ # marks.
#
# by way of reminder the (?:...) regular expression syntax is just
# a non-capturing version of regular parenthesis. We need the non-
# capturing syntax because _comment_replacer() looks at match
# groups
self.comment_pattern = re.compile(
- r'/\*.*?(\*/|$)|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"',
+ r'/\*.*\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"',
re.DOTALL | re.MULTILINE
)
diff --git a/tests/test_parsing.py b/tests/test_parsing.py
index 7a091720..6e795660 100644
--- a/tests/test_parsing.py
+++ b/tests/test_parsing.py
@@ -180,6 +180,20 @@ def test_parse_c_comment_empty(parser):
assert not statement.argv
assert statement == ''
+def test_parse_c_comment_no_closing(parser):
+ statement = parser.parse('cat /tmp/*.txt')
+ assert statement.command == 'cat'
+ assert statement.args == '/tmp/*.txt'
+ assert not statement.pipe_to
+ assert statement.argv == ['cat', '/tmp/*.txt']
+
+def test_parse_c_comment_multiple_opening(parser):
+ statement = parser.parse('cat /tmp/*.txt /tmp/*.cfg')
+ assert statement.command == 'cat'
+ assert statement.args == '/tmp/*.txt /tmp/*.cfg'
+ assert not statement.pipe_to
+ assert statement.argv == ['cat', '/tmp/*.txt', '/tmp/*.cfg']
+
def test_parse_what_if_quoted_strings_seem_to_start_comments(parser):
statement = parser.parse('what if "quoted strings /* seem to " start comments?')
assert statement.command == 'what'
@@ -344,14 +358,13 @@ def test_parse_multiline_command_ignores_redirectors_within_it(parser, line, ter
def test_parse_multiline_with_incomplete_comment(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;'
+ line = 'multiline command /* with unclosed comment;'
statement = parser.parse(line)
assert statement.multiline_command == 'multiline'
assert statement.command == 'multiline'
- assert statement.args == 'command'
- assert statement == statement.args
- assert statement.argv == ['multiline', 'command']
- assert not statement.terminator
+ assert statement.args == 'command /* with unclosed comment'
+ assert statement.argv == ['multiline', 'command', '/*', 'with', 'unclosed', 'comment']
+ assert statement.terminator == ';'
def test_parse_multiline_with_complete_comment(parser):
line = 'multiline command /* with comment complete */ is done;'