diff --git a/application.py b/application.py index c9fdf06..fe9a567 100755 --- a/application.py +++ b/application.py @@ -29,7 +29,10 @@ class Application(object): self.input = keyinput.Handler() # let's prepopulate some default token colors + self.cached_colors = {} self.token_colors = { + 'spaces': ('default', 'default'), + 'eol': ('default', 'default'), 'comment': ('red', 'default', 'bold'), 'comment.start': ('red', 'default', 'bold'), 'comment.data': ('red', 'default', 'bold'), diff --git a/lex.py b/lex.py index a5592cb..b457da5 100755 --- a/lex.py +++ b/lex.py @@ -7,16 +7,20 @@ def escape(s): class Token(object): def __init__(self, name, rule, y, x, s, color=None, parent=None, matchd={}, link=None): - self.name = name - self.rule = rule - self.y = y - self.x = x - self.string = s - self.color = color - self.parent = parent - self.matchd = matchd - self.link = link - self._debug = False + self.name = name + self.rule = rule + self.y = y + self.x = x + self.string = s + self.color = color + self.parent = parent + self.matchd = matchd + self.link = link + self._debug = False + #self._fqlist = None + #self._fqname = None + #self._fqlist = self.mkfqlist() + #self._fqname = self.mkfqname() assert parent is None or hasattr(parent, 'name'), 'oh no %r' % parent def match(self, name, string): @@ -54,6 +58,11 @@ class Token(object): if self.link and not self.link.startswith('middle'): names.append(self.rule.name) return names + #def fqlist(self): + # if self._fqlist is None: + # self._fqlist = self.mkfqlist() + # return self._fqlist + #def mkfqlist(self): def fqlist(self): if self.parent is not None: names = self.parent.domain() @@ -63,6 +72,11 @@ class Token(object): names.append(self.rule.name) names.append(self.name) return names + #def fqname(self): + # if self._fqname is None: + # self._fqname = self.mkfqname() + # return self._fqname + #def mkfqname(self): def fqname(self): names = self.fqlist() return '.'.join(names) @@ -540,15 +554,25 @@ class Lexer(object): raise StopIteration def get_color(self, token): - fqlist = token.fqlist() - if self.mstack: - mode = self.mstack[-1] - else: - mode = self.mode - app = mode.window.application - for j in range(0, len(fqlist)): - name = '.'.join(fqlist[j:]) - if name in app.token_colors: - assert type(app.token_colors[name]) == type(()), repr(mode) - return app.token_colors[name] + app = self.mode.window.application + name = '.'.join(token.fqlist()) + + if name in app.token_colors: + return app.token_colors[name] + elif name in app.cached_colors: + return app.cached_colors[name] + + name2 = name + while name2: + try: + i = name2.index('.') + name2 = name2[i + 1:] + except ValueError: + break + if name2 in app.token_colors: + c = app.token_colors[name2] + app.cached_colors[name] = c + return c + + app.cached_colors[name] = app.config['default_color'] return app.config['default_color'] diff --git a/mode/c.py b/mode/c.py index 5653e45..f763866 100644 --- a/mode/c.py +++ b/mode/c.py @@ -36,55 +36,55 @@ class MacroGrammar(Grammar): class CGrammar(Grammar): rules = [ - PatternRule('spaces', r' +'), + PatternRule('c.spaces', r' +'), PatternMatchRule('x', r'(\()( *)(' + word + r')(\**)( *)(\))( *)(?=[a-zA-Z0-9_\(])', - 'delimiter', 'spaces', 'type', 'operator', 'spaces', 'delimiter', - 'spaces'), - #PatternMatchRule('x', r'(\()(' + word + r')(\))', - # 'delimiter', 'type', 'delimiter'), + 'c.delimiter', 'c.spaces', 'c.type', 'c.operator', + 'c.spaces', 'c.delimiter', 'c.spaces'), - PatternRule(r"delimiter", r"\.|\(|\)|\[|\]|{|}|@|,|:|`|;|=(?!=)|\?|->"), - PatternRule('eol', r"\n$"), + PatternRule(r"c.delimiter", r"\.|\(|\)|\[|\]|{|}|@|,|:|`|;|=(?!=)|\?|->"), + PatternRule('c.eol', r"\n$"), PatternMatchRule('x', r'(struct|enum|union)( +)(' + word + ')', - 'builtin', 'spaces', 'type'), + 'c.builtin', 'c.spaces', 'c.type'), - PatternRule('builtin', r"(?:break|case|continue|default|do|else|for|goto|if|return|sizeof|switch|while)(?!" + chr2 + ")"), - PatternRule('builtin', r"(?:signed|register|extern|const|static|enum|struct|typedef|union|unsigned|volatile)(?!" + chr2 + ")"), - PatternRule('type', r"(?:auto|char|double|float|int|long|short|void|volatile)(?!" + chr2 + ")"), + PatternRule('c.builtin', r"(?:break|case|continue|default|do|else|for|goto|if|return|sizeof|switch|while)(?!" + chr2 + ")"), + PatternRule('c.builtin', r"(?:signed|register|extern|const|static|enum|struct|typedef|union|unsigned|volatile)(?!" + chr2 + ")"), + PatternRule('c.type', r"(?:auto|char|double|float|int|long|short|void|volatile)(?!" + chr2 + ")"), PatternMatchRule('x', '(' + word + ')( +)(\**)(' + word + ')( *)(\()', - 'type', 'spaces', 'operator', 'function', 'spaces', 'delimiter'), + 'c.type', 'c.spaces', 'c.operator', 'c.function', + 'c.spaces', 'c.delimiter'), PatternMatchRule('x', '(' + word + ')(\*+)( +)(' + word + ')( *)(\()', - 'type', 'operator', 'spaces', 'function', 'spaces', 'delimiter'), + 'c.type', 'c.operator', 'c.spaces', 'c.function', + 'c.spaces', 'c.delimiter'), PatternMatchRule('x', '(' + word + ')( +)(\**)(' + word + ')', - 'type', 'spaces', 'operator', 'c.identifier'), + 'c.type', 'c.spaces', 'c.operator', 'c.identifier'), PatternMatchRule('x', '(' + word + ')(\*+)( +)(' + word + ')', - 'type', 'operator', 'spaces', 'c.identifier'), + 'c.type', 'c.operator', 'c.spaces', 'c.identifier'), - PatternRule('function', word + r'(?= *\()'), - PatternRule('constant', "[A-Z_][A-Z0-9_]+(?!" + chr2 + ")"), - PatternRule('label', word + '(?=:)'), - RegionRule('error', '# *error', ErrorGrammar, r'\n$'), - RegionRule('macro', '# *(?:assert|cpu|define|elif|else|endif|error|ident|ifdef|ifndef|if|import|include_next|line|machine|pragma_once|pragma|system|unassert|undef|warning)(?!=' + chr2 + ')', MacroGrammar, r'\n$'), - RegionRule('comment', r'/\*', CommentGrammar, r'\*/'), - PatternRule('comment', '//.*$'), - RegionRule('string', '"', StringGrammar2, '"'), + PatternRule('c.function', word + r'(?= *\()'), + PatternRule('c.constant', "[A-Z_][A-Z0-9_]+(?!" + chr2 + ")"), + PatternRule('c.label', word + '(?=:)'), + RegionRule('c.error', '# *error', ErrorGrammar, r'\n$'), + RegionRule('c.macro', '# *(?:assert|cpu|define|elif|else|endif|error|ident|ifdef|ifndef|if|import|include_next|line|machine|pragma_once|pragma|system|unassert|undef|warning)(?!=' + chr2 + ')', MacroGrammar, r'\n$'), + RegionRule('c.comment', r'/\*', CommentGrammar, r'\*/'), + PatternRule('c.comment', '//.*$'), + RegionRule('c.string', '"', StringGrammar2, '"'), - PatternRule(r"float", r"-?[0-9]+\.[0-9]*|-?\.[0-9]+|-?(?:[0-9]|[0-9]+\.[0-9]*|-?\.[0-9]+)[eE][\+-]?[0-9]+"), - PatternRule(r"integer", r"(?:0(?![x0-9])|-?[1-9][0-9]*|0[0-7]+|0[xX][0-9a-fA-F]+)[lL]?"), + PatternRule("c.float", r"-?[0-9]+\.[0-9]*|-?\.[0-9]+|-?(?:[0-9]|[0-9]+\.[0-9]*|-?\.[0-9]+)[eE][\+-]?[0-9]+"), + PatternRule("c.integer", r"(?:0(?![x0-9])|-?[1-9][0-9]*|0[0-7]+|0[xX][0-9a-fA-F]+)[lL]?"), - PatternRule(r"operator", r"!(?!=)|\+=|-=|\*=|/=|//=|%=|&=\|\^=|>>=|<<=|\*\*="), - PatternRule('operator', r"\+|<>|<<|<=|<|-|>>|>=|>|\*\*|&|\*|\||/|\^|==|//|~|!=|%"), - RegionRule('macrocomment', '#if +(?:0|NULL|FALSE)', Grammar, '#endif'), - PatternRule('char', r"'.'|'\\.'|'\\[0-7]{3}'"), + PatternRule("c.operator", r"!(?!=)|\+=|-=|\*=|/=|//=|%=|&=\|\^=|>>=|<<=|\*\*="), + PatternRule('c.operator', r"\+|<>|<<|<=|<|-|>>|>=|>|\*\*|&|\*|\||/|\^|==|//|~|!=|%"), + RegionRule('c.macrocomment', '#if +(?:0|NULL|FALSE)', Grammar, '#endif'), + PatternRule('c.char', r"'.'|'\\.'|'\\[0-7]{3}'"), PatternMatchRule('x', r'(# *include)( +)(.+)(\n|$)', - 'macro.start', 'spaces', 'header', 'macro.end'), + 'c.macro.start', 'c.spaces', 'c.header', 'c.macro.end'), PatternRule('c.identifier', word), - OverridePatternRule('comment', r'/\* *@@:(?P[.a-zA-Z0-9_]+):(?P[.a-zA-Z0-9_]+) *\*/$'), - OverridePatternRule('comment', r'// *@@:(?P[.a-zA-Z0-9_]+):(?P[.a-zA-Z0-9_]+) *$'), + OverridePatternRule('c.comment', r'/\* *@@:(?P[.a-zA-Z0-9_]+):(?P[.a-zA-Z0-9_]+) *\*/$'), + OverridePatternRule('c.comment', r'// *@@:(?P[.a-zA-Z0-9_]+):(?P[.a-zA-Z0-9_]+) *$'), ] MacroGrammar.rules.extend(CGrammar.rules)