diff --git a/context.py b/context.py index eefb178..f5f5516 100644 --- a/context.py +++ b/context.py @@ -20,35 +20,32 @@ class Context(object): for i in reversed(range(p.y + 1, len(self.mode.window.buffer.lines))): self.namelines[i] = self.namelines[i - delta] for i in range(p.y, p.y + delta): - self.namelines[i] = None + self.namelines[i] = (None, None) else: for i in range(p.y + 1, len(self.mode.window.buffer.lines)): self.namelines[i + delta] = self.namelines[i] def _init_name_map(self): self.names = {} - self.namelines = [None] * len(self.mode.window.buffer.lines) + self.namelines = [(None, None)] * len(self.mode.window.buffer.lines) def build_name_map(self): self._init_name_map() self._build_name_map(0, len(self.mode.window.buffer.lines), None, None, []) + def _del_name(self, y, name): + if name and name in self.names: + del self.names[name] + self.namelines[y] = (None, None) def rebuild_name_map(self, y1, y2): for y in range(y1, y2): - name = self.namelines[y] - if name: - if name in self.names: - del self.names[name] - if name in self.classes: - del self.classes[name] - if name in self.functions: - del self.functions[name] - self.namelines[y] = None + (name, info) = self.namelines[y] + self._del_name(y, name) if y1 == 0: self._build_name_map(y1, y2, None, None, []) else: - last, curr, stack = None, self.namelines[y1 - 1], [] + last, curr, stack = None, self.namelines[y1 - 1][0], [] count = 0 if curr: for part in curr.split('.'): @@ -63,7 +60,7 @@ class Context(object): if self.namelines is None: self.build_name_map() if y < len(self.namelines): - return self.namelines[y] + return self.namelines[y][0] else: return None def get_names(self): diff --git a/mode/perl.py b/mode/perl.py index 2b61ae9..1080916 100644 --- a/mode/perl.py +++ b/mode/perl.py @@ -286,7 +286,7 @@ class PerlGotoFunction(Method): args = [Argument("name", type(""), "perlfunction", "Goto Function: ")] def _execute(self, w, **vargs): name = vargs['name'] - functions = w.mode.get_functions() + functions = w.mode.context.get_names() if name in functions: w.goto(Point(0, functions[name])) else: @@ -295,7 +295,7 @@ class PerlGotoFunction(Method): class PerlListFunctions(Method): '''Show the user all functions defined in this module''' def _execute(self, w, **vargs): - names = w.mode.get_function_names() + names = w.mode.context.get_name_list() output = "\n".join(names) + "\n" w.application.data_buffer("*Perl-List-Functions*", output, switch_to=True) @@ -303,11 +303,11 @@ class PerlWhichFunction(Method): '''Show the user what function they are in''' def _execute(self, w, **vargs): cursor = w.logical_cursor() - name = w.mode.get_line_function(cursor.y) + name = w.mode.context.get_line_name(cursor.y) if name is None: w.application.set_error("None"); else: - functions = w.mode.get_functions() + functions = w.mode.context.get_names() i = functions[name] + 1 w.application.set_error("line %d: %s" % (i, name)) @@ -389,91 +389,6 @@ class PerlHashCleanup(Method): w.kill(start_p, end_p) w.insert_string(start_p, data) -class PerlHashCleanup2(Method): - #_hash_parts = ( - # (TokenMatch('null', None),), - # (TokenMatch('hash_key', None), TokenMatch('string.start', None)), - # (TokenMatch('null', None),), - # (TokenMatch('delimiter', '=>'),), - # (TokenMatch('null', None),), - #) - def _hash_matchXXX(self, group, line): - i = 0 - j = 0 - stages = [] - while tok_i < len(group): - token = group[i] - name = token.fqname() - data = token.string - k = len(stages) - if k < len(self._hash_parts): - for (name2, data2) in self._hash_parts[k]: - if (name2 is None or name == name2 and - data2 is None or data == data2): - stages.append(line[j:token.x]) - j = token.x - else: - stages.append(line[j:]) - return stages - i += 1 - return None - - def _assign_match(self, group): - return None - - def _execute(self, w, **vargs): - cursor = w.logical_cursor() - tokens = w.buffer.highlights[w.mode.name()].tokens - if self._hash_match(tokens[cursor.y]): - token_groups = self._parse_hash(w, **vargs) - elif self._assign_match(tokens[cursor.y]): - token_groups = self._parse_assign(w, **vargs) - else: - w.set_error("Not a hash line") - return - - ys = token_groups.keys() - ys.sort() - - segment_groups = [] - for y in ys: - line = w.buffer.lines[y] - segments = [] - i = 0 - for token in token_groups[y]: - segments.append(line[i:token.x]) - i = token.x - segments.append(line[i:]) - segment_groups.append(segments) - - output = "Lines %d through %d\n%r" % (ys[0] + 1, ys[-1] + 1, segment_groups) - w.application.data_buffer("hash-dump", output, switch_to=True) - - def _parse_hash(self, w, **vargs): - cursor = w.logical_cursor() - tokens = w.buffer.highlights[w.mode.name()].tokens - lines = {cursor.y: self._hash_match(tokens[cursor.y])} - - y1 = cursor.y - while y1 > 0: - match = self._hash_match(tokens[y1 - 1]) - if not match: - break - lines[y1 - 1] = match - y1 -= 1 - - y2 = cursor.y - while y2 < len(tokens) - 1: - match = self._hash_match(tokens[y2 + 1]) - if not match: - break - lines[y2 + 1] = match - y2 += 1 - - return lines - def _parse_assign(self, w, **vargs): - pass - class PerlWrapParagraph(method.WrapParagraph): '''Wrap Comments and POD''' # enumerations for line types @@ -575,7 +490,7 @@ class PerlWrapParagraph(method.WrapParagraph): class PerlFunctionCompleter(completer.Completer): def get_candidates(self, s, w=None): old_window = w.buffer.method.old_window - functions = old_window.mode.get_functions() + functions = old_window.mode.context.get_names() return [n for n in functions if n.startswith(s)] class PerlContext(context.Context): @@ -585,56 +500,26 @@ class PerlContext(context.Context): i = y1 while i < y2: g = highlights.tokens[i] - if (len(g) == 1 and g[0].name == 'eol' or - len(g) == 2 and g[0].name == 'null' and g[1].name == 'eol'): - if last is None: - last = i - i += 1 - if i == y2 and y2 < blen: - y2 += 1 - continue + 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 + self.names[curr] = i - if g[0].name == 'null': - j, lvl = 1, len(g[0].string) - else: - j, lvl = 0, 0 - while stack and lvl <= stack[-1][0]: - stack.pop(-1) - - if last is not None: - curr = '.'.join([x[1] for x in stack]) - if curr: - for k in range(last, i): - self.namelines[k] = curr - last = None - - if len(g[j:]) > 3: - d, found = None, False - if g[j].name == 'python_keyword' and g[j].string == 'class': - d, found = self.classes, True - elif g[j].name == 'python_keyword' and g[j].string == 'def': - d, found = self.functions, True - if found: - stack.append([lvl, g[j+2].string]) - curr = '.'.join([x[1] for x in stack]) - d[curr] = i - self.names[curr] = i - else: - curr = '.'.join([x[1] for x in stack]) - - if i == y2 - 1 and curr != self.namelines[i] and y2 < blen: + if i == y2 - 1 and curr != self.namelines[i][0] and y2 < blen: y2 += 1 if curr: - self.namelines[i] = curr + self.namelines[i] = (curr, tuple(stack)) i += 1 - if last is not None and y2 < len(self.namelines): - if self.namelines[y2]: - n = len(self.namelines[y2].split('.')) - curr = '.'.join([x[1] for x in stack[:n]]) - if curr: - for k in range(last, y2): - self.namelines[k] = curr + m = self.mode + for t in g: + if t.name in m.opentokens and t.string in m.opentags: + stack.append(t.string) + elif t.name in m.closetokens and t.string in m.closetags: + assert stack[-1] == m.closetags[t.string] + stack.pop(-1) + if not stack: + curr = None class Perl(mode.Fundamental): modename = 'Perl' @@ -775,47 +660,15 @@ class Perl(mode.Fundamental): self.add_bindings('close-paren', (')')) self.add_bindings('close-bracket', (']')) self.add_bindings('close-brace', ('}')) + self.context = PerlContext(self) self.functions = None self.funclines = None - def build_function_map(self): - self.functions = {} - self.funclines = [] - highlights = self.window.get_highlighter() - curr, stack = None, [] - for group in highlights.tokens: - self.funclines.append(curr) - for t in group: - if not curr and t.name == 'sub': - curr = t.string - stack = [] - self.functions[curr] = t.y - elif t.name == 'delimiter': - if t.string == '{': - stack.append(None) - elif t.string == '}': - stack.pop() - if not stack: - curr = None - if curr: - self.funclines[-1] = curr - def get_functions(self): - if self.functions is None: - self.build_function_map() - return self.functions + return self.context.get_names() def get_function_names(self): - functions = self.get_functions() - pairs = [[functions[key], key] for key in functions] - pairs.sort() - names = [x[1] for x in pairs] - return names + return self.context.get_name_list() def get_line_function(self, y): - if self.funclines is None: - self.build_function_map() - if y < len(self.funclines): - return self.funclines[y] - else: - return None + return self.context.get_line_name(y) install = Perl.install diff --git a/mode/python.py b/mode/python.py index 74e11f6..7cf9ea8 100644 --- a/mode/python.py +++ b/mode/python.py @@ -358,8 +358,16 @@ class PythonContext(context.Context): self.names = {} self.classes = {} self.functions = {} - self.namelines = [None] * len(self.mode.window.buffer.lines) - + self.namelines = [(None, None)] * len(self.mode.window.buffer.lines) + def _del_name(self, y, name): + if name: + if name in self.names: + del self.names[name] + if name in self.classes: + del self.classes[name] + if name in self.functions: + del self.functions[name] + self.namelines[y] = (None, None) def _build_name_map(self, y1, y2, last, curr, stack): blen = len(self.mode.window.buffer.lines) highlights = self.mode.window.get_highlighter() @@ -386,7 +394,7 @@ class PythonContext(context.Context): curr = '.'.join([x[1] for x in stack]) if curr: for k in range(last, i): - self.namelines[k] = curr + self.namelines[k] = (curr, None) last = None if len(g[j:]) > 3: @@ -403,19 +411,19 @@ class PythonContext(context.Context): else: curr = '.'.join([x[1] for x in stack]) - if i == y2 - 1 and curr != self.namelines[i] and y2 < blen: + if i == y2 - 1 and curr != self.namelines[i][0] and y2 < blen: y2 += 1 if curr: - self.namelines[i] = curr + self.namelines[i] = (curr, None) i += 1 if last is not None and y2 < len(self.namelines): - if self.namelines[y2]: - n = len(self.namelines[y2].split('.')) + if self.namelines[y2][0]: + n = len(self.namelines[y2][0].split('.')) curr = '.'.join([x[1] for x in stack[:n]]) if curr: for k in range(last, y2): - self.namelines[k] = curr + self.namelines[k] = (curr, None) class Python(mode.Fundamental): modename = 'Python'