@@ -12,7 +12,7 @@ use crate::diff_util::constants::NO_NEW_LINE_AT_END_OF_FILE;
1212use std:: {
1313 collections:: HashMap ,
1414 fmt:: Write ,
15- fs:: { File , read_to_string } ,
15+ fs:: { read_to_string , File } ,
1616 io:: { self , BufReader , Read } ,
1717 os:: unix:: fs:: MetadataExt ,
1818 path:: PathBuf ,
@@ -322,7 +322,8 @@ impl<'a> FileDiff<'a> {
322322
323323 for hunk in self . hunks . hunks ( ) {
324324 println ! ( "***************" ) ;
325- let mut hunk_len = ( hunk. ln1_end ( ) - hunk. ln1_start ( ) + 2 * context) . min ( self . file1 . lines ( ) . len ( ) ) ;
325+ let mut hunk_len =
326+ ( hunk. ln1_end ( ) - hunk. ln1_start ( ) + 2 * context) . min ( self . file1 . lines ( ) . len ( ) ) ;
326327 let hunk_start = hunk. ln1_start ( ) . saturating_sub ( context) ;
327328
328329 // make sure we don't go out of bounds
@@ -331,7 +332,11 @@ impl<'a> FileDiff<'a> {
331332 }
332333
333334 println ! ( "*** {},{} ***" , hunk_start + 1 , hunk_start + hunk_len) ;
334- let h1_prefix = if hunk. ln2_start ( ) == hunk. ln2_end ( ) { "- " } else { "! " } ;
335+ let h1_prefix = if hunk. ln2_start ( ) == hunk. ln2_end ( ) {
336+ "- "
337+ } else {
338+ "! "
339+ } ;
335340
336341 // dont print context for empty hunk
337342 if hunk. ln1_start ( ) == hunk. ln1_end ( ) {
@@ -348,7 +353,8 @@ impl<'a> FileDiff<'a> {
348353 }
349354 }
350355
351- let mut hunk_len = ( hunk. ln2_end ( ) - hunk. ln2_start ( ) + 2 * context) . min ( self . file2 . lines ( ) . len ( ) ) ;
356+ let mut hunk_len =
357+ ( hunk. ln2_end ( ) - hunk. ln2_start ( ) + 2 * context) . min ( self . file2 . lines ( ) . len ( ) ) ;
352358 let hunk_start = hunk. ln2_start ( ) . saturating_sub ( context) ;
353359
354360 // make sure we don't go out of bounds
@@ -357,7 +363,11 @@ impl<'a> FileDiff<'a> {
357363 }
358364
359365 println ! ( "--- {},{} ---" , hunk_start + 1 , hunk_start + hunk_len) ;
360- let h2_prefix = if hunk. ln1_start ( ) == hunk. ln1_end ( ) { "+ " } else { "! " } ;
366+ let h2_prefix = if hunk. ln1_start ( ) == hunk. ln1_end ( ) {
367+ "+ "
368+ } else {
369+ "! "
370+ } ;
361371
362372 // dont print context for empty hunk
363373 if hunk. ln2_start ( ) == hunk. ln2_end ( ) {
@@ -374,20 +384,6 @@ impl<'a> FileDiff<'a> {
374384 }
375385 }
376386 }
377-
378- }
379-
380- fn print_line ( & self , lines : & mut String , start : usize , end : usize , prefix : & str ) -> Result < usize , std:: fmt:: Error > {
381- let mut j = 0 ;
382- for i in start..end {
383- if prefix == "+" {
384- writeln ! ( lines, "{prefix}{}" , self . file2. line( i) ) ?;
385- } else {
386- writeln ! ( lines, "{prefix}{}" , self . file1. line( i) ) ?;
387- }
388- j += 1 ;
389- }
390- Ok ( j)
391387 }
392388
393389 fn print_unified ( & mut self , unified : usize ) -> Result < ( ) , std:: fmt:: Error > {
@@ -400,86 +396,45 @@ impl<'a> FileDiff<'a> {
400396 Self :: get_header( self . file2, & self . format_options. label2)
401397 ) ;
402398
403- // curr_pos to keep track of the current position in both files
404- let mut curr_pos1 = 0 ;
405- let mut curr_pos2 = 0 ;
406- // `context_start` and `hunk_len` to get the values for the hunk header
407- // keep track of the lines where context start
408- let mut context_start1 = 0 ;
409- let mut context_start2 = 0 ;
410- // keep track of the length of the current hunk
411- let mut hunk1_len = 0 ;
412- let mut hunk2_len = 0 ;
413- let mut offset: usize ;
414- let mut lines = String :: new ( ) ;
399+ let mut diff_disp = DiffDisplay :: new ( ) ;
415400
416401 for hunk in self . hunks . hunks ( ) {
417402 // move cursor to the start of context for first hunk
418- if curr_pos1 == 0 {
403+ if diff_disp . curr_pos1 == 0 {
419404 if hunk. ln1_start ( ) > unified {
420- // this is guaranteed to be >= 0 due to the above conditions
421- curr_pos1 = hunk . ln1_start ( ) - unified ;
422- curr_pos2 = hunk. ln2_start ( ) - unified;
405+ // this is guaranteed to be >= 0 due to the above conditions
406+ diff_disp
407+ . update_curr_pos ( hunk. ln1_start ( ) - unified , hunk . ln2_start ( ) - unified) ;
423408 }
424- context_start1 = curr_pos1 + 1 ;
425- context_start2 = curr_pos2 + 1 ;
409+ diff_disp. set_context_start ( ) ;
426410 }
427411
428412 // do we have enough context between hunks?
429- if ( curr_pos1 != 0 ) && ( hunk. ln1_start ( ) - curr_pos1 > unified * 2 ) {
413+ if ( diff_disp. curr_pos1 != 0 ) && ( hunk. ln1_start ( ) - diff_disp. curr_pos1 > unified * 2 )
414+ {
430415 // print the context after the previous hunk
431- offset = self . print_line ( & mut lines, curr_pos1, curr_pos1 + unified, " " ) ?;
432- hunk1_len += offset;
433- hunk2_len += offset;
416+ diff_disp. write_line (
417+ self . file1 ,
418+ diff_disp. curr_pos1 ,
419+ diff_disp. curr_pos1 + unified,
420+ " " ,
421+ ) ?;
434422 // print a new section start
435- curr_pos1 = hunk. ln1_start ( ) - unified;
436- curr_pos2 = hunk. ln2_start ( ) - unified;
437- println ! (
438- "@@ -{},{} +{},{} @@" ,
439- context_start1,
440- hunk1_len,
441- context_start2,
442- hunk2_len
443- ) ;
444- if lines. ends_with ( '\n' ) {
445- lines. pop ( ) ;
446- }
447- println ! ( "{}" , lines) ;
448- lines. clear ( ) ;
449- context_start1 = curr_pos1 + 1 ;
450- context_start2 = curr_pos2 + 1 ;
451- hunk1_len = 0 ;
452- hunk2_len = 0 ;
453-
423+ diff_disp. update_curr_pos ( hunk. ln1_start ( ) - unified, hunk. ln2_start ( ) - unified) ;
424+ diff_disp. print_section ( ) ;
454425 }
455426
456427 // print context before current hunk
457- offset = self . print_line ( & mut lines, curr_pos1, hunk. ln1_start ( ) , " " ) ?;
458- curr_pos1 += offset;
459- hunk1_len += offset;
460- hunk2_len += offset;
428+ diff_disp. write_line ( self . file1 , diff_disp. curr_pos1 , hunk. ln1_start ( ) , " " ) ?;
461429 // print delete hunk
462- offset = self . print_line ( & mut lines, hunk. ln1_start ( ) , hunk. ln1_end ( ) , "-" ) ?;
463- curr_pos1 += offset;
464- hunk1_len += offset;
430+ diff_disp. write_line ( self . file1 , hunk. ln1_start ( ) , hunk. ln1_end ( ) , "-" ) ?;
465431 // print insert hunk
466- offset = self . print_line ( & mut lines, hunk. ln2_start ( ) , hunk. ln2_end ( ) , "+" ) ?;
467- hunk2_len += offset;
432+ diff_disp. write_line ( self . file2 , hunk. ln2_start ( ) , hunk. ln2_end ( ) , "+" ) ?;
468433 }
469434
470435 // print final hunk
471- if !lines. is_empty ( ) {
472- println ! (
473- "@@ -{},{} +{},{} @@" ,
474- context_start1,
475- hunk1_len,
476- context_start2,
477- hunk2_len
478- ) ;
479- if lines. ends_with ( '\n' ) {
480- lines. pop ( ) ;
481- }
482- println ! ( "{}" , lines) ;
436+ if !diff_disp. hunk_lines . is_empty ( ) {
437+ diff_disp. print_section ( ) ;
483438 }
484439
485440 if !self . file1 . ends_with_newline ( ) {
@@ -503,3 +458,80 @@ impl<'a> FileDiff<'a> {
503458 }
504459 }
505460}
461+
462+ pub struct DiffDisplay {
463+ curr_pos1 : usize ,
464+ curr_pos2 : usize ,
465+ //`context_start` and `hunk_len` to get the values for the hunk header
466+ //keep track of the lines where context start
467+ context_start1 : usize ,
468+ context_start2 : usize ,
469+ //keep track of the length of the current hunk
470+ hunk1_len : usize ,
471+ hunk2_len : usize ,
472+ hunk_lines : String ,
473+ }
474+
475+ impl DiffDisplay {
476+ pub fn new ( ) -> Self {
477+ Self {
478+ curr_pos1 : 0 ,
479+ curr_pos2 : 0 ,
480+ context_start1 : 0 ,
481+ context_start2 : 0 ,
482+ hunk1_len : 0 ,
483+ hunk2_len : 0 ,
484+ hunk_lines : String :: new ( ) ,
485+ }
486+ }
487+
488+ pub fn write_line (
489+ & mut self ,
490+ file : & FileData ,
491+ start : usize ,
492+ end : usize ,
493+ prefix : & str ,
494+ ) -> Result < ( ) , std:: fmt:: Error > {
495+ let mut offset = 0 ;
496+ for i in start..end {
497+ writeln ! ( self . hunk_lines, "{prefix}{}" , file. line( i) ) ?;
498+ offset += 1 ;
499+ }
500+ if prefix == " " {
501+ self . curr_pos1 += offset;
502+ self . hunk1_len += offset;
503+ self . hunk2_len += offset;
504+ } else if prefix == "-" {
505+ self . curr_pos1 += offset;
506+ self . hunk1_len += offset;
507+ } else if prefix == "+" {
508+ self . hunk2_len += offset;
509+ }
510+ Ok ( ( ) )
511+ }
512+
513+ pub fn set_context_start ( & mut self ) {
514+ self . context_start1 = self . curr_pos1 + 1 ;
515+ self . context_start2 = self . curr_pos2 + 1 ;
516+ }
517+ pub fn update_curr_pos ( & mut self , curr1 : usize , curr2 : usize ) {
518+ self . curr_pos1 = curr1;
519+ self . curr_pos2 = curr2;
520+ }
521+
522+ pub fn print_section ( & mut self ) {
523+ println ! (
524+ "@@ -{},{} +{},{} @@" ,
525+ self . context_start1, self . hunk1_len, self . context_start2, self . hunk2_len
526+ ) ;
527+ if self . hunk_lines . ends_with ( '\n' ) {
528+ self . hunk_lines . pop ( ) ;
529+ }
530+ println ! ( "{}" , self . hunk_lines) ;
531+ self . hunk_lines . clear ( ) ;
532+ self . context_start1 = self . curr_pos1 + 1 ;
533+ self . context_start2 = self . curr_pos2 + 1 ;
534+ self . hunk1_len = 0 ;
535+ self . hunk2_len = 0 ;
536+ }
537+ }
0 commit comments