Add context diff and tests for it
This commit is contained in:
+63
-1
@@ -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
@@ -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)
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
Reference in New Issue
Block a user