diff options
-rw-r--r-- | cmd2/parsing.py | 15 | ||||
-rw-r--r-- | tests/test_parsing.py | 109 |
2 files changed, 84 insertions, 40 deletions
diff --git a/cmd2/parsing.py b/cmd2/parsing.py index 61b6f745..8edfacb9 100644 --- a/cmd2/parsing.py +++ b/cmd2/parsing.py @@ -452,13 +452,16 @@ class StatementParser: This method is used by tab completion code and therefore must not generate an exception if there are unclosed quotes. - The Statement object returned by this method can at most contain values + The `Statement` object returned by this method can at most contain values in the following attributes: - args - raw - command - multiline_command + `Statement.args` includes all output redirection clauses and command + terminators. + Different from parse(), this method does not remove redundant whitespace within args. However, it does ensure args has no leading or trailing whitespace. @@ -473,12 +476,10 @@ class StatementParser: # we got a match, extract the command command = match.group(1) - # the _command_pattern regex is designed to match the spaces - # between command and args with a second match group. Using - # the end of the second match group ensures that args has - # no leading whitespace. The rstrip() makes sure there is - # no trailing whitespace - args = line[match.end(2):].rstrip() + # take everything from the end of the first match group to + # the end of the line as the arguments (stripping leading + # and trailing spaces) + args = line[match.end(1):].strip() # if the command is empty that means the input was either empty # or something weird like '>'. args should be empty if we couldn't # parse a command diff --git a/tests/test_parsing.py b/tests/test_parsing.py index b0d370ac..9cf9429a 100644 --- a/tests/test_parsing.py +++ b/tests/test_parsing.py @@ -584,77 +584,109 @@ def test_parse_command_only_command_and_args(parser): statement = parser.parse_command_only(line) assert statement == 'history' assert statement.args == statement - assert statement.raw == line + assert statement.arg_list == [] assert statement.command == 'help' assert statement.command_and_args == line - assert statement.arg_list == [] assert statement.multiline_command == '' + assert statement.raw == line assert statement.terminator == '' assert statement.suffix == '' assert statement.pipe_to == [] assert statement.output == '' assert statement.output_to == '' -def test_parse_command_only_emptyline(parser): - line = '' - statement = parser.parse_command_only(line) - # statement is a subclass of str(), the value of the str - # should be '', to retain backwards compatibility with - # the cmd in the standard library - assert statement.command == '' - assert statement == '' - assert statement.args == statement - assert not statement.argv - assert not statement.arg_list - assert statement.command_and_args == '' - def test_parse_command_only_strips_line(parser): line = ' help history ' statement = parser.parse_command_only(line) - assert statement.command == 'help' assert statement == 'history' assert statement.args == statement + assert statement.arg_list == [] + assert statement.command == 'help' assert statement.command_and_args == line.strip() + assert statement.multiline_command == '' + assert statement.raw == line + assert statement.terminator == '' + assert statement.suffix == '' + assert statement.pipe_to == [] + assert statement.output == '' + assert statement.output_to == '' def test_parse_command_only_expands_alias(parser): - line = 'fake foobar.py' + line = 'fake foobar.py "somebody.py' statement = parser.parse_command_only(line) - assert statement.command == 'pyscript' - assert statement == 'foobar.py' + assert statement == 'foobar.py "somebody.py' assert statement.args == statement + assert statement.arg_list == [] + assert statement.command == 'pyscript' + assert statement.command_and_args == 'pyscript foobar.py "somebody.py' + assert statement.multiline_command == '' + assert statement.raw == line + assert statement.terminator == '' + assert statement.suffix == '' + assert statement.pipe_to == [] + assert statement.output == '' + assert statement.output_to == '' def test_parse_command_only_expands_shortcuts(parser): line = '!cat foobar.txt' statement = parser.parse_command_only(line) - assert statement.command == 'shell' assert statement == 'cat foobar.txt' assert statement.args == statement + assert statement.arg_list == [] + assert statement.command == 'shell' assert statement.command_and_args == 'shell cat foobar.txt' + assert statement.multiline_command == '' + assert statement.raw == line + assert statement.multiline_command == '' + assert statement.terminator == '' + assert statement.suffix == '' + assert statement.pipe_to == [] + assert statement.output == '' + assert statement.output_to == '' def test_parse_command_only_quoted_args(parser): line = 'l "/tmp/directory with spaces/doit.sh"' statement = parser.parse_command_only(line) - assert statement.command == 'shell' assert statement == 'ls -al "/tmp/directory with spaces/doit.sh"' assert statement.args == statement + assert statement.arg_list == [] + assert statement.command == 'shell' assert statement.command_and_args == line.replace('l', 'shell ls -al') + assert statement.multiline_command == '' + assert statement.raw == line + assert statement.multiline_command == '' + assert statement.terminator == '' + assert statement.suffix == '' + assert statement.pipe_to == [] + assert statement.output == '' + assert statement.output_to == '' -@pytest.mark.parametrize('line', [ - 'helpalias > out.txt', - 'helpalias>out.txt', - 'helpalias >> out.txt', - 'helpalias>>out.txt', - 'help|less', - 'helpalias;', - 'help ;;', - 'help; ;;', +@pytest.mark.parametrize('line,args', [ + ('helpalias > out.txt', '> out.txt'), + ('helpalias>out.txt', '>out.txt'), + ('helpalias >> out.txt', '>> out.txt'), + ('helpalias>>out.txt', '>>out.txt'), + ('help|less', '|less'), + ('helpalias;', ';'), + ('help ;;', ';;'), + ('help; ;;', '; ;;'), ]) -def test_parse_command_only_specialchars(parser, line): +def test_parse_command_only_specialchars(parser, line, args): statement = parser.parse_command_only(line) + assert statement == args + assert statement.args == args assert statement.command == 'help' - assert statement.args == statement + assert statement.multiline_command == '' + assert statement.raw == line + assert statement.multiline_command == '' + assert statement.terminator == '' + assert statement.suffix == '' + assert statement.pipe_to == [] + assert statement.output == '' + assert statement.output_to == '' @pytest.mark.parametrize('line', [ + '', ';', ';;', ';; ;', @@ -668,8 +700,19 @@ def test_parse_command_only_specialchars(parser, line): ]) def test_parse_command_only_empty(parser, line): statement = parser.parse_command_only(line) - assert statement.command == '' assert statement == '' + assert statement.args == statement + assert statement.arg_list == [] + assert statement.command == '' + assert statement.command_and_args == '' + assert statement.multiline_command == '' + assert statement.raw == line + assert statement.multiline_command == '' + assert statement.terminator == '' + assert statement.suffix == '' + assert statement.pipe_to == [] + assert statement.output == '' + assert statement.output_to == '' def test_parse_command_only_multiline(parser): line = 'multiline with partially "open quotes and no terminator' |