30
30
'Differ' ,'IS_CHARACTER_JUNK' , 'IS_LINE_JUNK' , 'context_diff' ,
31
31
'unified_diff' , 'diff_bytes' , 'HtmlDiff' , 'Match' ]
32
32
33
+ from _colorize import can_colorize , get_theme
33
34
from heapq import nlargest as _nlargest
34
35
from collections import namedtuple as _namedtuple
35
36
from types import GenericAlias
@@ -1094,7 +1095,7 @@ def _format_range_unified(start, stop):
1094
1095
return '{},{}' .format (beginning , length )
1095
1096
1096
1097
def unified_diff (a , b , fromfile = '' , tofile = '' , fromfiledate = '' ,
1097
- tofiledate = '' , n = 3 , lineterm = '\n ' ):
1098
+ tofiledate = '' , n = 3 , lineterm = '\n ' , * , color = False ):
1098
1099
r"""
1099
1100
Compare two sequences of lines; generate the delta as a unified diff.
1100
1101
@@ -1111,6 +1112,10 @@ def unified_diff(a, b, fromfile='', tofile='', fromfiledate='',
1111
1112
For inputs that do not have trailing newlines, set the lineterm
1112
1113
argument to "" so that the output will be uniformly newline free.
1113
1114
1115
+ Set 'color' to True to enable output in color, similar to
1116
+ 'git diff --color'. Even if enabled, it can be
1117
+ controlled using environment variables such as 'NO_COLOR'.
1118
+
1114
1119
The unidiff format normally has a header for filenames and modification
1115
1120
times. Any or all of these may be specified using strings for
1116
1121
'fromfile', 'tofile', 'fromfiledate', and 'tofiledate'.
@@ -1134,32 +1139,37 @@ def unified_diff(a, b, fromfile='', tofile='', fromfiledate='',
1134
1139
four
1135
1140
"""
1136
1141
1142
+ if color and can_colorize ():
1143
+ t = get_theme (force_color = True ).difflib
1144
+ else :
1145
+ t = get_theme (force_no_color = True ).difflib
1146
+
1137
1147
_check_types (a , b , fromfile , tofile , fromfiledate , tofiledate , lineterm )
1138
1148
started = False
1139
1149
for group in SequenceMatcher (None ,a ,b ).get_grouped_opcodes (n ):
1140
1150
if not started :
1141
1151
started = True
1142
1152
fromdate = '\t {}' .format (fromfiledate ) if fromfiledate else ''
1143
1153
todate = '\t {}' .format (tofiledate ) if tofiledate else ''
1144
- yield ' --- {}{}{}' . format ( fromfile , fromdate , lineterm )
1145
- yield ' +++ {}{}{}' . format ( tofile , todate , lineterm )
1154
+ yield f' { t . header } --- { fromfile } { fromdate } { lineterm } { t . reset } '
1155
+ yield f' { t . header } +++ { tofile } { todate } { lineterm } { t . reset } '
1146
1156
1147
1157
first , last = group [0 ], group [- 1 ]
1148
1158
file1_range = _format_range_unified (first [1 ], last [2 ])
1149
1159
file2_range = _format_range_unified (first [3 ], last [4 ])
1150
- yield ' @@ -{} +{} @@{}' . format ( file1_range , file2_range , lineterm )
1160
+ yield f' { t . hunk } @@ -{ file1_range } +{ file2_range } @@{ lineterm } { t . reset } '
1151
1161
1152
1162
for tag , i1 , i2 , j1 , j2 in group :
1153
1163
if tag == 'equal' :
1154
1164
for line in a [i1 :i2 ]:
1155
- yield ' ' + line
1165
+ yield f' { t . context } { line } { t . reset } '
1156
1166
continue
1157
1167
if tag in {'replace' , 'delete' }:
1158
1168
for line in a [i1 :i2 ]:
1159
- yield '-' + line
1169
+ yield f' { t . removed } - { line } { t . reset } '
1160
1170
if tag in {'replace' , 'insert' }:
1161
1171
for line in b [j1 :j2 ]:
1162
- yield '+' + line
1172
+ yield f' { t . added } + { line } { t . reset } '
1163
1173
1164
1174
1165
1175
########################################################################
0 commit comments