#!/usr/bin/python3
# dv
#
# Highlights diff output (unified format):
# Usage: diff -u file1 file2 | dv
# git diff | dv
# cvs diff -u -D '1 year ago' -D '11 month ago' | dv
#
# Accepts input in system default encoding (usually utf8), conversion may be needed:
# diff -u file1 file2 | iconv -f koi8-r | dv
#
# To install python3 and tkinter on ubuntu, run:
# sudo aptitude install python3-tk
#
import tkinter as tk
from tkinter import ttk
import difflib as dl
import sys
import itertools as it
FONT = ('Nimbus Mono L', 13)
FONT_B = ('Nimbus Mono L', 13, 'bold')
TAGS = {'diff' : {'font':FONT_B, 'foreground':'SkyBlue4'},
'addition' : {'font':FONT_B, 'background':'LimeGreen', 'foreground':'yellow'},
'removal' : {'font':FONT_B, 'background':'indian red', 'foreground':'yellow'},
'removal-equal' : {'font':FONT_B, 'background':'gray80', 'foreground':'yellow'},
'removal-insert' : {'font':FONT_B, 'background':'pink2', 'foreground':'yellow'},
'removal-replace' : {'font':FONT_B, 'background':'pink3', 'foreground':'yellow'},
'removal-delete' : {'font':FONT_B, 'background':'pink4', 'foreground':'yellow'},
'addition-equal' : {'font':FONT_B, 'background':'gray82', 'foreground':'yellow'},
'addition-insert' : {'font':FONT_B, 'background':'cyan2', 'foreground':'yellow'},
'addition-replace' : {'font':FONT_B, 'background':'cyan3', 'foreground':'yellow'},
'addition-delete' : {'font':FONT_B, 'background':'cyan4', 'foreground':'yellow'}}
tags = []
def getTextIndex(s, sLine, i):
linesAdd = s.count("\n", 0, i)
column = i - s.rfind("\n", 0, i) - 1
return str(sLine + linesAdd) + '.' + str(column)
def addTag(s, sLine, i1, i2, name):
tag = (name, getTextIndex(s, sLine, i1), getTextIndex(s, sLine, i2))
tags.append(tag)
def compare(a, aLine, b, bLine):
s = dl.SequenceMatcher(None, a, b)
for tag, i1, i2, j1, j2 in s.get_opcodes():
addTag(a, aLine, i1, i2, 'removal-' + tag);
addTag(b, bLine, j1, j2, 'addition-' + tag);
diffText = ''
addition = ''
removal = ''
additionLine = 0
removalLine = 0
lineN = 0
for line in it.chain(sys.stdin, [' ']):
lineN += 1
if line.startswith('+') and not line.startswith('+++ '):
addition += line[1:]
if not additionLine:
additionLine = lineN
elif line.startswith('-') and not line.startswith('--- '):
removal += line[1:]
if not removalLine:
removalLine = lineN
else:
if removal and addition:
compare(removal, removalLine, addition, additionLine)
elif removal:
addTag(removal, removalLine, 0, len(removal), 'removal')
elif addition:
addTag(addition, additionLine, 0, len(addition), 'addition')
if removal:
diffText += removal
removal = ''
removalLine = 0
if addition:
diffText += addition
addition = ''
additionLine = 0
if not line.startswith(' '):
diffText += line
addTag(line, lineN, 0, len(line)-1, 'diff')
else:
diffText += line[1:]
if diffText:
root = tk.Tk()
root.title('Diff Viewer: ' + str(lineN) + ' lines')
text = tk.Text(root, width=100, height=40, font=FONT)
text.grid(column=0, row=0, sticky='nsew')
sb = ttk.Scrollbar(command=text.yview, orient='vertical')
sb.grid(column=1, row=0, sticky='ns')
text['yscrollcommand'] = sb.set
root.columnconfigure(0, weight=1)
root.rowconfigure(0, weight=1)
text.insert('end', diffText)
text['state'] = 'disabled'
for t in tags:
text.tag_add(*t)
for t,v in TAGS.items():
text.tag_config(t, **v)
root.mainloop()
Diff to Previous Revision
--- revision 3 2010-10-23 05:33:54
+++ revision 4 2010-10-29 10:48:15
@@ -18,6 +18,7 @@
from tkinter import ttk
import difflib as dl
import sys
+import itertools as it
FONT = ('Nimbus Mono L', 13)
FONT_B = ('Nimbus Mono L', 13, 'bold')
@@ -61,7 +62,7 @@
removalLine = 0
lineN = 0
-for line in sys.stdin:
+for line in it.chain(sys.stdin, [' ']):
lineN += 1
if line.startswith('+') and not line.startswith('+++ '):
addition += line[1:]