@@ -14,6 +14,7 @@ use crate::diff_util::{
1414
1515use std:: {
1616 collections:: HashMap ,
17+ fmt:: Write ,
1718 fs:: { File , read_to_string} ,
1819 io:: { self , BufReader , Read } ,
1920 os:: unix:: fs:: MetadataExt ,
@@ -442,13 +443,13 @@ impl<'a> FileDiff<'a> {
442443 }
443444 }
444445
445- fn print_line ( & self , start : usize , end : usize , prefix : & str ) -> usize {
446- let mut j = start ;
446+ fn print_line ( & self , lines : & mut String , start : usize , end : usize , prefix : & str ) -> usize {
447+ let mut j = 0 ;
447448 for i in start..end {
448449 if prefix == "+" {
449- println ! ( "{prefix}{}" , self . file2. line( i) ) ;
450+ writeln ! ( lines , "{prefix}{}" , self . file2. line( i) ) ;
450451 } else {
451- println ! ( "{prefix}{}" , self . file1. line( i) ) ;
452+ writeln ! ( lines , "{prefix}{}" , self . file1. line( i) ) ;
452453 }
453454 j += 1 ;
454455 }
@@ -465,45 +466,90 @@ impl<'a> FileDiff<'a> {
465466 Self :: get_header( self . file2, & self . format_options. label2)
466467 ) ;
467468
469+ // curr_pos to keep track of the current position in both files
468470 let mut curr_pos1 = 0 ;
471+ let mut curr_pos2 = 0 ;
472+ // `context_start` and `hunk_len` to get the values for the hunk header
473+ // keep track of the lines where context start
474+ let mut context_start1 = 0 ;
475+ let mut context_start2 = 0 ;
476+ // keep track of the length of the current hunk
477+ let mut hunk1_len = 0 ;
478+ let mut hunk2_len = 0 ;
479+ let mut offset = 0 ;
480+ let mut lines = String :: new ( ) ;
469481
470482 for hunk in self . hunks . hunks ( ) {
471- // print context before first hunk
472- if ( curr_pos1 == 0 ) && ( hunk. ln1_start ( ) > unified) {
483+ // move cursor to the start of context for first hunk
484+ if curr_pos1 == 0 {
485+ if hunk. ln1_start ( ) > unified {
473486 // this is guaranteed to be >= 0 due to the above conditions
474487 curr_pos1 = hunk. ln1_start ( ) - unified;
475- // FIXME: the numbers printed below are wrong
476- println ! (
477- "@@ -{},{} +{},{} @@" ,
478- hunk. ln1_start( ) + 1 ,
479- hunk. ln1_end( ) - hunk. ln1_start( ) ,
480- hunk. ln2_start( ) + 1 ,
481- hunk. ln2_end( ) - hunk. ln2_start( )
482- ) ;
488+ curr_pos2 = hunk. ln2_start ( ) - unified;
489+ }
490+ context_start1 = curr_pos1 + 1 ;
491+ context_start2 = curr_pos2 + 1 ;
483492 }
484493
485494 // do we have enough context between hunks?
486495 if ( curr_pos1 != 0 ) && ( hunk. ln1_start ( ) - curr_pos1 > unified * 2 ) {
487- // print the context after the last hunk
488- _ = self . print_line ( curr_pos1, curr_pos1 + unified, " " ) ;
496+ // print the context after the previous hunk
497+ offset = self . print_line ( & mut lines, curr_pos1, curr_pos1 + unified, " " ) ;
498+ // println!("Offset after final context: {}", offset);
499+ hunk1_len += offset;
500+ hunk2_len += offset;
489501 // print a new section start
490- // FIXME: the numbers printed below are wrong
502+ curr_pos1 = hunk. ln1_start ( ) - unified;
503+ curr_pos2 = hunk. ln2_start ( ) - unified;
491504 println ! (
492505 "@@ -{},{} +{},{} @@" ,
493- hunk . ln1_start ( ) + 1 ,
494- hunk . ln1_end ( ) - hunk . ln1_start ( ) ,
495- hunk . ln2_start ( ) + 1 ,
496- hunk . ln2_end ( ) - hunk . ln2_start ( )
506+ context_start1 ,
507+ hunk1_len ,
508+ context_start2 ,
509+ hunk2_len
497510 ) ;
498- curr_pos1 = hunk. ln1_start ( ) - unified
511+ if lines. ends_with ( '\n' ) {
512+ lines. pop ( ) ;
513+ }
514+ println ! ( "{}" , lines) ;
515+ lines. clear ( ) ;
516+ context_start1 = curr_pos1 + 1 ;
517+ context_start2 = curr_pos2 + 1 ;
518+ hunk1_len = 0 ;
519+ hunk2_len = 0 ;
520+
499521 }
500522
501523 // print context before current hunk
502- _ = self . print_line ( curr_pos1, hunk. ln1_start ( ) , " " ) ;
524+ offset = self . print_line ( & mut lines, curr_pos1, hunk. ln1_start ( ) , " " ) ;
525+ // println!("Offset after initial context: {}", offset);
526+ curr_pos1 += offset;
527+ hunk1_len += offset;
528+ hunk2_len += offset;
503529 // print delete hunk
504- curr_pos1 = self . print_line ( hunk. ln1_start ( ) , hunk. ln1_end ( ) , "-" ) ;
530+ offset = self . print_line ( & mut lines, hunk. ln1_start ( ) , hunk. ln1_end ( ) , "-" ) ;
531+ // println!("Offset after delete context: {}", offset);
532+ curr_pos1 += offset;
533+ hunk1_len += offset;
505534 // print insert hunk
506- _ = self . print_line ( hunk. ln2_start ( ) , hunk. ln2_end ( ) , "+" ) ;
535+ offset = self . print_line ( & mut lines, hunk. ln2_start ( ) , hunk. ln2_end ( ) , "+" ) ;
536+ // println!("Offset after insert context: {}", offset);
537+ hunk2_len += offset;
538+ }
539+
540+ // print final hunk
541+ if !lines. is_empty ( ) {
542+ println ! (
543+ "@@ -{},{} +{},{} @@" ,
544+ context_start1,
545+ hunk1_len,
546+ context_start2,
547+ hunk2_len
548+ ) ;
549+ if lines. ends_with ( '\n' ) {
550+ lines. pop ( ) ;
551+ }
552+ println ! ( "{}" , lines) ;
507553 }
508554
509555 if !self . file1 . ends_with_newline ( ) {
0 commit comments