import commands, os.path, string, sys, traceback
import color, completer, default, mode, method, regex, tab
from point import Point
from lex import Grammar, PatternRule, RegionRule, OverridePatternRule
from mode.lisp import LispTabber

class StringGrammar(Grammar):
    rules = [
        PatternRule(r'octal', r'\\[0-7]{3}'),
        PatternRule(r'escaped', r'\\.'),
        PatternRule(r'data', r'[^\\"]+'),
    ]

class ELispGrammar(Grammar):
    rules = [
        PatternRule(r'comment', r';.*$'),
        PatternRule(r'delimiter', r'[()]'),
        PatternRule(r'elisp_reserved', r'(?:nil)(?![a-zA-Z0-9_])'),
        PatternRule(r'elisp_keyword', r'(?:while|when|unless|setq-default|setq|require|or|not|mapcar|list|let|lambda|if|exists|equal|defvar|defun|defalias|count|cons|cdr|car|apply|and)(?![a-zA-Z0-9_])'),
        PatternRule(r'elisp_symbol', r"'[a-zA-Z_][a-zA-Z0-9-_]*"),
        PatternRule(r'elisp_type', r":[a-zA-Z_][a-zA-Z0-9-_]*"),
        PatternRule(r'attribute', r"&[a-zA-Z_][a-zA-Z0-9-_]*"),
        PatternRule(r'bareword', r"[a-zA-Z_][a-zA-Z0-9-_]*"),
        PatternRule(r"integer", r"(?<![\.0-9a-zA-Z_])(?:0|-?[1-9][0-9]*|0[0-7]+|0[xX][0-9a-fA-F]+)[lL]?(?![\.0-9a-zA-Z_])"),
        PatternRule(r"float", r"(?<![\.0-9a-zA-Z_])(?:[0-9]+\.[0-9]*|\.[0-9]+|(?:[0-9]|[0-9]+\.[0-9]*|\.[0-9]+)[eE][\+-]?[0-9]+)(?![\.0-9a-zA-Z_])"),
        PatternRule(r"imaginary", r"(?<![\.0-9a-zA-Z_])(?:[0-9]+|(?:[0-9]+\.[0-9]*|\.[0-9]+|(?:[0-9]|[0-9]+\.[0-9]*|\.[0-9]+)[eE][\+-]?[0-9]+)[jJ])(?![\.0-9a-zA-Z_])"),
        RegionRule(r'string', r'"', StringGrammar, r'"'),
        PatternRule(r'eol', r'\n$'),
    ]

class ELisp(mode.Fundamental):
    modename    = 'ELisp'
    tabwidth    = 2
    basenames   = ['.emacs']
    extensions  = ['.el']
    tabbercls   = LispTabber
    grammar     = ELispGrammar
    commentc    = ';'
    opentokens  = ('delimiter',)
    opentags    = {'(': ')', '[': ']', '{': '}'}
    closetokens = ('delimiter',)
    closetags   = {')': '(', ']': '[', '}': '{'}
    colors      = {
        'elisp_keyword':  ('cyan', 'default', 'bold'),
        'elisp_reserved': ('blue', 'default', 'bold'),
        'elisp_symbol':   ('magenta', 'default', 'bold'),
        'elisp_type':     ('blue', 'default', 'bold'),
    }
    _bindings = {
        'close-paren': (')',),
        'close-brace': ('}',),
        'close-bracket': (']',),
    }

install = ELisp.install