Skip to content

Commit c87446b

Browse files
committed
use DiffDisplay struct
1 parent 92ff4cc commit c87446b

File tree

1 file changed

+113
-81
lines changed

1 file changed

+113
-81
lines changed

text/diff_util/file_diff.rs

Lines changed: 113 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use crate::diff_util::constants::NO_NEW_LINE_AT_END_OF_FILE;
1212
use 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

Comments
 (0)