diff --git a/mode/c.py b/mode/c.py index 7f1d1b1..a286262 100644 --- a/mode/c.py +++ b/mode/c.py @@ -1,6 +1,6 @@ import os, re from subprocess import Popen, PIPE, STDOUT -import color, default, method, method.shell, mode, tab +import color, context, default, method, method.shell, mode, tab from lex import Grammar, PatternRule, RegionRule, OverridePatternRule from mode.python import StringGrammar @@ -9,7 +9,7 @@ from mode.python import StringGrammar class MacroGrammar(Grammar): rules = [ PatternRule('name', r'(?:(?<=#define )) *[a-zA-Z_][a-zA-Z0-9_]*'), - PatternRule(r"unop", r"\+=|-=|\*=|/=|//=|%=|&=\|\^=|>>=|<<=|\*\*="), + PatternRule(r"unop", r"\+=|-=|\*=|/=|//=|%=|&=|\^=|>>=|<<=|\*\*=|\|="), PatternRule(r'binop', r"\+|<>|<<|<=|<|-|>>|>=|>|\*\*|&|\*|\||/|\^|==|//|~|!=|%"), PatternRule(r"delimiter", r"->|\.|\(|\)|\[|\]|{|}|@|,|:|`|;|=|\?"), PatternRule(r"integer", r"-?(?:0(?![x0-9])|[1-9][0-9]*|0[0-7]+|0[xX][0-9a-fA-F]+)[lL]?"), @@ -38,6 +38,7 @@ class CGrammar(Grammar): PatternRule(r'function', r'[a-zA-Z_][a-zA-Z0-9_]*(?= *\()'), PatternRule(r'builtin', r"(?:NULL|TRUE|FALSE)"), + PatternRule(r'c_type', r'[a-zA-Z_][a-zA-Z0-9_]*(?= +[a-zA-Z_])'), PatternRule(r'identifier', r"[a-zA-Z_][a-zA-Z0-9_]*"), PatternRule(r"unop", r"\+=|-=|\*=|/=|//=|%=|&=\|\^=|>>=|<<=|\*\*="), PatternRule(r'binop', r"\+|<>|<<|<=|<|-|>>|>=|>|\*\*|&|\*|\||/|\^|==|//|~|!=|%"), @@ -97,7 +98,7 @@ class CTabber(tab.StackTabber): self._opt_pop('cont') token = self.get_token(y, i) if token.string == '{': - self._pop_while('cond', 'cont') + self._pop_while('cond', 'cont', 'case') if self.is_leftmost_token(y, i): currlvl = self.get_curr_level() tab.StackTabber._handle_open_token(self, currlvl, y, i) @@ -105,11 +106,13 @@ class CTabber(tab.StackTabber): def _handle_close_token(self, currlvl, y, i): w = self.mode.tabwidth self._opt_pop('cont') - currlvl = tab.StackTabber._handle_close_token(self, currlvl, y, i) token = self.get_token(y, i) + if token.string == '}': + self._opt_pop('case') + currlvl = tab.StackTabber._handle_close_token(self, currlvl, y, i) if self.is_rightmost_token(y, i): if token.string == '}': - self._pop_while('cond', 'cont') + self._pop_while('cond', 'cont', 'case') elif self._has_markers() and self._peek_name() == 'cond': pass else: @@ -198,6 +201,54 @@ class CMake(method.shell.Exec): self._doit(w, w.buffer.path, w.application.config['c.make-cmd'], cmdname='c-make') +class CContext(context.Context): + 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 + starting = curr and not bool(stack) + while i < y2: + if not starting and not stack: + curr = None + + g = highlights.tokens[i] + if not stack and len(g) > 2 and g[0].name in ('c_type', 'keyword'): + g2 = [x for x in g if x.name != 'spaces'] + j = 0 + while j < len(g2) - 1 and g2[j].name in ('keyword', 'c_type'): + j += 1 + if j < len(g2) and g2[j].name == 'function': + curr = g2[j].string + starting = True + + if curr is not None and curr not in self.names: + self.names[curr] = i + + if i == y2 - 1 and curr != self.namelines[i][0] and y2 < blen: + y2 += 1 + + m = self.mode + for t in g: + if t.name == 'delimiter' and t.string == '{': + stack.append(t.string) + starting = False + elif t.name == 'delimiter' and t.string == '}': + if not stack: + # we are totally hosed. start over. ugh. + #self.build_name_map() + raise Exception, "we're totally hosed" + return + stack.pop(-1) + if curr: + self.namelines[i] = (curr, tuple(stack)) + i += 1 + class C(mode.Fundamental): modename = 'C' extensions = ['.c', '.h', '.cpp'] @@ -230,6 +281,7 @@ class C(mode.Fundamental): 'header': ('green', 'default', 'bold'), 'structname': ('yellow', 'default', 'bold'), 'enumname': ('yellow', 'default', 'bold'), + 'c_type': ('green', 'default', 'bold'), } config = { 'c.syntax-cmd': "gcc -x c -fsyntax-only %(path)s", @@ -238,6 +290,15 @@ class C(mode.Fundamental): 'c.make-rel-dir': True, } actions = [CCheckSyntax, CMake] + + format = "%(flag)s %(bname)-18s (%(mname)s) %(indent)s %(cursor)s/%(mark)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) + return names + def __init__(self, w): mode.Fundamental.__init__(self, w) self.add_bindings('close-paren', (')',)) @@ -245,5 +306,15 @@ class C(mode.Fundamental): self.add_bindings('close-bracket', (']',)) self.add_bindings('c-check-syntax', ('C-c s',)) self.add_bindings('c-make', ('C-c C-c',)) + self.context = CContext(self) + self.functions = None + self.funclines = None + + 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 = C.install diff --git a/mode/perl.py b/mode/perl.py index e0d03c2..3c60b39 100644 --- a/mode/perl.py +++ b/mode/perl.py @@ -743,20 +743,12 @@ class Perl(mode.Fundamental): completers = { 'perlfunction': PerlFunctionCompleter(), } - format = "%(flag)s %(bname)-18s (%(mname)s) %(cursor)s/%(mark)s %(perc)s [%(func)s]" + format = "%(flag)s %(bname)-18s (%(mname)s) %(indent)s %(cursor)s/%(mark)s %(perc)s [%(func)s]" #format = "%(flag)s %(bname)-18s (%(mname)s) %(cursor)s/%(mark)s %(perc)s" def get_status_names(self): - w = self.window - c = w.logical_cursor() - names = { - 'bname': w.buffer.name(), - 'mname': self.name(), - 'flag': self._get_flag(), - 'perc': self._get_perc(), - 'cursor': '(%d,%d)' % (c.y + 1, c.x + 1), - 'mark': self._get_mark(), - 'func': self.get_line_function(c.y), - } + names = mode.Fundamental.get_status_names(self) + c = self.window.logical_cursor() + names['func'] = self.get_line_function(c.y) return names def __init__(self, w): mode.Fundamental.__init__(self, w) diff --git a/mode/python.py b/mode/python.py index 59993dd..71e8656 100644 --- a/mode/python.py +++ b/mode/python.py @@ -481,20 +481,15 @@ class Python(mode.Fundamental): "pythonfunction": PythonFunctionCompleter(), "pythonclass": PythonClassCompleter(), } - format = "%(flag)s %(bname)-18s (%(mname)s) %(cursor)s/%(mark)s %(perc)s [%(name)s]" + + format = "%(flag)s %(bname)-18s (%(mname)s) %(indent)s %(cursor)s/%(mark)s %(perc)s [%(name)s]" + def get_status_names(self): - w = self.window - c = w.logical_cursor() - names = { - 'bname': w.buffer.name(), - 'mname': self.name(), - 'flag': self._get_flag(), - 'perc': self._get_perc(), - 'cursor': '(%d,%d)' % (c.y + 1, c.x + 1), - 'mark': self._get_mark(), - 'name': self.context.get_line_name(c.y), - } + names = mode.Fundamental.get_status_names(self) + c = self.window.logical_cursor() + names['name'] = self.context.get_line_name(c.y) return names + def __init__(self, w): mode.Fundamental.__init__(self, w) self.add_bindings('close-paren', (')',))