use similar::TextDiff;
pub fn unified_diff(old: &str, new: &str, context: usize) -> String {
if old == new {
return String::new();
}
TextDiff::from_lines(old, new)
.unified_diff()
.context_radius(context)
.header("a", "b")
.to_string()
}
pub fn changed_lines(old: &str, new: &str) -> usize {
TextDiff::from_lines(old, new)
.iter_all_changes()
.filter(|c| c.tag() != similar::ChangeTag::Equal)
.count()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn identical_inputs_produce_no_diff() {
assert_eq!(unified_diff("a\nb\n", "a\nb\n", 1), "");
assert_eq!(changed_lines("a\nb\n", "a\nb\n"), 0);
}
#[test]
fn diff_shows_only_changed_hunk_with_context() {
let old = "one\ntwo\nthree\nfour\nfive\n";
let new = "one\ntwo\nTHREE\nfour\nfive\n";
let d = unified_diff(old, new, 1);
assert!(d.contains("-three"));
assert!(d.contains("+THREE"));
assert!(!d.contains("one"));
assert!(!d.contains("five"));
}
#[test]
fn changed_lines_counts_inserts_and_deletes() {
assert_eq!(changed_lines("a\nb\nc\n", "a\nB\nc\n"), 2);
}
}