Beispiel #1
0
def test_backslash_z(compiler_state):
    # similar to text.git-commit grammar, \z matches nothing!
    compiler, state = compiler_state({
        'scopeName':
        'test',
        'patterns': [
            {
                'begin': '#',
                'end': r'\z',
                'name': 'comment'
            },
            {
                'name': 'other',
                'match': '.'
            },
        ],
    })

    state, regions1 = highlight_line(compiler, state, '# comment', True)
    state, regions2 = highlight_line(compiler, state, 'other?', False)

    assert regions1 == (
        Region(0, 1, ('test', 'comment')),
        Region(1, 9, ('test', 'comment')),
    )

    assert regions2 == (Region(0, 6, ('test', 'comment')), )
Beispiel #2
0
def test_captures_ignores_empty(compiler_state):
    compiler, state = compiler_state({
        'scopeName':
        'test',
        'patterns': [{
            'match': '(.*) hi',
            'captures': {
                '1': {
                    'name': 'before'
                }
            },
        }],
    })

    state, regions1 = highlight_line(compiler, state, ' hi\n', True)
    state, regions2 = highlight_line(compiler, state, 'o hi\n', False)

    assert regions1 == (
        Region(0, 3, ('test', )),
        Region(3, 4, ('test', )),
    )
    assert regions2 == (
        Region(0, 1, ('test', 'before')),
        Region(1, 4, ('test', )),
        Region(4, 5, ('test', )),
    )
Beispiel #3
0
def test_captures_implies_begin_while_captures(compiler_state):
    compiler, state = compiler_state({
        'scopeName':
        'test',
        'patterns': [
            {
                'begin': '(>) ',
                'while': '(>) ',
                'captures': {
                    '1': {
                        'name': 'block'
                    }
                },
            },
        ],
    })

    state, regions1 = highlight_line(compiler, state, '> x\n', True)
    state, regions2 = highlight_line(compiler, state, '> x\n', False)

    assert regions1 == (
        Region(0, 1, ('test', 'block')),
        Region(1, 2, ('test', )),
        Region(2, 4, ('test', )),
    )

    assert regions2 == (
        Region(0, 1, ('test', 'block')),
        Region(1, 2, ('test', )),
        Region(2, 4, ('test', )),
    )
Beispiel #4
0
def test_while_no_nl(compiler_state):
    compiler, state = compiler_state({
        'scopeName': 'test',
        'patterns': [{
            'begin': '> ',
            'while': '> ',
            'contentName': 'while',
            'patterns': [
                {'match': r'\Ga', 'name': 'ga'},
                {'match': 'a', 'name': 'noga'},
            ],
        }],
    })

    state, regions1 = highlight_line(compiler, state, '> aa\n', True)
    state, regions2 = highlight_line(compiler, state, '> aa\n', False)
    state, regions3 = highlight_line(compiler, state, 'after\n', False)

    assert regions1 == (
        Region(0, 2, ('test',)),
        Region(2, 3, ('test', 'while', 'ga')),
        Region(3, 4, ('test', 'while', 'noga')),
        Region(4, 5, ('test', 'while')),
    )
    assert regions2 == (
        Region(0, 2, ('test', 'while')),
        Region(2, 3, ('test', 'while', 'ga')),
        Region(3, 4, ('test', 'while', 'noga')),
        Region(4, 5, ('test', 'while')),
    )
    assert regions3 == (
        Region(0, 6, ('test',)),
    )
Beispiel #5
0
def test_include_base(compiler_state):
    compiler, state = compiler_state(
        {
            'scopeName':
            'test',
            'patterns': [
                {
                    'begin': '<',
                    'end': '>',
                    'name': 'bracket',
                    # $base from root grammar includes itself
                    'patterns': [{
                        'include': '$base'
                    }],
                },
                {
                    'include': 'other.grammar'
                },
                {
                    'match': 'z',
                    'name': 'testz'
                },
            ],
        },
        {
            'scopeName':
            'other.grammar',
            'patterns': [
                {
                    'begin': '`',
                    'end': '`',
                    'name': 'tick',
                    # $base from included grammar includes the root
                    'patterns': [{
                        'include': '$base'
                    }],
                },
            ],
        },
    )

    state, regions1 = highlight_line(compiler, state, '<z>\n', True)
    state, regions2 = highlight_line(compiler, state, '`z`\n', False)

    assert regions1 == (
        Region(0, 1, ('test', 'bracket')),
        Region(1, 2, ('test', 'bracket', 'testz')),
        Region(2, 3, ('test', 'bracket')),
        Region(3, 4, ('test', )),
    )

    assert regions2 == (
        Region(0, 1, ('test', 'tick')),
        Region(1, 2, ('test', 'tick', 'testz')),
        Region(2, 3, ('test', 'tick')),
        Region(3, 4, ('test', )),
    )
Beispiel #6
0
def test_include_other_grammar(compiler_state):
    compiler, state = compiler_state(
        {
            'scopeName': 'test',
            'patterns': [
                {
                    'begin': '<',
                    'end': '>',
                    'name': 'angle',
                    'patterns': [{'include': 'other.grammar'}],
                },
                {
                    'begin': '`',
                    'end': '`',
                    'name': 'tick',
                    'patterns': [{'include': 'other.grammar#backtick'}],
                },
            ],
        },
        {
            'scopeName': 'other.grammar',
            'patterns': [
                {'match': 'a', 'name': 'roota'},
                {'match': '.', 'name': 'rootother'},
            ],
            'repository': {
                'backtick': {
                    'patterns': [
                        {'match': 'a', 'name': 'ticka'},
                        {'match': '.', 'name': 'tickother'},
                    ],
                },
            },
        },
    )

    state, regions1 = highlight_line(compiler, state, '<az>\n', True)
    state, regions2 = highlight_line(compiler, state, '`az`\n', False)

    assert regions1 == (
        Region(0, 1, ('test', 'angle')),
        Region(1, 2, ('test', 'angle', 'roota')),
        Region(2, 3, ('test', 'angle', 'rootother')),
        Region(3, 4, ('test', 'angle')),
        Region(4, 5, ('test',)),
    )

    assert regions2 == (
        Region(0, 1, ('test', 'tick')),
        Region(1, 2, ('test', 'tick', 'ticka')),
        Region(2, 3, ('test', 'tick', 'tickother')),
        Region(3, 4, ('test', 'tick')),
        Region(4, 5, ('test',)),
    )
Beispiel #7
0
def test_backslash_g_captures_nl(compiler_state):
    compiler, state = compiler_state(BEGIN_END_NL)

    state, regions1 = highlight_line(compiler, state, 'x\n', True)
    state, regions2 = highlight_line(compiler, state, 'aax\n', False)

    assert regions1 == (Region(0, 2, ('test', )), )
    assert regions2 == (
        Region(0, 1, ('test', 'ga')),
        Region(1, 2, ('test', 'noga')),
        Region(2, 3, ('test', )),
        Region(3, 4, ('test', )),
    )
Beispiel #8
0
def test_backslash_a(compiler_state):
    grammar = {
        'scopeName': 'test',
        'patterns': [{'name': 'aaa', 'match': r'\Aa+'}],
    }
    compiler, state = compiler_state(grammar)

    state, (region_0,) = highlight_line(compiler, state, 'aaa', True)
    state, (region_1,) = highlight_line(compiler, state, 'aaa', False)

    # \A should only match at the beginning of the file
    assert region_0 == Region(0, 3, ('test', 'aaa'))
    assert region_1 == Region(0, 3, ('test',))
Beispiel #9
0
def test_include_with_nested_repositories(compiler_state):
    compiler, state = compiler_state({
        'scopeName': 'test',
        'patterns': [{
            'begin': '<', 'end': '>', 'name': 'b',
            'patterns': [
                {'include': '#rule1'},
                {'include': '#rule2'},
                {'include': '#rule3'},
            ],
            'repository': {
                'rule2': {'match': '2', 'name': 'inner2'},
                'rule3': {'match': '3', 'name': 'inner3'},
            },
        }],
        'repository': {
            'rule1': {'match': '1', 'name': 'root1'},
            'rule2': {'match': '2', 'name': 'root2'},
        },
    })

    state, regions = highlight_line(compiler, state, '<123>', first_line=True)

    assert regions == (
        Region(0, 1, ('test', 'b')),
        Region(1, 2, ('test', 'b', 'root1')),
        Region(2, 3, ('test', 'b', 'inner2')),
        Region(3, 4, ('test', 'b', 'inner3')),
        Region(4, 5, ('test', 'b')),
    )
Beispiel #10
0
def test_complex_captures(compiler_state):
    compiler, state = compiler_state({
        'scopeName': 'test',
        'patterns': [
            {
                'match': '(<).([^>]+)(>)',
                'captures': {
                    '1': {'name': 'lbracket'},
                    '2': {
                        'patterns': [
                            {'match': 'a', 'name': 'a'},
                            {'match': 'z', 'name': 'z'},
                        ],
                    },
                    '3': {'name': 'rbracket'},
                },
            },
        ],
    })

    state, regions = highlight_line(compiler, state, '<qabz>', first_line=True)
    assert regions == (
        Region(0, 1, ('test', 'lbracket')),
        Region(1, 2, ('test',)),
        Region(2, 3, ('test', 'a')),
        Region(3, 4, ('test',)),
        Region(4, 5, ('test', 'z')),
        Region(5, 6, ('test', 'rbracket')),
    )
Beispiel #11
0
def test_captures_begin_end(compiler_state):
    compiler, state = compiler_state({
        'scopeName':
        'test',
        'patterns': [
            {
                'begin': '(""")',
                'end': '(""")',
                'beginCaptures': {
                    '1': {
                        'name': 'startquote'
                    }
                },
                'endCaptures': {
                    '1': {
                        'name': 'endquote'
                    }
                },
            },
        ],
    })

    state, regions = highlight_line(compiler, state, '"""x"""', True)

    assert regions == (
        Region(0, 3, ('test', 'startquote')),
        Region(3, 4, ('test', )),
        Region(4, 7, ('test', 'endquote')),
    )
Beispiel #12
0
    def _hl_uncached(
        self,
        state: State,
        line: str,
        first_line: bool,
    ) -> Tuple[State, HLs]:
        new_state, regions = highlight_line(
            self._compiler,
            state,
            f'{line}\n',
            first_line=first_line,
        )

        # remove the trailing newline
        new_end = regions[-1]._replace(end=regions[-1].end - 1)
        regions = regions[:-1] + (new_end, )

        regs: List[HL] = []
        for r in regions:
            style = self._theme.select(r.scope)
            if style == self._theme.default:
                continue

            attr = self.attr(style)
            if (regs and regs[-1].attr == attr and regs[-1].end == r.start):
                regs[-1] = regs[-1]._replace(end=r.end)
            else:
                regs.append(HL(x=r.start, end=r.end, attr=attr))

        return new_state, tuple(regs)
Beispiel #13
0
def test_rule_with_begin_and_no_end(compiler_state):
    compiler, state = compiler_state({
        'scopeName':
        'test',
        'patterns': [
            {
                'begin': '!',
                'end': '!',
                'name': 'bang',
                'patterns': [{
                    'begin': '--',
                    'name': 'invalid'
                }],
            },
        ],
    })

    state, regions = highlight_line(compiler, state, '!x! !--!', True)

    assert regions == (
        Region(0, 1, ('test', 'bang')),
        Region(1, 2, ('test', 'bang')),
        Region(2, 3, ('test', 'bang')),
        Region(3, 4, ('test', )),
        Region(4, 5, ('test', 'bang')),
        Region(5, 7, ('test', 'bang', 'invalid')),
        Region(7, 8, ('test', 'bang', 'invalid')),
    )
Beispiel #14
0
def test_include_repository_rule(compiler_state):
    compiler, state = compiler_state({
        'scopeName': 'test',
        'patterns': [{
            'include': '#impl'
        }],
        'repository': {
            'impl': {
                'patterns': [
                    {
                        'match': 'a',
                        'name': 'a'
                    },
                    {
                        'match': '.',
                        'name': 'other'
                    },
                ],
            },
        },
    })

    state, regions = highlight_line(compiler, state, 'az', first_line=True)

    assert regions == (
        Region(0, 1, ('test', 'a')),
        Region(1, 2, ('test', 'other')),
    )
Beispiel #15
0
def test_include_self(compiler_state):
    compiler, state = compiler_state({
        'scopeName':
        'test',
        'patterns': [
            {
                'begin': '<',
                'end': '>',
                'contentName': 'bracketed',
                'patterns': [{
                    'include': '$self'
                }],
            },
            {
                'match': '.',
                'name': 'content'
            },
        ],
    })

    state, regions = highlight_line(compiler, state, '<<_>>', first_line=True)
    assert regions == (
        Region(0, 1, ('test', )),
        Region(1, 2, ('test', 'bracketed')),
        Region(2, 3, ('test', 'bracketed', 'bracketed', 'content')),
        Region(3, 4, ('test', 'bracketed', 'bracketed')),
        Region(4, 5, ('test', 'bracketed')),
    )
Beispiel #16
0
def test_backslash_g_inline(compiler_state):
    compiler, state = compiler_state(BEGIN_END_NO_NL)

    _, regions = highlight_line(compiler, state, 'xaax', True)
    assert regions == (
        Region(0, 1, ('test', )),
        Region(1, 2, ('test', 'ga')),
        Region(2, 3, ('test', 'noga')),
        Region(3, 4, ('test', )),
    )
Beispiel #17
0
def test_end_before_other_match(compiler_state):
    compiler, state = compiler_state(BEGIN_END_NO_NL)

    state, regions = highlight_line(compiler, state, 'xazzx', True)

    assert regions == (
        Region(0, 1, ('test', )),
        Region(1, 2, ('test', 'ga')),
        Region(2, 4, ('test', )),
        Region(4, 5, ('test', )),
    )
Beispiel #18
0
def test_captures_ignores_invalid_out_of_bounds(compiler_state):
    compiler, state = compiler_state({
        'scopeName': 'test',
        'patterns': [{'match': '.', 'captures': {'1': {'name': 'oob'}}}],
    })

    state, regions = highlight_line(compiler, state, 'x', first_line=True)

    assert regions == (
        Region(0, 1, ('test',)),
    )
Beispiel #19
0
def _highlight_output(theme: Theme, compiler: Compiler, filename: str) -> int:
    state = compiler.root_state

    if theme.default.bg is not None:
        print('\x1b[48;2;{r};{g};{b}m'.format(**theme.default.bg._asdict()))
    with open(filename, encoding='UTF-8') as f:
        for line_idx, line in enumerate(f):
            first_line = line_idx == 0
            state, regions = highlight_line(compiler, state, line, first_line)
            for start, end, scope in regions:
                print_styled(line[start:end], theme.select(scope))
    print('\x1b[m', end='')
    return 0
Beispiel #20
0
def test_begin_end_substitute_special_chars(compiler_state):
    compiler, state = compiler_state({
        'scopeName': 'test',
        'patterns': [{'begin': r'(\*)', 'end': r'\1', 'name': 'italic'}],
    })

    state, regions = highlight_line(compiler, state, '*italic*', True)

    assert regions == (
        Region(0, 1, ('test', 'italic')),
        Region(1, 7, ('test', 'italic')),
        Region(7, 8, ('test', 'italic')),
    )
Beispiel #21
0
def test_captures_multiple_applied_to_same_capture(compiler_state):
    compiler, state = compiler_state({
        'scopeName': 'test',
        'patterns': [
            {
                'match': '((a)) ((b) c) (d (e)) ((f) )',
                'name': 'matched',
                'captures': {
                    '1': {'name': 'g1'},
                    '2': {'name': 'g2'},
                    '3': {'name': 'g3'},
                    '4': {'name': 'g4'},
                    '5': {'name': 'g5'},
                    '6': {'name': 'g6'},
                    '7': {
                        'patterns': [
                            {'match': 'f', 'name': 'g7f'},
                            {'match': ' ', 'name': 'g7space'},
                        ],
                    },
                    # this one has to backtrack some
                    '8': {'name': 'g8'},
                },
            },
        ],
    })

    state, regions = highlight_line(compiler, state, 'a b c d e f ', True)

    assert regions == (
        Region(0, 1, ('test', 'matched', 'g1', 'g2')),
        Region(1, 2, ('test', 'matched')),
        Region(2, 3, ('test', 'matched', 'g3', 'g4')),
        Region(3, 5, ('test', 'matched', 'g3')),
        Region(5, 6, ('test', 'matched')),
        Region(6, 8, ('test', 'matched', 'g5')),
        Region(8, 9, ('test', 'matched', 'g5', 'g6')),
        Region(9, 10, ('test', 'matched')),
        Region(10, 11, ('test', 'matched', 'g7f', 'g8')),
        Region(11, 12, ('test', 'matched', 'g7space')),
    )
Beispiel #22
0
def test_buggy_begin_end_grammar(compiler_state):
    # before this would result in an infinite loop of start / end
    compiler, state = compiler_state({
        'scopeName':
        'test',
        'patterns': [
            {
                'begin': '(?=</style)',
                'end': '(?=</style)',
                'name': 'css',
            },
        ],
    })

    state, regions = highlight_line(compiler, state, 'test </style', True)

    assert regions == (
        Region(0, 5, ('test', )),
        Region(5, 6, ('test', 'css')),
        Region(6, 12, ('test', )),
    )