pub fn generate_preview(
old_lines: &[String],
new_lines: &[String],
start: usize,
end: usize,
) -> Vec<String> {
let mut preview = Vec::new();
preview.push(format!("--- original (lines {}-{})", start, end));
preview.push(format!("+++ modified ({} lines)", new_lines.len()));
preview.push(String::new());
let ctx_before = start.saturating_sub(3);
for line in old_lines.iter().take(start - 1).skip(ctx_before) {
preview.push(format!(
" {} | {}",
ctx_before + 1,
line.trim_end_matches('\n')
));
}
if ctx_before < start - 1 {
preview.push(" ...".to_string());
}
let splice_start = start - 1;
let splice_end = end.min(old_lines.len());
for (idx, line) in old_lines
.iter()
.enumerate()
.take(splice_end)
.skip(splice_start)
{
preview.push(format!("-{}| {}", idx + 1, line.trim_end_matches('\n')));
}
for (i, line) in new_lines.iter().enumerate() {
let trimmed = line.trim_end_matches('\n');
preview.push(format!("+{}| {}", start + i, trimmed));
}
if splice_end < old_lines.len() {
let ctx_after = (splice_end + 3).min(old_lines.len());
if splice_end < ctx_after {
preview.push(" ...".to_string());
}
for line in old_lines.iter().take(ctx_after).skip(splice_end) {
preview.push(format!(
" {} | {}",
splice_end + 1,
line.trim_end_matches('\n')
));
}
}
preview
}
#[cfg(test)]
mod tests {
use super::*;
fn make_lines(text: &str) -> Vec<String> {
text.split_inclusive('\n').map(String::from).collect()
}
#[test]
fn test_generate_preview_simple() {
let old = make_lines("line1\nline2\nline3\nline4\nline5\n");
let new = vec!["new2\n".to_string()];
let preview = generate_preview(&old, &new, 2, 2);
assert!(
preview[0].starts_with("--- original"),
"Header missing: {}",
preview[0]
);
assert!(
preview[1].starts_with("+++ modified"),
"Header missing: {}",
preview[1]
);
assert!(
preview
.iter()
.any(|l| l.starts_with("-2|") && l.contains("line2")),
"Must show removal of line 2"
);
assert!(
preview
.iter()
.any(|l| l.starts_with("+2|") && l.contains("new2")),
"Must show addition of new2"
);
assert!(
preview.len() >= 5,
"Preview too short: {}",
preview.join("\n")
);
}
}