Change behavior of inline diff to be word based

This also fixes a bug with bad indexes and updates the inline terminal
example.
This commit is contained in:
Armin Ronacher 2021-01-31 22:02:08 +01:00
parent 459fdfdf9d
commit f3e401fc17
4 changed files with 208 additions and 43 deletions

View file

@ -1,39 +1,56 @@
use console::Style;
use std::fmt;
use std::fs::read_to_string;
use std::process::exit;
use console::{style, Style};
use similar::text::{ChangeTag, TextDiff};
fn main() {
let diff = TextDiff::from_lines(
"schtzngrmm\nschtzngrmm\nt-t-t-t\nt-t-t-t\ngrrrmmmmm\nt-t-t-t\n\
s---------c---------h\ntzngrmm\ntzngrmm\ntzngrmm\ngrrrmmmmm\n\
schtzn\nschtzn\nt-t-t-t\nt-t-t-t\nschtzngrmm\nschtzngrmm\n\
tssssssssssssss\ngrrt\ngrrrrrt\ngrrrrrrrrrt\nscht\nscht\n\
t-t-t-t-t-t-t-t-t-t\nscht\ntzngrmm\ntzngrmm\nt-t-t-t-t-t-t-t-t-t\n\
scht\nscht\nscht\nscht\nscht\ngrrrrrrrrrrrrrrrrrrrrrrrrrrrr\nt-tt",
"schützengraben\nschützengraben\nt-t-t-t\nt-t-t-t\ngrrrmmmmm\nt-t-t-t\n\
s---------c---------h\ntzngrmm\ntzngrmm\ntzngrmm\ngrrrmmmmm\nschützen\n\
schützen\nt-t-t-t\nt-t-t-t\nschützengraben\nschützengraben\n\
tssssssssssssss\ngrrt\ngrrrrrt\ngrrrrrrrrrt\nscht\nscht\n\
t-t-t-t-t-t-t-t-t-t\nscht\ntzngrmm\ntzngrmm\nt-t-t-t-t-t-t-t-t-t\n\
scht\nscht\nscht\nscht\nscht\ngrrrrrrrrrrrrrrrrrrrrrrrrrrrr\nt-tt",
);
struct Line(Option<usize>);
for op in diff.ops() {
for change in diff.iter_inline_changes(op) {
let (sign, style) = match change.tag() {
ChangeTag::Delete => ("-", Style::new().red()),
ChangeTag::Insert => ("+", Style::new().green()),
ChangeTag::Equal => (" ", Style::new()),
};
print!("{}", style.apply_to(sign).bold(),);
for &(emphasized, value) in change.values() {
if emphasized {
print!("{}", style.apply_to(value).underlined().on_black());
} else {
print!("{}", style.apply_to(value));
impl fmt::Display for Line {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.0 {
None => write!(f, " "),
Some(idx) => write!(f, "{:<4}", idx + 1),
}
}
}
fn main() {
let args: Vec<_> = std::env::args_os().collect();
if args.len() != 3 {
eprintln!("usage: terminal-inline [old] [new]");
exit(1);
}
let old = read_to_string(&args[1]).unwrap();
let new = read_to_string(&args[2]).unwrap();
let diff = TextDiff::from_lines(&old, &new);
for group in diff.grouped_ops(5) {
for op in group {
for change in diff.iter_inline_changes(&op) {
let (sign, s) = match change.tag() {
ChangeTag::Delete => ("-", Style::new().red()),
ChangeTag::Insert => ("+", Style::new().green()),
ChangeTag::Equal => (" ", Style::new()),
};
print!(
"{}{} |{}",
style(Line(change.old_index())).dim(),
style(Line(change.new_index())).dim(),
s.apply_to(sign).bold(),
);
for &(emphasized, value) in change.values() {
if emphasized {
print!("{}", s.apply_to(value).underlined().on_black());
} else {
print!("{}", s.apply_to(value));
}
}
if change.is_missing_newline() {
println!();
}
}
if change.is_missing_newline() {
println!();
}
}
}