diff -r 000000000000 -r 40c8f766c9b8 src/cm/diff.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/cm/diff.py Mon Nov 23 15:14:29 2009 +0100 @@ -0,0 +1,115 @@ +import difflib, string +from django.utils.translation import ugettext as _ + +def isatag(x): return x.startswith("<") and x.endswith(">") + +def text_diff(a, b): + res = [] + a, b = createlist(a), createlist(b) + s = difflib.SequenceMatcher(isatag, a, b) + for e in s.get_opcodes(): + if e[0] == "replace": + res.append(''+''.join(a[e[1]:e[2]]) + ''+''.join(b[e[3]:e[4]])+"") + elif e[0] == "delete": + res.append(''+ ''.join(a[e[1]:e[2]]) + "") + elif e[0] == "insert": + res.append(''+''.join(b[e[3]:e[4]]) + "") + elif e[0] == "equal": + res.append(''.join(b[e[3]:e[4]])) + else: + raise "error parsing %s" %(e[0]) + return ''.join(res) + +COLORS = [ +'#FF0000', +'#EE0000', +'#DD0000', +'#CC0000', +'#BB0000', +'#AA0000', +'#990000', +'#880000', +'#770000', +] + +from colorsys import hls_to_rgb, hsv_to_rgb + +def generatePastelColors(n): + s = .4 + v = .99 + return ['#'+''.join((hex(int(r*255))[2:],hex(int(g*255))[2:],hex(int(b*255))[2:])) for r,g,b in [hsv_to_rgb(h/200.,s,v) for h in range(1,100,100/n)]] + + +DEFAULT_COLOR = '#D9D9D9' +def get_colors(authors, last_white = False): + """ + returns a dict for authors's colors (with last one white if 'last_white') + """ + authors = set(authors) + #new_colors = list(tuple(COLORS)) + new_colors = generatePastelColors(len(set(authors))) + res = [] + if None in authors or '' in authors: + res = [(_(u'unknown'),DEFAULT_COLOR) ] + res.extend([(author,new_colors.pop()) for author in authors if author]) + #if authors[-1]: + # res[authors[-1]] = '#FFFFFF' + return res + + +def text_history(versions, authors): + res = versions[0] + colors = get_colors(authors) + for ind in range(len(versions)-1): + author = authors[ind] + color = colors.get(author,DEFAULT_COLOR) + v_2 = versions[ind + 1] + res = text_diff_add(v_2, res, color) + return res,colors.items() + +from cm.utils.html import surrond_text_node + +def text_diff_add(a,b, color): + res = [] + a, b = createlist(a), createlist(b) + s = difflib.SequenceMatcher(isatag, a, b) + for e in s.get_opcodes(): + if e[0] == "replace": + html_chunk = ''.join(b[e[3]:e[4]]) + new_html_chunk = surrond_text_node(html_chunk,'' %color,'') + res.append(new_html_chunk) + #res.append('' %color+''.join(b[e[3]:e[4]])+"") + elif e[0] == "delete": + pass + elif e[0] == "insert": + html_chunk = ''.join(b[e[3]:e[4]]) + new_html_chunk = surrond_text_node(html_chunk,'' %color,'') + res.append(new_html_chunk) + #res.append('' %color+''.join(b[e[3]:e[4]]) + "") + elif e[0] == "equal": + res.append(''.join(b[e[3]:e[4]])) + else: + raise "error parsing %s" %(e[0]) + return ''.join(res) + +def createlist(x, b=0): + mode = 'char' + cur = '' + out = [] + for c in x: + if mode == 'tag': + if c == '>': + if b: cur += ']' + else: cur += c + out.append(cur); cur = ''; mode = 'char' + else: cur += c + elif mode == 'char': + if c == '<': + out.append(cur) + if b: cur = '[' + else: cur = c + mode = 'tag' + elif c in string.whitespace: out.append(cur+c); cur = '' + else: cur += c + out.append(cur) + return filter(lambda x: x is not '', out)