import commands, os.path, sets, string, sys, traceback
import color, completer, default, mode, method, regex, tab
from point import Point
from lex import Grammar, PatternRule, RegionRule, OverridePatternRule
from mode.python import StringGrammar2
from method import CommentRegion, UncommentRegion

class LispGrammar(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'),
    ]

class LispCommentRegion(CommentRegion):
    commentc = ';'
class LispUncommentRegion(UncommentRegion):
    commentc = ';'

class LispTabber(tab.StackTabber):
    wsre = regex.whitespace
    wst  = ('spaces', 'null', 'eol',)
    sre  = regex.space
    st   = ('spaces', 'null',)
    def _handle_open_token(self, currlvl, y, i):
        token  = self.get_token(y, i)
        rtoken = self.get_next_right_token(y, i)
        if rtoken is None:
            level = self.get_curr_level() + self.mode.tabwidth
        elif rtoken.string not in ('(', 'define', 'lambda'):
            rtoken = self.get_next_right_token(y, i + 1)
            if rtoken is None or rtoken.string != '(':
                level = self.get_curr_level() + self.mode.tabwidth
            else:
                level = rtoken.x
        else:
            level = self.get_curr_level() + self.mode.tabwidth
        self._append(token.string, level)
        return currlvl

class Lisp(mode.Fundamental):
    modename    = 'Lisp'
    tabwidth    = 2
    tabbercls   = LispTabber
    grammar     = LispGrammar
    opentokens  = ('delimiter',)
    opentags    = {'(': ')'}
    closetokens = ('delimiter',)
    closetags   = {')': '('}
    actions     = [LispCommentRegion, LispUncommentRegion]

    def __init__(self, w):
        mode.Fundamental.__init__(self, w)
        self.add_bindings('close-paren', (')',))
        self.add_bindings('close-brace', ('}',))
        self.add_bindings('close-bracket', (']',))
        self.add_action_and_bindings('lisp-comment-region', ('C-c #',))
        self.add_action_and_bindings('lisp-uncomment-region', ('C-u C-C #',))

install = Lisp.install