pmacs3/method/vc.py

120 lines
4.0 KiB
Python

import os
from method import Method, arg
import buffer.colors
import util
import lex
class VcException(Exception): pass
class VcBase(Method):
_is_method = False
def _get_path(self, w):
if not hasattr(w.buffer, 'path'):
raise VcException("buffer has no path")
cwd = os.getcwd() + os.path.sep
path = w.buffer.path
if path.startswith(cwd):
path = path[len(cwd):]
return path
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.colors.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 as e:
w.set_error(str(e))
return
data = ''.join(self._build_lines(groups, gsizes, w, **vargs))
w.application.color_data_buffer("*Blame*", data, switch_to=True)
class VcRevView(Method):
'''show file contents at revision'''
_is_method = False
namebase = 'VC'
def _get_path(self, w, **vargs):
cwd = os.getcwd() + os.path.sep
path = w.buffer.path
if path.startswith(cwd):
path = path[len(cwd):]
return path
def _get_cmd(self, w, **vargs):
path = self._get_path(w, **vargs)
raise Exception("unimplemented")
def _get_name(self, w, **vargs):
return '*%s:%s-%s' % (self.namebase, w.buffer.name(), vargs['revision'])
def _execute(self, w, **vargs):
if not hasattr(w.buffer, 'path'):
w.set_error("Buffer has no corresponding file")
return
cmd = self._get_cmd(w, **vargs)
name = self._get_name(w, **vargs)
mname = w.mode.name.lower()
status, out, err = util.communicate(cmd)
w.application.data_buffer(name, out, switch_to=True, modename=mname)
class VcDateView(VcRevView):
'''show file contents at date'''
args = [arg("date", t=type(""), p="Date: ", h="date specifier")]
def _get_name(self, w, **vargs):
return '*%s:%s-%s' % (self.namebase, w.buffer.name(), vargs['date'])