changeset 18:83d58ccc70bf

Interleave adjacent runs of consecutive old and new lines into alternating old and new lines.
author Peter Hosey <hg@boredzo.org>
date Wed, 05 Jan 2011 06:56:01 -0800
parents 54a209909531
children b709258a2fc2
files diff-colorize.py
diffstat 1 files changed, 49 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/diff-colorize.py
+++ b/diff-colorize.py
@@ -41,6 +41,32 @@ You can customize the color numbers used
 * DIFF_HUNK_START_COLOR (lines starting with "@@")
 """.strip()
 
+def interleave(*sequences):
+	"Generator that yields one object from each sequence in turn."
+	
+	def zip_pad(*iterables, **kw):
+		"Downloaded from http://code.activestate.com/recipes/497007/"
+		from itertools import izip, chain
+		if kw:
+			assert len(kw) == 1
+			pad = kw["pad"]
+		else:
+			pad = None
+		done = [len(iterables)-1]
+		def pad_iter():
+			if not done[0]:
+				return
+			done[0] -= 1
+			while 1:
+				yield pad
+		iterables = [chain(seq, pad_iter()) for seq in iterables]
+		return izip(*iterables)
+
+	for objects in zip_pad(*sequences):
+		for obj in objects:
+			if obj is not None:
+				yield obj
+
 # Everything in the unified diff format is identified by a prefix. The prefixes are:
 # 'Index: ':    File marker (unified diff)
 # 'diff --git': File marker (git-style diff)
@@ -127,7 +153,30 @@ if __name__ == "__main__":
 		# Standard input is a TTY, meaning that the user ran 'diff-colorize' at the shell prompt, without redirecting anything into it. Print usage info and exit.
 		sys.exit(USAGE)
 
+	# Buffers to support interleaving old and new lines that were contiguous runs.
+	buffer_old = [] # '-' lines
+	buffer_new = [] # '+' lines
+
 	for line in fileinput.input():
+		if line.startswith('-') and not line.startswith('---'):
+			buffer_old.append(line)
+			continue
+		elif line.startswith('+') and not line.startswith('+++'):
+			buffer_new.append(line)
+			continue
+		else:
+			# Flush the buffers, interleaving the lines.
+			for buffered_line in interleave(buffer_old, buffer_new):
+				prefix = '-' if buffered_line.startswith('-') else '+'
+				buffered_line = buffered_line[len(prefix):]
+
+				sys.stdout.write(prefixes[prefix])
+				sys.stdout.write(buffered_line)
+				sys.stdout.write(RESET_FORMAT)
+
+			del buffer_old[:]
+			del buffer_new[:]
+
 		for prefix_to_test in prefixes:
 			if line.startswith(prefix_to_test):
 				sys.stdout.write(prefixes[prefix_to_test])