from lex import Grammar, PatternRule, RegionRule, OverrideRegionRule
from mode import Fundamental
from method import Method, WrapParagraph
from mode.text import TextInsertSpace
from mode.python import PythonGrammar

def make_string_rules(forbid):
    return [
        PatternRule('escaped', r'\\.'),
        PatternRule('data', r'[^\\' + forbid + ']+'),
    ]

class LineGrammar(Grammar): rules = [PatternRule('data', r'^.*\n$')]
class RSTString1(Grammar): rules = make_string_rules('*')
class RSTString2(Grammar): rules = make_string_rules('`')
class RSTString3(Grammar): rules = make_string_rules('|')

class RSTGrammar(Grammar):
    rules = [
        PatternRule(r'escape', r'\\.'),

        PatternRule(r'bullet', r'^ *[-*+](?=$| )'),
        PatternRule(r'enumeration', r'^ *(?:[0-9]+|#)\.(?=$| )'),

        RegionRule(r'strong_emphasis', r'\*\*', RSTString1, r'\*\*'),
        RegionRule(r'emphasis', r'\*', RSTString1, r'\*'),
        RegionRule(r'inline_literal', r'``', RSTString2, r'``'),
        RegionRule(r'interpreted', r'`', RSTString2, r'`_?'),

        PatternRule(r'anonymous', r'[a-zA-Z]+__'),
        PatternRule(r'reference', r'[a-zA-Z]+_(?![a-zA-Z0-9_])'),
        RegionRule(r'inline_internal', r'_`', RSTString2, r'`'),

        RegionRule(r'substitution', r'\|(?! )', RSTString3, r'\|'),
        PatternRule(r'footnote', r'\[[0-9]+\]_'),
        PatternRule(r'citation', r'\[.+?\]_'),
        PatternRule(r'rst_url', r'http://[^ ]+'),

        PatternRule(r'title', r'^={3,}\n$'),
        PatternRule(r'subtitle', r'^-{3,}\n$'),

        PatternRule(r'option', r'^(?:--|-|/)[a-zA-Z]+(?:[ =][-a-zA-Z_]+)?'),
        RegionRule(r'table', r'\+-+(\+-+)*\+\n$', LineGrammar, r'^\n$'),

        PatternRule(r'field', r'^:.+?:'),

        PatternRule(r'lineblock', r'^\|'),
        RegionRule(r'blocktest', r'>>>', PythonGrammar, '^\n'),
        OverrideRegionRule(r'code', r'^\.\. code-block:: +(?P<grammar>.+)\n$', None, r'^(?=[^\n ])'),
        RegionRule(r'literal_block', r'::\n$', LineGrammar, r'^(?=[^\n ])'),

        PatternRule('rst_word', r'[a-zA-Z]+'),
        PatternRule('spaces', ' +'),
        PatternRule('eol', ' +'),
        PatternRule('rst_null', r'.'),
    ]

class RstWrapParagraph(WrapParagraph):
    limit = 75
class RstInsertSpace(TextInsertSpace):
    limit   = 75
    wrapper = RstWrapParagraph

class RstBuild(Method):
    pass

class RST(Fundamental):
    name       = 'RST'
    extensions = ['.rst']
    grammar    = RSTGrammar
    colors     = {
        'title':     ('blue', 'default', 'bold'),
        'subtitle':  ('blue', 'default'),
        'field':     ('green', 'default', 'bold'),
        'option':    ('green', 'default', 'bold'),
        'anonymous': ('blue', 'default', 'bold'),
        'reference': ('blue', 'default', 'bold'),
        'footnote':  ('blue', 'default', 'bold'),
        'citation':  ('blue', 'default', 'bold'),
        'rst_url':   ('blue', 'default', 'bold'),

        'table.start': ('cyan', 'default'),
        'table.data':  ('cyan', 'default'),
        'table.null':  ('cyan', 'default'),

        'bullet':      ('magenta', 'default', 'bold'),
        'enumeration': ('magenta', 'default', 'bold'),

        'lineblock':       ('cyan', 'default', 'bold'),
        'blocktest.start': ('cyan', 'default', 'bold'),

        'emphasis.start':        ('red', 'default'),
        'emphasis.data':         ('red', 'default'),
        'emphasis.null':         ('red', 'default'),
        'emphasis.end':          ('red', 'default'),
        'strong_emphasis.start': ('red', 'default', 'bold'),
        'strong_emphasis.data':  ('red', 'default', 'bold'),
        'strong_emphasis.null':  ('red', 'default', 'bold'),
        'strong_emphasis.end':   ('red', 'default', 'bold'),
        'interpreted.start':     ('magenta', 'default'),
        'interpreted.data':      ('magenta', 'default'),
        'interpreted.null':      ('magenta', 'default'),
        'interpreted.end':       ('magenta', 'default'),
        'inline_literal.start':  ('magenta', 'default', 'bold'),
        'inline_literal.data':   ('magenta', 'default', 'bold'),
        'inline_literal.null':   ('magenta', 'default', 'bold'),
        'inline_literal.end':    ('magenta', 'default', 'bold'),
        'inline_internal.start': ('yellow', 'default'),
        'inline_internal.data':  ('yellow', 'default'),
        'inline_internal.null':  ('yellow', 'default'),
        'inline_internal.end':   ('magenta', 'default'),
        'substitution.start':    ('cyan', 'default', 'bold'),
        'substitution.data':     ('cyan', 'default', 'bold'),
        'substitution.null':     ('cyan', 'default', 'bold'),
        'substitution.end':      ('cyan', 'default', 'bold'),

        'code.start':          ('yellow', 'default', 'bold'),
        'literal_block.start': ('yellow', 'default'),
        'literal_block.data':  ('yellow', 'default'),
        'literal_block.null':  ('yellow', 'default'),
    }
    actions = [RstInsertSpace, RstWrapParagraph]
    config = {
        'rst.margin': 75,
    }
    _bindings = {
        'rst-insert-space': ('SPACE',),
        'rst-wrap-paragraph': ('M-q',),
    }

install = RST.install