import color, mode, tab import context from lex import Grammar, PatternRule, RegionRule from mode.python import StringGrammar2 from mode.c import CTabber2 from parse import Any, And, Or, Optional, Name, Match, Matchs class CommentGrammar(Grammar): rules = [ PatternRule(r"javadoc", r"@[a-z]+"), PatternRule(r"data", r"(?:[^@*]|\*(?!/))+"), ] class JavaGrammar(Grammar): rules = [ PatternRule(r"spaces", r" +"), PatternRule(r'import', r'(?<=import ) *[a-zA-Z0-9_.*]+'), PatternRule(r'package', r'(?<=package ) *[a-zA-Z0-9_.*]+'), RegionRule(r'java_comment', '/\*', CommentGrammar, '\*/'), PatternRule(r'java_comment', r'//.*$'), PatternRule(r'keyword', r"(?:abstract|assert|boolean|break|byte|case|catch|char|class|continue|default|double|do|else|extends|finally|final|float|for|if|implements|import|instanceof|interface|int|long|native|new|package|private|protected|public|return|short|static|switch|super|synchronized|threadsafe|throws|throw|transient|try|void|while)(?![a-zA-Z_])"), PatternRule(r'java_label', r'[a-zA-Z_][a-zA-Z0-9_]*(?=:)'), PatternRule(r'java_builtin', r"(?:null|true|false|this)"), PatternRule(r'identifier', r"[a-zA-Z_][a-zA-Z0-9_]*"), PatternRule(r"unop", r"\+=|-=|\*=|/=|//=|%=|&=\|\^=|>>=|<<=|\*\*="), PatternRule(r'binop', r"\+|<>|<<|<=|<|-|>>|>=|>|\*\*|&|\*|\||/|\^|==|//|~|!=|%"), PatternRule(r"delimiter", r"->|\.|\(|\)|\[|\]|{|}|@|,|:|`|;|=|\?"), PatternRule(r"java_integer", r"(?:0(?![x0-9])|[1-9][0-9]*|0[0-7]+|0[xX][0-9a-fA-F]+)[lL]?"), PatternRule(r"java_float", r"[0-9]+\.[0-9]*|\.[0-9]+|(?:[0-9]|[0-9]+\.[0-9]*|\.[0-9]+)[eE][\+-]?[0-9]+"), RegionRule(r'string', '"', StringGrammar2, '"'), PatternRule(r'java_char', r"'.'|'\\.'|'\\[0-7]{3}'"), PatternRule(r"eol", r"\n$"), ] CLASS_MATCH = And(Optional(Name('spaces')), Matchs('keyword', ('public', 'protected', 'private')), Name('spaces'), Match('keyword', 'class'), Name('spaces'), Name('identifier')) CLASS_OFFSET = 1 METHOD_MATCH = And(Optional(Name('spaces')), Matchs('keyword', ('public', 'protected', 'private')), Name('spaces'), Optional(And(Match('keyword', 'static'), Name('spaces'))), Any(), Name('spaces'), Name('identifier'), Optional(Name('spaces')), Match('delimiter', '(')) METHOD_OFFSET = 2 class JavaTabber2(tab.StackTabber2): open_tokens = {'delimiter': {'{': '}', '(': ')', '[': ']'}} close_tokens = {'delimiter': {'}': '{', ')': '(', ']': '['}} control_tokens = {'keyword': {'if': 1, 'else': 1, 'while': 1, 'do': 1, 'for': 1}} end_at_eof = False end_at_tokens = {'delimiter': {';': 1}} nocontinue_tokens = {'delimiter': {';': 1}, 'java_comment.start': 1, 'java_comment.data': 1, 'java_comment.end': 1} start_free_tokens = {'string.start': 'string.end'} end_free_tokens = {'string.end': 'string.start'} def is_base(self, y): if y == 0: return True else: return False def _is_indent(self, t): return t.name == 'spaces' def _is_ignored(self, t): return t.fqname() in ('spaces', 'eol', 'comment', 'comment.start', 'comment.data', 'comment.null', 'comment.end') class JavaContext(context.Context): class_match = CLASS_MATCH class_offset = CLASS_OFFSET method_match = METHOD_MATCH method_offset = METHOD_OFFSET def _regen_stack(self, y): if y > 0 and self.namelines[y - 1][1]: return list(self.namelines[y - 1][1]) else: return [] def _build_name_map(self, y1, y2, last, curr, stack): blen = len(self.mode.window.buffer.lines) highlights = self.mode.window.get_highlighter() i = y1 while i < y2: if not stack: curr = None g = highlights.tokens[i] gl = len(g) result = self.class_match.match(g) if result: n = result[0] - self.class_offset curr = g[n].string result = self.method_match.match(g) if result: n = result[0] - self.method_offset curr = g[n].string if curr is not None and curr not in self.names: self.names[curr] = i for t in g: if t.match('delimiter', '{'): stack.append(curr) elif t.match('delimiter', '}'): if stack: stack.pop(-1) if stack: curr = stack[-1] else: curr = None if curr: self.namelines[i] = (curr, tuple(stack)) i += 1 class Java(mode.Fundamental): modename = 'Java' extensions = ['.java'] tabbercls = JavaTabber2 grammar = JavaGrammar opentokens = ('delimiter',) opentags = {'(': ')', '[': ']', '{': '}'} closetokens = ('delimiter',) closetags = {')': '(', ']': '[', '}': '{'} colors = { 'java_comment.start': ('red', 'default', 'bold'), 'java_comment.end': ('red', 'default', 'bold'), 'java_comment.javadoc': ('magenta', 'default', 'bold'), 'java_comment.data': ('red', 'default', 'bold'), 'java_comment.null': ('red', 'default', 'bold'), 'import': ('blue', 'default', 'bold'), 'java_label': ('magenta', 'default', 'bold'), 'java_builtin': ('magenta', 'default', 'bold'), 'java_char': ('green', 'default', 'bold'), 'java_integer': ('green', 'default', 'bold'), 'java_float': ('green', 'default', 'bold'), } format = "%(flag)s %(bname)-18s (%(mname)s) %(indent)s %(cursor)s/%(mark)s %(perc)s [%(func)s]" #format = "%(flag)s %(bname)-18s (%(mname)s) %(indent)s %(cursor)s/%(first)s %(perc)s [%(func)s]" def get_status_names(self): names = mode.Fundamental.get_status_names(self) c = self.window.logical_cursor() names['func'] = self.get_line_function(c.y) #names['first'] = self.window.first.xy() return names 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.context = JavaContext(self) def get_functions(self): return self.context.get_names() def get_function_names(self): return self.context.get_name_list() def get_line_function(self, y): return self.context.get_line_name(y) install = Java.install