import regex, util from point2 import Point class Marker: def __init__(self, name, level): self.name = name self.level = level def __repr__(self): return '' % (self.name, self.level) class Tabber: def __init__(self, m): self.mode = m self.lines = {} def get_next_left_token(self, y, i): tokens = self.get_tokens(y) assert i >= 0 and i < len(tokens) for j in range(0, i): m = regex.whitespace.match(tokens[i - j].string) if not m: return tokens[i - j] return None def get_next_right_token(self, y, i): tokens = self.get_tokens(y) assert i >= 0 and i < len(tokens) for j in range(i + 1, len(tokens)): m = regex.whitespace.match(tokens[j].string) if not m: return tokens[j] return None def is_leftmost_token(self, y, i): return self.get_next_left_token(y, i) is None def is_rightmost_token(self, y, i): return self.get_next_right_token(y, i) is None def is_only_token(self, y, i): return self.is_leftmost_token(y, i) and self.is_rightmost_token(y, i) def region_added(self, p, newlines): self.lines = {} def region_removed(self, p1, p2): self.lines = {} def is_base(self, y): return True def get_level(self, y): if y in self.lines: return self.lines[y] else: self._calc_level(y) return self.lines.get(y) def _calc_level(self, y): pass def get_level(markers): if markers: return markers[-1].level else: return 0 class StackTabber(Tabber): def __init__(self, m): self.mode = m self.lines = {} self.record = {} self.markers = [] def get_curr_level(self): if self.markers: return self.markers[-1].level else: return 0 def get_tokens(self, y): return self.mode.window.buffer.highlights[self.mode.name()].tokens[y] def get_token(self, y, i): return self.mode.window.buffer.highlights[self.mode.name()].tokens[y][i] def region_added(self, p, newlines): self.lines = {} self.record = {} self.markers = [] def region_removed(self, p1, p2): self.lines = {} self.record = {} self.markers = [] def is_base(self, y): return y == 0 def _calc_level(self, y): highlighter = self.mode.window.buffer.highlights[self.mode.name()] target = y # first we need to step back to find the last place where we have tab # stops figured out, or a suitable place to start while not self.is_base(y) and y > 0: y -= 1 # ok now, let's do this shit self.markers = [] currlvl = 0 while y <= target: currlvl = self.get_curr_level() tokens = self.get_tokens(y) for i in range(0, len(tokens)): currlvl = self._handle_token(currlvl, y, i) self.lines[y] = currlvl self.record[y] = tuple(self.markers) y += 1 def _handle_token(self, currlvl, y, i): token = self.get_token(y, i) s = token.string if token.name == self.mode.closetoken and s in self.mode.closetags: currlvl = self._handle_open_token(currlvl, y, i) elif token.name == self.mode.opentoken and s in self.mode.opentags: currlvl = self._handle_close_token(currlvl, y, i) else: currlvl = self._handle_other_token(currlvl, y, i) return currlvl def _handle_open_token(self, currlvl, y, i): token = self.get_token(y, i) s1 = token.string if not self.markers: raise Exception, "unmatched closing token %r" % s1 s2 = self.markers[-1].name if s1 == self.mode.opentags[s2]: del self.markers[-1] if self.is_leftmost_token(y, i): currlvl = self.get_curr_level() else: raise Exception, "mismatched closing tag %r vs %r" % (s2, s1) return currlvl def _handle_close_token(self, currlvl, y, i): token = self.get_token(y, i) rtoken = self.get_next_right_token(y, i) if rtoken is None: level = self.get_curr_level() + 4 else: level = rtoken.x self.markers.append(Marker(token.string, level)) return currlvl def _handle_other_token(self, currlvl, y, i): return currlvl class PerlTabber(StackTabber): pass