Diffing & Patching
FIXME
diff
diff
⮳ is an LCS-based slice and string diffing implementation.
use diff::Result; // Add to your `Cargo.toml`: // [dependencies] // diff = "0.1.13" # Or latest fn main() -> anyhow::Result<()> { let old_text = "Hello world\nThis is a test\nOf the diff library"; let new_text = "Hello world\nThis is a sample\nOf the diff library\nWith a new line"; // Computes the diff between the lines of two strings. let changeset = diff::lines(old_text, new_text); // Print the diff for chunk in changeset { match chunk { Result::Both(s, _) => println!(" {}", s), Result::Left(s) => println!("-{}", s), Result::Right(s) => println!("+{}", s), } } Ok(()) }
similar
similar
⮳ is a dependency-free crate for Rust that implements different diffing algorithms and high level interfaces for it.
use std::fmt; use console::Style; use similar::ChangeTag; use similar::TextDiff; // Add to your `Cargo.toml`: // [dependencies] // similar = "2.7.0" # Or latest // console = "0.15.11" # Or latest struct Line(Option<usize>, String); impl fmt::Display for Line { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.0 { None => write!(f, " {}", self.1), Some(idx) => write!(f, "{:4} {}", idx + 1, self.1), } } } fn line_diff() { // Original and modified text let old_text = "Hello World\nThis is a test\nfor the `similar` crate\nto demonstrate diffing"; let new_text = "Hello Rust\nThis is a test\nusing the `similar` crate\nto demonstrate diffing\nwith added line"; // Generate a diff with context let diff = TextDiff::from_lines(old_text, new_text); // Define styles for different types of changes let add_style = Style::new().green(); let remove_style = Style::new().red(); let unchanged_style = Style::new(); // Print the styled diff println!("Text Difference:"); for change in diff.iter_all_changes() { let (sign, style) = match change.tag() { ChangeTag::Delete => ("-", &remove_style), ChangeTag::Insert => ("+", &add_style), ChangeTag::Equal => (" ", &unchanged_style), }; // Format the line with line number and styling let line = Line( change.old_index().or(change.new_index()), format!("{}{}", sign, change.value()), ); println!("{}", style.apply_to(line)); } // Use the unified_diff format for comparison println!("\nUnified Diff Format:"); let mut unified = diff.unified_diff(); let unified = unified.context_radius(2).header("old_file", "new_file"); print!("{}", unified); } // Creates a diff of words. // This splits the text into words and whitespace. fn word_diff() { let text1 = "The quick brown fox jumps over the lazy dog"; let text2 = "The quick red fox jumps over the sleepy dog"; let diff = TextDiff::from_words(text1, text2); print!("\nWord-by-word changes: "); for change in diff.iter_all_changes() { match change.tag() { ChangeTag::Delete => print!("\x1b[31m{}\x1b[0m", change.value()), ChangeTag::Insert => print!("\x1b[32m{}\x1b[0m", change.value()), ChangeTag::Equal => print!("{}", change.value()), } } println!(); } fn main() { line_diff(); word_diff(); }
Related Topics
- Development Tools.
- Strings.