diff --git a/mode/perl.py b/mode/perl.py index 64b8487..0d733d3 100644 --- a/mode/perl.py +++ b/mode/perl.py @@ -6,14 +6,18 @@ from lex import Grammar, PatternRule, ContextPatternRule, RegionRule, \ OverridePatternRule, PatternGroupRule from method import Argument, Method, WrapParagraph from tab import StackTabber, StackTabber2 +from parse import Any, And, Or, Optional, Name, Match, Matchs + +class PodDataGrammar(Grammar): + rules = [PatternRule(r'data', r'[^\n]+\n$')] class PodGrammar(Grammar): rules = [ - RegionRule(r'entry', r'(?<=^=head[1-4]) +.*$', Grammar, '^\n$'), - RegionRule(r'entry', r'(?<=^=over) +.*$', Grammar, '^\n$'), - RegionRule(r'entry', r'(?<=^=item) +.*$', Grammar, '^\n$'), - RegionRule(r'entry', r'(?:(?<=^=begin)|(?<=^=end)) +.*$', Grammar, '^\n$'), - RegionRule(r'entry', r'(?<=^=encoding) +.*$', Grammar, '^\n$'), + RegionRule(r'entry', r'(?<=^=head[1-4]) +.*$', PodDataGrammar, '^\n$'), + RegionRule(r'entry', r'(?<=^=over) +.*$', PodDataGrammar, '^\n$'), + RegionRule(r'entry', r'(?<=^=item) +.*$', PodDataGrammar, '^\n$'), + RegionRule(r'entry', r'(?:(?<=^=begin)|(?<=^=end)) +.*$', PodDataGrammar, '^\n$'), + RegionRule(r'entry', r'(?<=^=encoding) +.*$', PodDataGrammar, '^\n$'), ] def _make_string_rules(forbidden): @@ -577,6 +581,10 @@ class PerlFunctionCompleter(completer.Completer): return [n for n in functions if n.startswith(s)] class PerlContext(context.Context): + sub_match = And(Optional(Name('spaces')), + Match('perl_keyword', 'sub'), + Name('spaces'), + Name('sub')) def _regen_stack(self, y): if y > 0 and self.namelines[y - 1][1]: return list(self.namelines[y - 1][1]) @@ -584,39 +592,25 @@ class PerlContext(context.Context): 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) + tokenlines = self.mode.window.get_highlighter().tokens + + i = y1 while i < y2: - if not starting and not stack: - curr = None + tokens = tokenlines[i] + if not stack: + result = self.sub_match.match(tokens) + if result: curr = tokens[result[0] - 1].string - g = highlights.tokens[i] - if (not stack and len(g) > 2 and g[0].name == 'perl_keyword' and - g[0].string == 'sub' and g[2].name == 'sub'): - curr = g[2].string - starting = True + if curr is not None: self.names.setdefault(curr, i) - if curr is not None and curr not in self.names: - self.names[curr] = i + for t in tokens: + if t.match('delimiter', '{'): + stack.append(curr) + elif t.match('delimiter', '}'): + if stack: stack.pop(-1) + if not stack: curr = None - 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 stack: - stack.pop(-1) - else: - # we are totally hosed. ugh. - pass - if curr: - self.namelines[i] = (curr, tuple(stack)) + if curr: self.namelines[i] = (curr, tuple(stack)) i += 1 class Perl(mode.Fundamental): @@ -639,6 +633,7 @@ class Perl(mode.Fundamental): 'pod.start': ('red', 'default', 'bold'), 'pod.null': ('red', 'default', 'bold'), 'pod.entry.start': ('magenta', 'default', 'bold'), + 'pod.entry.data': ('magenta', 'default', 'bold'), 'pod.entry.null': ('magenta', 'default', 'bold'), 'pod.entry.end': ('magenta', 'default', 'bold'), 'pod.end': ('red', 'default', 'bold'), @@ -654,6 +649,7 @@ class Perl(mode.Fundamental): 'perl_keyword': ('magenta', 'default', 'bold'), 'cast': ('yellow', 'default', 'bold'), 'scalar': ('yellow', 'default', 'bold'), + 'length': ('yellow', 'default', 'bold'), 'array': ('yellow', 'default', 'bold'), 'deref': ('yellow', 'default', 'bold'), 'perl_hash': ('yellow', 'default', 'bold'), diff --git a/mode/python.py b/mode/python.py index de162ca..2e64772 100644 --- a/mode/python.py +++ b/mode/python.py @@ -2,6 +2,7 @@ import commands, os.path, string, sys, traceback import color, completer, context, default, mode, method, regex, tab, method.introspect from point import Point from lex import Grammar, PatternRule, RegionRule, OverridePatternRule +from parse import Any, And, Or, Optional, Name, Match, Matchs try: import bike @@ -411,7 +412,24 @@ class PythonClassCompleter(completer.Completer): def _get_dict(self, w): return w.buffer.method.old_window.mode.context.get_classes() +CLASS_MATCH = And(Optional(Name('spaces')), + Matchs('python_keyword', ('public', 'protected', 'private')), + Name('spaces'), + Match('keyword', 'class'), + Name('spaces'), + Name('identifier')) +CLASS_OFFSET = 1 + class PythonContext(context.Context): + empty_match = And(Optional(Name('spaces')), Name('eol')) + class_match = And(Optional(Name('spaces')), + Match('python_keyword', 'class'), + Name('spaces'), + Name('classname')) + func_match = And(Optional(Name('spaces')), + Match('python_keyword', 'def'), + Name('spaces'), + Name('functionname')) def __init__(self, mode): self.mode = mode self.names = None @@ -453,20 +471,23 @@ class PythonContext(context.Context): highlights = self.mode.window.get_highlighter() i = y1 while i < y2: + tokens = highlights.tokens[i] g = highlights.tokens[i] - if (len(g) == 1 and g[0].name == 'eol' or - len(g) == 2 and g[0].name == 'spaces' and g[1].name == 'eol'): + if self.empty_match.match(tokens): + #if (len(g) == 1 and g[0].name == 'eol' or + # len(g) == 2 and g[0].name == 'spaces' and g[1].name == 'eol'): if last is None: last = i i += 1 - if i == y2 and y2 < blen: - y2 += 1 + #if i == y2 and y2 < blen: + # y2 += 1 continue if g[0].name == 'spaces': j, lvl = 1, len(g[0].string) else: j, lvl = 0, 0 + while stack and lvl <= stack[-1][0]: stack.pop(-1)