Add context diff and tests for it

This commit is contained in:
Dima Kudosh
2016-02-28 19:14:11 +03:00
parent 0fa2c80be0
commit 3781894ffc
3 changed files with 85 additions and 2 deletions
+63 -1
View File
@@ -3,8 +3,9 @@ pub mod differ;
mod utils;
use std::collections::HashMap;
use sequencematcher::{SequenceMatcher, Sequence};
use utils::{format_range_unified};
use utils::{format_range_unified, format_range_context};
pub fn get_close_matches<'a>(word: &str, possibilities: Vec<&'a str>, n: usize, cutoff: f32) -> Vec<&'a str> {
@@ -63,3 +64,64 @@ pub fn unified_diff<T: Sequence>(first_sequence: &T, second_sequence: &T, from_f
}
res
}
pub fn context_diff<T: Sequence>(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<String> {
let mut res = Vec::new();
let mut prefix: HashMap<String, String> = HashMap::new();
prefix.insert(String::from("insert"), String::from("+ "));
prefix.insert(String::from("delete"), String::from("- "));
prefix.insert(String::from("replace"), String::from("! "));
prefix.insert(String::from("equal"), String::from(" "));
let mut started = false;
let mut matcher = SequenceMatcher::new(first_sequence, second_sequence);
for group in &matcher.get_grouped_opcodes(n) {
if !started {
started = true;
let from_date = format!("\t{}", from_file_date);
let to_date = format!("\t{}", to_file_date);
res.push( format!("*** {}{}{}", from_file, from_date, lineterm) );
res.push( format!("--- {}{}{}", to_file, to_date, lineterm) );
}
let (first, last) = (group.first().unwrap(), group.last().unwrap());
res.push(format!("***************{}", lineterm));
let file1_range = format_range_context(first.first_start, last.first_end);
res.push(format!("*** {} ****{}", file1_range, lineterm));
let mut any = false;
for opcode in group {
if opcode.tag == "replace" || opcode.tag == "delete" {
any = true;
break;
}
}
if any {
for opcode in group {
if opcode.tag != "insert" {
for i in opcode.first_start..opcode.first_end {
res.push( format!("{}{}", prefix.get(&opcode.tag).unwrap(), first_sequence.at_index(i).unwrap()) );
}
}
}
}
let file2_range = format_range_context(first.second_start, last.second_end);
res.push(format!("--- {} ----{}", file1_range, lineterm));
any = false;
for opcode in group {
if opcode.tag == "replace" || opcode.tag == "insert" {
any = true;
break;
}
}
if any {
for opcode in group {
if opcode.tag != "delete" {
for i in opcode.second_start..opcode.second_end {
res.push( format!("{}{}", prefix.get(&opcode.tag).unwrap(), second_sequence.at_index(i).unwrap()) );
}
}
}
}
}
res
}
+14 -1
View File
@@ -30,10 +30,23 @@ pub fn format_range_unified(start:usize, end: usize) -> String {
println!("{:?} {}", start, end);
let length = end - start;
if length == 1 {
return format!("{}", beginning)
return beginning.to_string()
}
if length == 0 {
beginning -= 1;
}
format!("{},{}", beginning, length)
}
pub fn format_range_context(start: usize, end: usize) -> String {
let mut beginning = start + 1;
let length = end - start;
if length == 0 {
beginning -= 1
}
if length <= 1 {
return beginning.to_string()
}
format!("{},{}", beginning, beginning + length - 1)
}
+8
View File
@@ -109,5 +109,13 @@ fn test_unified_diff() {
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");
}
#[test]
fn test_context_diff() {
let first_text = "one two three four".split(" ").collect::<Vec<&str>>();
let second_text = "zero one tree four".split(" ").collect::<Vec<&str>>();
let result = difflib::context_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 **** one! two! three four--- 1,4 ----+ zero one! tree four");
}