<commit_before># coding=utf-8
"""
Test the parsing logic in parsing.py

Copyright 2017 <NAME> <<EMAIL>>
Released under MIT license, see LICENSE file
"""
import pytest

from cmd2 import cmd2
from cmd2.parsing import StatementParser

from cmd2 import utils

@pytest.fixture
def parser():
    parser = StatementParser(
        allow_redirection=True,
        terminators=[';'],
        multiline_commands=['multiline'],
        aliases={'helpalias': 'help',
                 '42': 'theanswer',
                 'l': '!ls -al',
                 'anothermultiline': 'multiline',
                 'fake': 'pyscript'},
        shortcuts=[('?', 'help'), ('!', 'shell')]
    )
    return parser

def test_parse_empty_string(parser):
    statement = parser.parse('')
    assert not statement.command
    assert not statement.args
    assert statement.raw == ''

@pytest.mark.parametrize('line,tokens', [
    ('command', ['command']),
    ('command /* with some comment */ arg', ['command', 'arg']),
    ('command arg1 arg2 # comment at the end', ['command', 'arg1', 'arg2']),
    ('42 arg1 arg2', ['theanswer', 'arg1', 'arg2']),
    ('l', ['shell', 'ls', '-al'])
])
def test_tokenize(parser, line, tokens):
    tokens_to_test = parser.tokenize(line)
    assert tokens_to_test == tokens

@pytest.mark.parametrize('tokens,command,args', [
    ([], None, None),
    (['command'], 'command', None),
    (['command', 'arg1', 'arg2'], 'command', 'arg1 arg2')
])
def test_parse_command_and_args(parser, tokens, command, args):
    (parsed_command, parsed_args) = parser._command_and_args(tokens)
    assert command == parsed_command
    assert args == parsed_args

@pytest.mark.parametrize('line', [
    'plainword',
    '"one word"',
    "'one word'",
])
def test_parse_single_word(parser, line):
    statement = parser.parse(line)
    assert statement.command == line
    assert not statement.args
    assert statement.argv == [utils.strip_quotes(line)]

def test_parse_word_plus_terminator(parser):
    line = 'termbare;'
    statement = parser.parse(line)
    assert statement.command == 'termbare'
    assert statement.terminator == ';'
    assert statement.argv == ['termbare']

def test_parse_suffix_after_terminator(parser):
    line = 'termbare; suffx'
    statement = parser.parse(line)
    assert statement.command == 'termbare'
    assert statement.terminator == ';'
    assert statement.suffix == 'suffx'
    assert statement.argv == ['termbare']

def test_parse_command_with_args(parser):
    line = 'command with args'
    statement = parser.parse(line)
    assert statement.command == 'command'
    assert statement.args == 'with args'
    assert statement.argv == ['command', 'with', 'args']

def test_parse_command_with_quoted_args(parser):
    line = 'command with "quoted args" and "some not"'
    statement = parser.parse(line)
    assert statement.command == 'command'
    assert statement.args == 'with "quoted args" and "some not"'
    assert statement.argv == ['command', 'with', 'quoted args', 'and', 'some not']

def test_parse_command_with_args_terminator_and_suffix(parser):
    line = 'command with args and terminator; and suffix'
    statement = parser.parse(line)
    assert statement.command == 'command'
    assert statement.args == "with args and terminator"
    assert statement.terminator == ';'
    assert statement.suffix == 'and suffix'
    assert statement.argv == ['command', 'with', 'args', 'and', 'terminator']

def test_parse_hashcomment(parser):
    statement = parser.parse('hi # this is all a comment')
    assert statement.command == 'hi'
    assert not statement.args
    assert statement.argv == ['hi']

def test_parse_c_comment(parser):
    statement = parser.parse('hi /* this is | all a comment */')
    assert statement.command == 'hi'
    assert not statement.args
    assert not statement.pipe_to
    assert statement.argv == ['hi']

def test_parse_c_comment_empty(parser):
    statement = parser.parse('/* this is | all a comment */')
    assert not statement.command
    assert not statement.args
    assert not statement.pipe_to
    assert not statement.argv

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'
    assert statement.args == 'if "quoted strings /* seem to " start comments?'
    assert not statement.pipe_to
    assert statement.argv == ['what', 'if', 'quoted strings /* seem to ', 'start', 'comments?']

@pytest.mark.parametrize('line',[
    'simple | piped',
    'simple|piped',
])
def test_parse_simple_pipe(parser, line):
    statement = parser.parse(line)
    assert statement.command == 'simple'
    assert not statement.args
    assert statement.argv == ['simple']
    assert statement.pipe_to == 'piped'

def test_parse_double_pipe_is_not_a_pipe(parser):
    line = 'double-pipe || is not a pipe'
    statement = parser.parse(line)
    assert statement.command == 'double-pipe'
    assert statement.args == '|| is not a pipe'
    assert statement.argv == ['double-pipe', '||', 'is', 'not', 'a', 'pipe']
    assert not statement.pipe_to

def test_parse_complex_pipe(parser):
    line = 'command with args, terminator;sufx | piped'
    statement = parser.parse(line)
    assert statement.command == 'command'
    assert statement.args == "with args, terminator"
    assert statement.argv == ['command', 'with', 'args,', 'terminator']
    assert statement.terminator == ';'
    assert statement.suffix == 'sufx'
    assert statement.pipe_to == 'piped'

@pytest.mark.parametrize('line,output', [
    ('help > out.txt', '>'),
    ('help>out.txt', '>'),
    ('help >> out.txt', '>>'),
    ('help>>out.txt', '>>'),
])
def test_parse_redirect(parser,line):
    statement = parser.parse(line)
    assert statement.command == 'help'
    assert not statement.args
    assert statement.output == '>'
    assert statement.output_to == 'out.txt'

def test_parse_redirect_with_args(parser):
    line = 'output into > afile.txt'
    statement = parser.parse(line)
    assert statement.command == 'output'
    assert statement.args == 'into'
    assert statement.argv == ['output', 'into']
    assert statement.output == '>'
    assert statement.output_to == 'afile.txt'

def test_parse_redirect_with_dash_in_path(parser):
    line = 'output into > python-cmd2/afile.txt'
    statement = parser.parse(line)
    assert statement.command == 'output'
    assert statement.args == 'into'
    assert statement.argv == ['output', 'into']
    assert statement.output == '>'
    assert statement.output_to == 'python-cmd2/afile.txt'

def test_parse_redirect_append(parser):
    line = 'output appended to >> /tmp/afile.txt'
    statement = parser.parse(line)
    assert statement.command == 'output'<commit_msg>Oops, fixed an oversight that broke the build<commit_after># coding=utf-8
"""
Test the parsing logic in parsing.py

Copyright 2017 <NAME> <<EMAIL>>
Released under MIT license, see LICENSE file
"""
import pytest

from cmd2 import cmd2
from cmd2.parsing import StatementParser

from cmd2 import utils

@pytest.fixture
def parser():
    parser = StatementParser(
        allow_redirection=True,
        terminators=[';'],
        multiline_commands=['multiline'],
        aliases={'helpalias': 'help',
                 '42': 'theanswer',
                 'l': '!ls -al',
                 'anothermultiline': 'multiline',
                 'fake': 'pyscript'},
        shortcuts=[('?', 'help'), ('!', 'shell')]
    )
    return parser

def test_parse_empty_string(parser):
    statement = parser.parse('')
    assert not statement.command
    assert not statement.args
    assert statement.raw == ''

@pytest.mark.parametrize('line,tokens', [
    ('command', ['command']),
    ('command /* with some comment */ arg', ['command', 'arg']),
    ('command arg1 arg2 # comment at the end', ['command', 'arg1', 'arg2']),
    ('42 arg1 arg2', ['theanswer', 'arg1', 'arg2']),
    ('l', ['shell', 'ls', '-al'])
])
def test_tokenize(parser, line, tokens):
    tokens_to_test = parser.tokenize(line)
    assert tokens_to_test == tokens

@pytest.mark.parametrize('tokens,command,args', [
    ([], None, None),
    (['command'], 'command', None),
    (['command', 'arg1', 'arg2'], 'command', 'arg1 arg2')
])
def test_parse_command_and_args(parser, tokens, command, args):
    (parsed_command, parsed_args) = parser._command_and_args(tokens)
    assert command == parsed_command
    assert args == parsed_args

@pytest.mark.parametrize('line', [
    'plainword',
    '"one word"',
    "'one word'",
])
def test_parse_single_word(parser, line):
    statement = parser.parse(line)
    assert statement.command == line
    assert not statement.args
    assert statement.argv == [utils.strip_quotes(line)]

def test_parse_word_plus_terminator(parser):
    line = 'termbare;'
    statement = parser.parse(line)
    assert statement.command == 'termbare'
    assert statement.terminator == ';'
    assert statement.argv == ['termbare']

def test_parse_suffix_after_terminator(parser):
    line = 'termbare; suffx'
    statement = parser.parse(line)
    assert statement.command == 'termbare'
    assert statement.terminator == ';'
    assert statement.suffix == 'suffx'
    assert statement.argv == ['termbare']

def test_parse_command_with_args(parser):
    line = 'command with args'
    statement = parser.parse(line)
    assert statement.command == 'command'
    assert statement.args == 'with args'
    assert statement.argv == ['command', 'with', 'args']

def test_parse_command_with_quoted_args(parser):
    line = 'command with "quoted args" and "some not"'
    statement = parser.parse(line)
    assert statement.command == 'command'
    assert statement.args == 'with "quoted args" and "some not"'
    assert statement.argv == ['command', 'with', 'quoted args', 'and', 'some not']

def test_parse_command_with_args_terminator_and_suffix(parser):
    line = 'command with args and terminator; and suffix'
    statement = parser.parse(line)
    assert statement.command == 'command'
    assert statement.args == "with args and terminator"
    assert statement.terminator == ';'
    assert statement.suffix == 'and suffix'
    assert statement.argv == ['command', 'with', 'args', 'and', 'terminator']

def test_parse_hashcomment(parser):
    statement = parser.parse('hi # this is all a comment')
    assert statement.command == 'hi'
    assert not statement.args
    assert statement.argv == ['hi']

def test_parse_c_comment(parser):
    statement = parser.parse('hi /* this is | all a comment */')
    assert statement.command == 'hi'
    assert not statement.args
    assert not statement.pipe_to
    assert statement.argv == ['hi']

def test_parse_c_comment_empty(parser):
    statement = parser.parse('/* this is | all a comment */')
    assert not statement.command
    assert not statement.args
    assert not statement.pipe_to
    assert not statement.argv

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'
    assert statement.args == 'if "quoted strings /* seem to " start comments?'
    assert not statement.pipe_to
    assert statement.argv == ['what', 'if', 'quoted strings /* seem to ', 'start', 'comments?']

@pytest.mark.parametrize('line',[
    'simple | piped',
    'simple|piped',
])
def test_parse_simple_pipe(parser, line):
    statement = parser.parse(line)
    assert statement.command == 'simple'
    assert not statement.args
    assert statement.argv == ['simple']
    assert statement.pipe_to == 'piped'

def test_parse_double_pipe_is_not_a_pipe(parser):
    line = 'double-pipe || is not a pipe'
    statement = parser.parse(line)
    assert statement.command == 'double-pipe'
    assert statement.args == '|| is not a pipe'
    assert statement.argv == ['double-pipe', '||', 'is', 'not', 'a', 'pipe']
    assert not statement.pipe_to

def test_parse_complex_pipe(parser):
    line = 'command with args, terminator;sufx | piped'
    statement = parser.parse(line)
    assert statement.command == 'command'
    assert statement.args == "with args, terminator"
    assert statement.argv == ['command', 'with', 'args,', 'terminator']
    assert statement.terminator == ';'
    assert statement.suffix == 'sufx'
    assert statement.pipe_to == 'piped'

@pytest.mark.parametrize('line,output', [
    ('help > out.txt', '>'),
    ('help>out.txt', '>'),
    ('help >> out.txt', '>>'),
    ('help>>out.txt', '>>'),
])
def test_parse_redirect(parser,line, output):
    statement = parser.parse(line)
    assert statement.command == 'help'
    assert not statement.args
    assert statement.output == output
    assert statement.output_to == 'out.txt'

def test_parse_redirect_with_args(parser):
    line = 'output into > afile.txt'
    statement = parser.parse(line)
    assert statement.command == 'output'
    assert statement.args == 'into'
    assert statement.argv == ['output', 'into']
    assert statement.output == '>'
    assert statement.output_to == 'afile.txt'

def test_parse_redirect_with_dash_in_path(parser):
    line = 'output into > python-cmd2/afile.txt'
    statement = parser.parse(line)
    assert statement.command == 'output'
    assert statement.args == 'into'
    assert statement.argv == ['output', 'into']
    assert statement.output == '>'
    assert statement.output_to == 'python-cmd2/afile.txt'

def test_parse_redirect_append(parser):
    line = 'output appended to >> /tmp/afile.txt'
    statement = parser.parse(line)
    assert statement.command == 'output'
{'fraction_non_alphanumeric': 0.14455445544554454, 'fraction_numerical': 0.0039603960396039604, 'mean_word_length': 3.796341892367218, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 46, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3586962', 'n_tokens_mistral': 4182, 'n_tokens_neox': 4150, 'n_words': 1068}