use ratatui::prelude::*;
use crate::tui::app::{DiffHunk, DiffLineKind};
pub fn header_line(path: &str) -> Line<'static> {
Line::from(vec![
Span::raw(" "),
Span::styled("📝", Style::default().fg(Color::Magenta)),
Span::raw(" "),
Span::styled(path.to_string(), Style::default().fg(Color::White)),
])
}
pub fn body_lines(hunks: &[DiffHunk]) -> Vec<Line<'static>> {
let mut out = Vec::new();
for hunk in hunks {
for dl in &hunk.lines {
let (sigil, color) = match dl.kind {
DiffLineKind::Add => ("+", Color::Green),
DiffLineKind::Remove => ("-", Color::Red),
DiffLineKind::Context => (" ", Color::Gray),
};
out.push(Line::from(vec![
Span::styled(" │ ".to_string(), Style::default().fg(Color::Gray)),
Span::styled(sigil.to_string(), Style::default().fg(color)),
Span::raw(" "),
Span::styled(dl.text.clone(), Style::default().fg(color)),
]));
}
}
out
}
pub fn empty_stub_line(path: &str) -> Line<'static> {
Line::from(vec![
Span::styled(" │ ".to_string(), Style::default().fg(Color::Gray)),
Span::styled(
format!("Updated {path}"),
Style::default()
.fg(Color::Gray)
.add_modifier(Modifier::ITALIC),
),
])
}
#[cfg(test)]
mod tests {
use super::*;
use crate::tui::app::DiffLine;
fn span_style_colors(line: &Line) -> Vec<Color> {
line.spans.iter().filter_map(|s| s.style.fg).collect()
}
#[test]
fn diff_renders_plus_minus_with_colors() {
let hunks = vec![DiffHunk {
lines: vec![
DiffLine {
kind: DiffLineKind::Add,
text: "new line".into(),
},
DiffLine {
kind: DiffLineKind::Remove,
text: "old line".into(),
},
DiffLine {
kind: DiffLineKind::Context,
text: "ctx".into(),
},
],
}];
let lines = body_lines(&hunks);
assert_eq!(lines.len(), 3);
assert!(span_style_colors(&lines[0]).contains(&Color::Green));
assert!(span_style_colors(&lines[1]).contains(&Color::Red));
assert!(span_style_colors(&lines[2]).contains(&Color::Gray));
}
#[test]
fn header_line_contains_path() {
let line = header_line("src/agent.rs");
let text: String = line.spans.iter().map(|s| s.content.as_ref()).collect();
assert!(text.contains("src/agent.rs"));
assert!(text.contains("📝"));
}
}