@@ -310,6 +310,38 @@ def counts(self) -> tuple[int, int]:
310310 additions += 1
311311 return additions , removals
312312
313+ @classmethod
314+ def _highlight_diff_lines (
315+ cls , lines_a : list [Content ], lines_b : list [Content ]
316+ ) -> tuple [list [Content ], list [Content ]]:
317+ """Diff two groups of lines.
318+
319+ Args:
320+ lines_a: Lines before.
321+ lines_b: Lines after
322+
323+ Returns:
324+ A pair of highlighted lists of lines.
325+ """
326+ code_a = Content ("\n " ).join (content for content in lines_a )
327+ code_b = Content ("\n " ).join (content for content in lines_b )
328+ sequence_matcher = difflib .SequenceMatcher (
329+ lambda character : character in " \t " ,
330+ code_a .plain ,
331+ code_b .plain ,
332+ autojunk = True ,
333+ )
334+ spans_a : list [Span ] = []
335+ spans_b : list [Span ] = []
336+ for tag , i1 , i2 , j1 , j2 in sequence_matcher .get_opcodes ():
337+ if tag in {"delete" , "replace" }:
338+ spans_a .append (Span (i1 , i2 , "on $error 40%" ))
339+ if tag in {"insert" , "replace" }:
340+ spans_b .append (Span (j1 , j2 , "on $success 40%" ))
341+ diffed_lines_a = code_a .add_spans (spans_a ).split ("\n " )
342+ diffed_lines_b = code_b .add_spans (spans_b ).split ("\n " )
343+ return diffed_lines_a , diffed_lines_b
344+
313345 @property
314346 def highlighted_code_lines (self ) -> tuple [list [Content ], list [Content ]]:
315347 """Get syntax highlighted code for both files, as a list of lines.
@@ -331,35 +363,21 @@ def highlighted_code_lines(self) -> tuple[list[Content], list[Content]]:
331363 "\n " .join (text_lines_b ), language = language2 , path = self .path2
332364 )
333365
334- if self .code_before :
335-
336- sequence_matcher = difflib .SequenceMatcher (
337- lambda character : character in " \t " ,
338- code_a .plain ,
339- code_b .plain ,
340- autojunk = True ,
341- )
342- code_a_spans : list [Span ] = []
343- code_b_spans : list [Span ] = []
344-
345- for tag , i1 , i2 , j1 , j2 in sequence_matcher .get_opcodes ():
346- if (
347- tag in {"delete" , "replace" }
348- and "\n " not in code_a .plain [i1 : i2 + 1 ]
349- ):
350- code_a_spans .append (Span (i1 , i2 , "on $error 40%" ))
351- if (
352- tag in {"insert" , "replace" }
353- and "\n " not in code_b .plain [j1 : j2 + 1 ]
354- ):
355- code_b_spans .append (Span (j1 , j2 , "on $success 40%" ))
356-
357- code_a = code_a .add_spans (code_a_spans )
358- code_b = code_b .add_spans (code_b_spans )
359-
360366 lines_a = code_a .split ("\n " )
361367 lines_b = code_b .split ("\n " )
368+
369+ if self .code_before :
370+ for group in self .grouped_opcodes :
371+ for tag , i1 , i2 , j1 , j2 in group :
372+ if tag == "replace" and (j2 - j1 ) / (i2 - i1 ) <= 1.5 :
373+ diff_lines_a , diff_lines_b = self ._highlight_diff_lines (
374+ lines_a [i1 :i2 ], lines_b [j1 :j2 ]
375+ )
376+ lines_a [i1 :i2 ] = diff_lines_a
377+ lines_b [j1 :j2 ] = diff_lines_b
378+
362379 self ._highlighted_code_lines = (lines_a , lines_b )
380+
363381 return self ._highlighted_code_lines
364382
365383 def get_title (self ) -> Content :
0 commit comments