From 0fa2c80be0853c66bbb31038dd42411b3b61e3f5 Mon Sep 17 00:00:00 2001 From: Dima Kudosh Date: Sun, 28 Feb 2016 18:24:03 +0300 Subject: [PATCH] Add unified diff and tests for it --- src/lib.rs | 25 ++++++++++++------------- src/sequencematcher.rs | 22 +--------------------- src/utils.rs | 1 + tests/test.rs | 10 ++++++++++ 4 files changed, 24 insertions(+), 34 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 263a75a..38082df 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,7 +3,7 @@ pub mod differ; mod utils; -use sequencematcher::SequenceMatcher; +use sequencematcher::{SequenceMatcher, Sequence}; use utils::{format_range_unified}; @@ -24,9 +24,9 @@ pub fn get_close_matches<'a>(word: &str, possibilities: Vec<&'a str>, n: usize, res.truncate(n); res.iter().map(|x| x.1).collect() } -/* -pub fn unified_diff(first_sequence: &str, second_sequence: &str, from_file: &str, to_file: &str, - from_file_date: &str, to_file_date: &str, n: usize, lineterm: char) -> Vec { + +pub fn unified_diff(first_sequence: &T, second_sequence: &T, from_file: &str, to_file: &str, + from_file_date: &str, to_file_date: &str, n: usize, lineterm: &str) -> Vec { let mut res = Vec::new(); let mut started = false; let mut matcher = SequenceMatcher::new(first_sequence, second_sequence); @@ -39,28 +39,27 @@ pub fn unified_diff(first_sequence: &str, second_sequence: &str, from_file: &str res.push( format!("+++ {}{}{}", to_file, to_date, lineterm) ); } let (first, last) = (group.first().unwrap(), group.last().unwrap()); - let file1_range = format_range_unified(first.first_start, first.first_end); - let file2_range = format_range_unified(last.second_start, last.second_end); + let file1_range = format_range_unified(first.first_start, last.first_end); + let file2_range = format_range_unified(first.second_start, last.second_end); res.push( format!("@@ -{} +{} @@{}", file1_range, file2_range, lineterm) ); for code in group { if code.tag == "equal" { - for line in slice_str(first_sequence, code.first_start, code.first_end).unwrap().split_whitespace() { - res.push( format!(" {}", line) ); + for i in code.first_start..code.first_end { + res.push( format!(" {}", first_sequence.at_index(i).unwrap()) ); } continue; } if code.tag == "replace" || code.tag == "delete" { - for line in slice_str(first_sequence, code.first_start, code.first_end).unwrap().split_whitespace() { - res.push( format!("-{}", line) ); + for i in code.first_start..code.first_end { + res.push( format!("-{}", first_sequence.at_index(i).unwrap()) ); } } if code.tag == "replace" || code.tag == "insert" { - for line in slice_str(second_sequence, code.second_start, code.second_end).unwrap().split_whitespace() { - res.push( format!("+{}", line) ); + for i in code.second_start..code.second_end { + res.push( format!("+{}", second_sequence.at_index(i).unwrap()) ); } } } } res } -*/ \ No newline at end of file diff --git a/src/sequencematcher.rs b/src/sequencematcher.rs index 2b2f9d8..22ef27f 100644 --- a/src/sequencematcher.rs +++ b/src/sequencematcher.rs @@ -86,7 +86,6 @@ impl<'a> Sequence for Vec<&'a str> { } } - pub struct SequenceMatcher<'a, T: 'a + ?Sized + Sequence>{ first_sequence: &'a T, second_sequence: &'a T, @@ -257,26 +256,7 @@ impl<'a, T: ?Sized + Sequence> SequenceMatcher<'a, T>{ self.matching_blocks = Some(non_adjacent); self.matching_blocks.as_ref().unwrap().clone() } -/* -if self.opcodes is not None: - return self.opcodes - i = j = 0 - self.opcodes = answer = [] - for ai, bj, size in self.get_matching_blocks(): - tag = '' - if i < ai and j < bj: - tag = 'replace' - elif i < ai: - tag = 'delete' - elif j < bj: - tag = 'insert' - if tag: - answer.append( (tag, i, ai, j, bj) ) - i, j = ai+size, bj+size - if size: - answer.append( ('equal', ai, i, bj, j) ) - return answer -*/ + pub fn get_opcodes(&mut self) -> Vec{ if self.opcodes.as_ref().is_some(){ return self.opcodes.as_ref().unwrap().clone() diff --git a/src/utils.rs b/src/utils.rs index c4f7ea7..a855a9e 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -27,6 +27,7 @@ pub fn count_leading(line: &str, c: char) -> usize { pub fn format_range_unified(start:usize, end: usize) -> String { let mut beginning = start + 1; + println!("{:?} {}", start, end); let length = end - start; if length == 1 { return format!("{}", beginning) diff --git a/tests/test.rs b/tests/test.rs index f1e2f23..58ef026 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -100,4 +100,14 @@ fn test_differ_compare() { let differ = Differ::new(); let result = differ.compare(&first_text, &second_text).join(""); assert_eq!(result, "- one\n? ^\n+ ore\n? ^\n- two\n- three\n? -\n+ tree\n+ emu\n"); +} + +#[test] +fn test_unified_diff() { + let first_text = "one two three four".split(" ").collect::>(); + let second_text = "zero one tree four".split(" ").collect::>(); + let result = difflib::unified_diff(&first_text, &second_text, "Original", "Current", + "2005-01-26 23:30:50", "2010-04-02 10:20:52", 3, "").join(""); + assert_eq!(result, "--- Original\t2005-01-26 23:30:50+++ Current\t2010-04-02 10:20:52@@ -1,4 +1,4 @@+zero one-two-three+tree four"); + } \ No newline at end of file