blob: cbb7dff4fccedf6e4dadf5f0f51d2da20edb071f [file] [log] [blame] [edit]
pub(crate) fn diff(
expected: &str,
actual: &str,
expected_name: impl std::fmt::Display,
actual_name: impl std::fmt::Display,
palette: crate::Palette,
) -> String {
diff_inner(
expected,
actual,
&palette.info.paint(expected_name).to_string(),
&palette.error.paint(actual_name).to_string(),
palette,
)
}
pub(crate) fn diff_inner(
expected: &str,
actual: &str,
expected_name: &str,
actual_name: &str,
palette: crate::Palette,
) -> String {
let expected: Vec<_> = crate::lines::LinesWithTerminator::new(expected).collect();
let actual: Vec<_> = crate::lines::LinesWithTerminator::new(actual).collect();
let diff = difflib::unified_diff(
&expected,
&actual,
expected_name,
actual_name,
&palette.info.paint("expected").to_string(),
&palette.error.paint("actual").to_string(),
0,
);
let mut diff = colorize_diff(diff, palette);
diff.insert(0, "\n".to_owned());
diff.join("")
}
#[cfg(feature = "color")]
fn colorize_diff(mut lines: Vec<String>, palette: crate::Palette) -> Vec<String> {
for (i, line) in lines.iter_mut().enumerate() {
match (i, line.as_bytes().get(0)) {
(0, _) => {
if let Some((prefix, body)) = line.split_once(' ') {
*line = format!("{} {}", palette.info.paint(prefix), body);
}
}
(1, _) => {
if let Some((prefix, body)) = line.split_once(' ') {
*line = format!("{} {}", palette.error.paint(prefix), body);
}
}
(_, Some(b'-')) => {
let (prefix, body) = line.split_at(1);
*line = format!("{}{}", palette.info.paint(prefix), body);
}
(_, Some(b'+')) => {
let (prefix, body) = line.split_at(1);
*line = format!("{}{}", palette.error.paint(prefix), body);
}
(_, Some(b'@')) => {
*line = format!("{}", palette.hint.paint(&line));
}
_ => (),
}
}
lines
}
#[cfg(not(feature = "color"))]
fn colorize_diff(lines: Vec<String>, _palette: crate::Palette) -> Vec<String> {
lines
}