use super::{DisplayLine, DisplayRole};
pub(crate) fn render_diff(input: &str) -> Vec<DisplayLine> {
if input.is_empty() {
return vec![DisplayLine::from_span("", DisplayRole::DiffContext)];
}
input
.split('\n')
.map(|line| DisplayLine::from_span(line, classify_diff_line(line)))
.collect()
}
fn classify_diff_line(line: &str) -> DisplayRole {
if line.starts_with("diff --git ")
|| line.starts_with("index ")
|| line.starts_with("--- ")
|| line.starts_with("+++ ")
{
DisplayRole::DiffFileHeader
} else if line.starts_with("@@") {
DisplayRole::DiffHunkHeader
} else if line.starts_with("\\ No newline at end of file") {
DisplayRole::DiffMetadata
} else if line.starts_with('+') {
DisplayRole::DiffInserted
} else if line.starts_with('-') {
DisplayRole::DiffRemoved
} else if line.starts_with('!') {
DisplayRole::DiffChanged
} else {
DisplayRole::DiffContext
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn classifies_git_diff_roles() {
let lines = render_diff(
"diff --git a/x b/x\n@@ -1 +1 @@\n-old\n+new\n context\n\\ No newline at end of file",
);
let roles: Vec<_> = lines.iter().map(|line| line.spans[0].role).collect();
assert_eq!(
roles,
vec![
DisplayRole::DiffFileHeader,
DisplayRole::DiffHunkHeader,
DisplayRole::DiffRemoved,
DisplayRole::DiffInserted,
DisplayRole::DiffContext,
DisplayRole::DiffMetadata,
]
);
}
#[test]
fn context_diff_changed_lines_classify_as_changed() {
let lines = render_diff("! old line\n! new line");
let roles: Vec<_> = lines.iter().map(|line| line.spans[0].role).collect();
assert_eq!(
roles,
vec![DisplayRole::DiffChanged, DisplayRole::DiffChanged]
);
}
}