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 subprocess import Popen, PIPE, STDOUT
from method import Method, Argument from method import Method, Argument
from method.vc import VcBlame from method.vc import VcBlame
import re
try: try:
from mercurial import hg, ui from mercurial import hg, ui
@ -20,31 +22,23 @@ class HgBase(object):
return False return False
else: else:
return True return True
def _hg_init(self): def _hg_init(self, **kwargs):
ui_imp = ui.ui(verbose=True) ui_imp = ui.ui(**kwargs)
ui_imp.pushbuffer() ui_imp.pushbuffer()
repo = hg.repository(ui=ui_imp, path='.') repo = hg.repository(ui=ui_imp, path='.')
return ui_imp, repo return ui_imp, repo
class HgBlame(VcBlame, HgBase): class HgBlame(VcBlame, HgBase):
"""Show buffer annotated with hg metadata""" """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$') num_fields = 3
prefix_fmt = '[b:d:*]%(rev)-5s [c:d:*]%(user)-10s [b:d:*]%(date)10s[d:d:*]' # 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 _is_method = True
def _open_pipe(self, w, **vargs): 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) 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): class HgLog(Method, HgBase):
"""Show hg log for this buffer""" """Show hg log for this buffer"""
def _execute(self, w, **vargs): def _execute(self, w, **vargs):

View File

@ -264,10 +264,12 @@ class SvnDiff3(Method):
class SvnBlame(VcBlame): class SvnBlame(VcBlame):
'''show blame output for the current version in SVN''' '''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$') # rev, user, date, [time], [timezone], [date-str], content
prefix_fmt = '[b:d:*]%(rev)-4s [c:d:*]%(user)-10s [b:d:*]%(date)10s[d:d:*]' num_fields = 3
_is_method = True 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' pretest_err_msg = 'Subversion is not installed'
_is_method = True
def _pretest(self): def _pretest(self):
return has_svn return has_svn
def _open_pipe(self, w, **vargs): def _open_pipe(self, w, **vargs):

View File

@ -10,34 +10,37 @@ class VcBlame(Method):
line_re = None line_re = None
prefix_fmt = None prefix_fmt = None
pretest_err_msg = None pretest_err_msg = None
num_fields = 1
def _pretest(self): def _pretest(self):
return True return True
def _filter(self, line): def _filter(self, line):
m = self.line_re.match(line) m = self.line_re.match(line)
if not m: if not m:
raise VcException("couldn't parse %r" % line) 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): def _open_pipe(self, w, **vargs):
raise Exception('unimplemented') raise Exception('unimplemented')
def _execute(self, w, **vargs): def _build_groups(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
pipe = self._open_pipe(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 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: if w.mode.grammar:
lexer = lex.Lexer(w.mode, w.mode.grammar) lexer = lex.Lexer(w.mode, w.mode.grammar)
tokens = list(lexer.lex([d['content'] for d in groups])) for t in lexer.lex([d['content'] for d in groups]):
for t in tokens:
groups[t.y].setdefault('tokens', [])
groups[t.y]['tokens'].append(t) groups[t.y]['tokens'].append(t)
def _build_lines(self, groups, gsizes, w, **vargs):
self._lex_groups(groups, w, **vargs)
lines = [] lines = []
for d in groups: for d in groups:
if d['tokens']: if d['tokens']:
@ -47,10 +50,21 @@ class VcBlame(Method):
suffix += code + util.cbuf_escape(t.string) suffix += code + util.cbuf_escape(t.string)
else: else:
suffix = d['content'] + '\n' suffix = d['content'] + '\n'
lines.append(self.prefix_fmt % d + ' ' + suffix) tpl = tuple(util.flatzip(gsizes, d['fields']))
data = ''.join(lines) 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: try:
w.application.color_data_buffer("*Blame*", data, switch_to=True) groups, gsizes = self._build_groups(w, **vargs)
else: except Exception, e:
w.set_error("There was an error (%s)" % (status)) 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): def cbuf_escape(s):
return cbuf_re.sub(lambda m: '\\' + m.group(0), 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): def normal_path(path):
#path = os.path.realpath(path) #path = os.path.realpath(path)
path = os.path.normpath(path) path = os.path.normpath(path)