Add hb-diff-colorize

Accepts --format=html now.
This commit is contained in:
Behdad Esfahbod 2012-05-08 23:41:41 +02:00
parent 9155e4ffe0
commit f1eb008cc7
4 changed files with 104 additions and 62 deletions

View File

@ -11,6 +11,7 @@ manifests:
EXTRA_DIST += \ EXTRA_DIST += \
hb-diff \ hb-diff \
hb-diff-colorize \
hb-diff-filter-failures \ hb-diff-filter-failures \
hb-manifest-read \ hb-manifest-read \
hb-manifest-update \ hb-manifest-update \

View File

@ -3,8 +3,8 @@
from hb_test_tools import * from hb_test_tools import *
import sys, os import sys, os
if len (sys.argv) < 3: if len (sys.argv) < 2:
print "usage: %s file1 file2..." % sys.argv[0] print "usage: %s FILES..." % sys.argv[0]
sys.exit (1) sys.exit (1)
ZipDiffer.diff_files (FileHelpers.open_file_or_stdin (f) for f in sys.argv[1:]) ZipDiffer.diff_files (FileHelpers.open_file_or_stdin (f) for f in sys.argv[1:])

7
test/shaping/hb-diff-colorize Executable file
View File

@ -0,0 +1,7 @@
#!/usr/bin/python
from hb_test_tools import *
formatter = ColorFormatter.Auto (sys.argv)
colorizer = DiffColorizer (formatter=formatter)
UtilMains.process_multiple_files (FilterHelpers.filter_printer_function_no_newline (colorizer.colorize_diff))

View File

@ -1,65 +1,81 @@
#!/usr/bin/python #!/usr/bin/python
import sys, os, re, difflib, unicodedata, errno import sys, os, re, difflib, unicodedata, errno, cgi
from itertools import * from itertools import *
diff_symbols = "-+=*&^%$#@!~/" diff_symbols = "-+=*&^%$#@!~/"
diff_colors = ['red', 'green', 'blue'] diff_colors = ['red', 'green', 'blue']
class Colors: class ColorFormatter:
class Null: class Null:
red = '' @staticmethod
green = '' def start_color (c): return ''
end = '' @staticmethod
def end_color (): return ''
@staticmethod
def escape (s): return s
@staticmethod
def newline (): return '\n'
class ANSI: class ANSI:
red = '\033[41;37;1m' @staticmethod
green = '\033[42;37;1m' def start_color (c):
end = '\033[m' return {
'red': '\033[41;37;1m',
'green': '\033[42;37;1m',
'blue': '\033[44;37;1m',
}[c]
@staticmethod
def end_color ():
return '\033[m'
@staticmethod
def escape (s): return s
@staticmethod
def newline (): return '\n'
class HTML: class HTML:
red = '<span style="color:red">' @staticmethod
green = '<span style="color:green">' def start_color (c):
end = '</span>' return '<span style="background:%s">' % c
@staticmethod
def end_color ():
return '</span>'
@staticmethod
def escape (s): return cgi.escape (s)
@staticmethod
def newline (): return '<br/>\n'
@staticmethod @staticmethod
def Auto (argv = [], out = sys.stdout): def Auto (argv = [], out = sys.stdout):
if os.isatty (out.fileno ()): format = ColorFormatter.ANSI
color = Colors.ANSI if "--format" in argv:
else: argv.remove ("--format")
color = Colors.Null format = ColorFormatter.ANSI
if "--color" in argv: if "--format=ansi" in argv:
argv.remove ("--color") argv.remove ("--format=ansi")
color = Colors.ANSI format = ColorFormatter.ANSI
if "--color=ansi" in argv: if "--format=html" in argv:
argv.remove ("--color=ansi") argv.remove ("--format=html")
color = Colors.ANSI format = ColorFormatter.HTML
if "--color=html" in argv: if "--no-format" in argv:
argv.remove ("--color=html") argv.remove ("--no-format")
color = Colors.HTML format = ColorFormatter.Null
if "--no-color" in argv: return format
argv.remove ("--no-color")
color = Colors.Null
return color
@staticmethod class DiffColorizer:
def Default (argv = []):
return Colors.ANSI
class FancyDiffer:
diff_regex = re.compile ('([a-za-z0-9_]*)([^a-za-z0-9_]?)') diff_regex = re.compile ('([a-za-z0-9_]*)([^a-za-z0-9_]?)')
@staticmethod def __init__ (self, formatter, colors=diff_colors, symbols=diff_symbols):
def diff_lines (l1, l2, colors=Colors.Null): self.formatter = formatter
self.colors = colors
self.symbols = symbols
# Easy without colors def colorize_lines (self, lines):
if colors == Colors.Null: lines = (l if l else '' for l in lines)
if l1 == l2: ss = [self.diff_regex.sub (r'\1\n\2\n', l).splitlines (True) for l in lines]
return [' ', l1]
return ['-', l1, '+', l2]
ss = [FancyDiffer.diff_regex.sub (r'\1\n\2\n', l).splitlines (True) for l in (l1, l2)]
oo = ["",""] oo = ["",""]
st = [False, False] st = [False, False]
for l in difflib.Differ().compare (*ss): for l in difflib.Differ().compare (*ss):
@ -68,29 +84,47 @@ class FancyDiffer:
if l[0] == ' ': if l[0] == ' ':
for i in range(2): for i in range(2):
if st[i]: if st[i]:
oo[i] += colors.end oo[i] += self.formatter.end_color ()
st[i] = False st[i] = False
oo = [o + l[2:] for o in oo] oo = [o + self.formatter.escape (l[2:]) for o in oo]
continue continue
if l[0] == '-': if l[0] in self.symbols:
if not st[0]: i = self.symbols.index (l[0])
oo[0] += colors.red if not st[i]:
st[0] = True oo[i] += self.formatter.start_color (self.colors[i])
oo[0] += l[2:] st[i] = True
oo[i] += self.formatter.escape (l[2:])
continue continue
if l[0] == '+':
if not st[1]:
oo[1] += colors.green
st[1] = True
oo[1] += l[2:]
for i in range(2): for i in range(2):
if st[i]: if st[i]:
oo[i] += colors.end oo[i] += self.formatter.end_color ()
st[i] = 0 st[i] = False
oo = [o.replace ('\n', '') for o in oo] oo = [o.replace ('\n', '') for o in oo]
if oo[0] == oo[1]: return [s1+s2+self.formatter.newline () for (s1,s2) in zip (self.symbols, oo) if s2]
return [' ', oo[0], '\n']
return ['-', oo[0], '\n', '+', oo[1], '\n'] def colorize_diff (self, f):
lines = [None, None]
for l in f:
if l[0] not in self.symbols:
yield self.formatter.escape (l).replace ('\n', self.formatter.newline ())
continue
i = self.symbols.index (l[0])
if lines[i]:
# Flush
for line in self.colorize_lines (lines):
yield line
lines = [None, None]
lines[i] = l[1:]
if (all (lines)):
# Flush
for line in self.colorize_lines (lines):
yield line
lines = [None, None]
if (any (lines)):
# Flush
for line in self.colorize_lines (lines):
yield line
class ZipDiffer: class ZipDiffer: