from method import Method
from method.shell import Interact
from point import Point
from lex import Grammar, PatternRule, RegionRule, OverridePatternRule
from lex import PatternMatchRule
from mode.lisp import StringGrammar2, Lisp, LispTabber

class SchemeGrammar(Grammar):
    rules = [
        PatternRule(r'comment', r';.*$'),
        PatternRule(r'delimiter', r'[()]'),
        RegionRule(r'string', r'"', StringGrammar2, r'"'),
        PatternRule(r'spaces', r' +'),
        PatternRule(r'eol', r'\n'),
        PatternRule(r'abbrev', r"'|`|,\@|,"),

        # from r5rs
        PatternRule(r'scheme_keyword', r'(?:=>|unquote-splicing|unquote|syntax-rules|set!|quote|quasiquote|or|map|loop|letrec-syntax|letrec|let-syntax|let\*|let|lambda|if|for-each|else|dynamic-wind|do|delay|define-syntax|define-macro|define|cond|case|call-with-output-file|call-with-input-file|call-with-current-continuation|begin|and)(?![^\n )])'),

        PatternRule(r'scheme_boolean', r'#[tf]'),
        PatternRule(r'scheme_char', r'#\\space|#\\newline|#\\.'),
        PatternRule(r'scheme_number', '[+-]?[0-9][^ ()\n]+'),
        PatternRule(r'scheme_number', '#[bodx][ie]?[^ ()\n]+'),
        PatternRule(r'scheme_number', '#[ie][bodx]?[^ ()\n]+'),

        PatternRule(r'variable', r'[a-zA-Z!$%&*/:<=>?\^_~][-a-zA-Z0-9!$%&*/:<=>?^_~+.@]*|\+|-|\.\.\.'),
    ]

class SchemeCheckSyntax(Method):
    '''Check the syntax of a scheme file'''
    def _execute(self, w, **vargs):
        app = w.application
        cmd = "guile -s %r" % (w.buffer.path)
        (status, output) = commands.getstatusoutput(cmd)
        if status == 0:
            app.set_error("Syntax OK")
            app.data_buffer("*Scheme-Check-Syntax*", output, switch_to=False)
        else:
            app.data_buffer("*Scheme-Check-Syntax*", output)

class GuileStart(Interact):
    args = []
    reuse = True
    def _execute(self, w, **vargs):
        Interact._execute(self, w, bname='*Guile*', cmd='guile')

class GuileLoadFile(Interact):
    args = []
    reuse = True
    def _execute(self, w, **vargs):
        Interact._execute(self, w, bname='*Guile*', cmd='guile')
        b = w.application.get_buffer_by_name('*Guile*')
        path = os.path.realpath(w.buffer.path)
        b.pipe_write('(load "%s")\n' % path)

class Scheme(Lisp):
    name        = 'Scheme'
    extensions  = ['.scm']
    grammar     = SchemeGrammar
    colors      = {
        'scheme_keyword': ('cyan', 'default', 'bold'),
        'scheme_char':    ('green', 'default', 'bold'),
        'scheme_boolean': ('magenta', 'default', 'bold'),
        'scheme_number':  ('default', 'default', 'bold'),
    }
    actions = [SchemeCheckSyntax, GuileStart, GuileLoadFile]
    _bindings = {
        'close-paren':         (')',),
        'close-brace':         ('}',),
        'close-bracket':       (']',),
        'scheme-check-syntax': ('C-c s',),
    }

install = Scheme.install