from method import Method import buffer.color import util import lex class VcException(Exception): pass class VcBlame(Method): _is_method = False line_re = None prefix_fmt = None pretest_err_msg = None num_fields = 1 def _pretest(self): return True def _filter(self, line): m = self.line_re.match(line) if not m: raise VcException("couldn't parse %r" % line) groups = m.groups() return {'fields': groups[:-1], 'content': groups[-1], 'tokens': []} def _open_pipe(self, w, **vargs): raise Exception('unimplemented') def _build_groups(self, w, **vargs): pipe = self._open_pipe(w, **vargs) groups = [] gsizes = [0] * self.num_fields for line in pipe.stdout: d = self._filter(line) for i in range(0, self.num_fields): gsizes[i] = max(gsizes[i], len(d['fields'][i])) groups.append(d) status = pipe.wait() >> 8 if status != 0: raise Exception("There was an error (%d)" % status) return groups, gsizes def _lex_groups(self, groups, w, **vargs): if w.mode.grammar: lexer = lex.Lexer(w.mode, w.mode.grammar) for t in lexer.lex([d['content'] for d in groups]): groups[t.y]['tokens'].append(t) def _build_lines(self, groups, gsizes, w, **vargs): self._lex_groups(groups, w, **vargs) lines = [] for d in groups: if d['tokens']: suffix = '' for t in d['tokens']: code = buffer.color.get_cbuf_code(*t.color) suffix += code + util.cbuf_escape(t.string) else: suffix = d['content'] + '\n' tpl = tuple(util.flatzip(gsizes, d['fields'])) lines.append(self.prefix_fmt % tpl + ' ' + suffix) return lines def _execute(self, w, **vargs): if not self._pretest(): w.set_error(self.pretest_err_msg) return elif not hasattr(w.buffer, 'path'): w.set_error("Buffer has no corresponding file") return try: groups, gsizes = self._build_groups(w, **vargs) except Exception, e: w.set_error(str(e)) data = ''.join(self._build_lines(groups, gsizes, w, **vargs)) w.application.color_data_buffer("*Blame*", data, switch_to=True)