vc, svn and hg refactors; hg blame works

--HG--
branch : pmacs2
This commit is contained in:
Erik Osheim 2009-05-14 23:59:13 -04:00
parent 0fad7e130c
commit b92be6cc27
4 changed files with 57 additions and 40 deletions

View File

@ -1,7 +1,9 @@
import os
import re
from subprocess import Popen, PIPE, STDOUT
from method import Method, Argument
from method.vc import VcBlame
import re
try:
from mercurial import hg, ui
@ -20,31 +22,23 @@ class HgBase(object):
return False
else:
return True
def _hg_init(self):
ui_imp = ui.ui(verbose=True)
def _hg_init(self, **kwargs):
ui_imp = ui.ui(**kwargs)
ui_imp.pushbuffer()
repo = hg.repository(ui=ui_imp, path='.')
return ui_imp, repo
class HgBlame(VcBlame, HgBase):
"""Show buffer annotated with hg metadata"""
line_re = re.compile(r'^ *(?P<user>[^ ]+) (?P<rev>\d+) (?P<date>\d{4}-\d{2}-\d{2}): (?P<content>.*)\n$')
prefix_fmt = '[b:d:*]%(rev)-5s [c:d:*]%(user)-10s [b:d:*]%(date)10s[d:d:*]'
num_fields = 3
# user, rev, [changeset], date, content
line_re = re.compile(r'^ *([^ ]+) +(\d+) +[^ ]+ +(\d{4}-\d{2}-\d{2}): (.*)\n$')
prefix_fmt = '[g:d:*]%*s [c:d:*]%*s [b:d:*]%*s[d:d:*]'
_is_method = True
def _open_pipe(self, w, **vargs):
cmd = ("hg", 'blame', '-nudq', w.buffer.path)
cmd = ("hg", 'blame', '-cnudq', w.buffer.path)
return Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE)
class HgBlame2(Method, HgBase):
def _execute(self, w, **vargs):
if not self._hg_check(w):
return
ui_imp, repo = self._hg_init()
hgc.identify(ui_imp, repo, w.buffer.path)
hgc.annotate(ui_imp, repo, w.buffer.path, user=None, date=None, rev=None)
s = ''.join(ui_imp.popbuffer())
w.application.data_buffer('*Blame*', s, switch_to=True)
class HgLog(Method, HgBase):
"""Show hg log for this buffer"""
def _execute(self, w, **vargs):

View File

@ -264,10 +264,12 @@ class SvnDiff3(Method):
class SvnBlame(VcBlame):
'''show blame output for the current version in SVN'''
line_re = re.compile('^ *(?P<rev>\d+) *(?P<user>[a-zA-Z0-9_]+) *(?P<date>[-0-9]+) *(?P<time>[:0-9]+) *(?P<tz>-\d{4}) *\((?P<vdate>[^\)]+)\) (?P<content>.*)\n$')
prefix_fmt = '[b:d:*]%(rev)-4s [c:d:*]%(user)-10s [b:d:*]%(date)10s[d:d:*]'
_is_method = True
# rev, user, date, [time], [timezone], [date-str], content
num_fields = 3
line_re = re.compile(r'^ *(\d+) *([a-zA-Z0-9_]+) *([-0-9]+) *[:0-9]+ *-\d{4} *\(.+?\) (.*)\n$')
prefix_fmt = '[g:d:*]%*s [c:d:*]%-*s [b:d:*]%*s[d:d:*]'
pretest_err_msg = 'Subversion is not installed'
_is_method = True
def _pretest(self):
return has_svn
def _open_pipe(self, w, **vargs):

View File

@ -10,34 +10,37 @@ class VcBlame(Method):
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)
return m.groupdict()
groups = m.groups()
return {'fields': groups[:-1], 'content': groups[-1], 'tokens': []}
def _open_pipe(self, w, **vargs):
raise Exception('unimplemented')
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
def _build_groups(self, w, **vargs):
pipe = self._open_pipe(w, **vargs)
groups = [self._filter(line) for line in pipe.stdout]
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)
tokens = list(lexer.lex([d['content'] for d in groups]))
for t in tokens:
groups[t.y].setdefault('tokens', [])
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']:
@ -47,10 +50,21 @@ class VcBlame(Method):
suffix += code + util.cbuf_escape(t.string)
else:
suffix = d['content'] + '\n'
lines.append(self.prefix_fmt % d + ' ' + suffix)
data = ''.join(lines)
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
if status == 0:
w.application.color_data_buffer("*Blame*", data, switch_to=True)
else:
w.set_error("There was an error (%s)" % (status))
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)

View File

@ -7,6 +7,13 @@ cbuf_re = re.compile(r'[\[\]\\]')
def cbuf_escape(s):
return cbuf_re.sub(lambda m: '\\' + m.group(0), s)
def flatzip(a, b):
l = []
for x, y in zip(a, b):
l.append(x)
l.append(y)
return l
def normal_path(path):
#path = os.path.realpath(path)
path = os.path.normpath(path)