@@ -1094,7 +1094,7 @@ def _format_range_unified(start, stop):
10941094 return '{},{}' .format (beginning , length )
10951095
10961096def unified_diff (a , b , fromfile = '' , tofile = '' , fromfiledate = '' ,
1097- tofiledate = '' , n = 3 , lineterm = '\n ' ):
1097+ tofiledate = '' , n = 3 , lineterm = '\n ' , color = False ):
10981098 r"""
10991099 Compare two sequences of lines; generate the delta as a unified diff.
11001100
@@ -1111,6 +1111,9 @@ def unified_diff(a, b, fromfile='', tofile='', fromfiledate='',
11111111 For inputs that do not have trailing newlines, set the lineterm
11121112 argument to "" so that the output will be uniformly newline free.
11131113
1114+ Set `color` to True to inject ANSI color codes and make the output look
1115+ like what `git diff --color` shows.
1116+
11141117 The unidiff format normally has a header for filenames and modification
11151118 times. Any or all of these may be specified using strings for
11161119 'fromfile', 'tofile', 'fromfiledate', and 'tofiledate'.
@@ -1134,20 +1137,34 @@ def unified_diff(a, b, fromfile='', tofile='', fromfiledate='',
11341137 four
11351138 """
11361139
1140+ # {tag: ANSI color escape code}
1141+ colors = {
1142+ "delete" : "\033 [31m" , # red
1143+ "insert" : "\033 [32m" , # green
1144+ "header" : "\033 [1m" , # bold / increased intensity
1145+ "hunk" : "\033 [36m" , # cyan
1146+ }
1147+ reset = "\033 [m"
1148+
11371149 _check_types (a , b , fromfile , tofile , fromfiledate , tofiledate , lineterm )
11381150 started = False
11391151 for group in SequenceMatcher (None ,a ,b ).get_grouped_opcodes (n ):
11401152 if not started :
11411153 started = True
11421154 fromdate = '\t {}' .format (fromfiledate ) if fromfiledate else ''
11431155 todate = '\t {}' .format (tofiledate ) if tofiledate else ''
1144- yield '--- {}{}{}' .format (fromfile , fromdate , lineterm )
1145- yield '+++ {}{}{}' .format (tofile , todate , lineterm )
1156+ _line = '--- {}{}{}' .format (fromfile , fromdate , lineterm )
1157+ yield colors ["header" ] + _line + reset if color else _line
1158+ _line = '+++ {}{}{}' .format (tofile , todate , lineterm )
1159+ yield colors ["header" ] + _line + reset if color else _line
11461160
11471161 first , last = group [0 ], group [- 1 ]
11481162 file1_range = _format_range_unified (first [1 ], last [2 ])
11491163 file2_range = _format_range_unified (first [3 ], last [4 ])
1150- yield '@@ -{} +{} @@{}' .format (file1_range , file2_range , lineterm )
1164+ _line = '@@ -{} +{} @@{}' .format (file1_range , file2_range , lineterm )
1165+ if color :
1166+ _line = colors ["hunk" ] + _line + reset
1167+ yield _line
11511168
11521169 for tag , i1 , i2 , j1 , j2 in group :
11531170 if tag == 'equal' :
@@ -1156,10 +1173,12 @@ def unified_diff(a, b, fromfile='', tofile='', fromfiledate='',
11561173 continue
11571174 if tag in {'replace' , 'delete' }:
11581175 for line in a [i1 :i2 ]:
1159- yield '-' + line
1176+ _line = '-' + line
1177+ yield colors ["delete" ] + _line + reset if color else _line
11601178 if tag in {'replace' , 'insert' }:
11611179 for line in b [j1 :j2 ]:
1162- yield '+' + line
1180+ _line = '+' + line
1181+ yield colors ["insert" ] + _line + reset if color else _line
11631182
11641183
11651184########################################################################
0 commit comments