use ratatui::Frame;
use ratatui::layout::Rect;
use ratatui::text::Text;
use ratatui::widgets::Paragraph;
use crate::component::styled_text::{StyledContent, StyledInline};
use crate::theme::Theme;
pub fn styled_line(frame: &mut Frame, area: Rect, inlines: &[StyledInline], theme: &Theme) {
if area.width == 0 || area.height == 0 {
return;
}
let content = StyledContent::new().line(inlines.to_vec());
let lines = content.render_lines(area.width, theme);
let text = Text::from(lines);
let paragraph = Paragraph::new(text);
frame.render_widget(paragraph, area);
}
#[cfg(test)]
mod tests {
use super::*;
use crate::component::styled_text::StyledInline;
use crate::component::test_utils::setup_render;
use ratatui::style::Color;
#[test]
fn test_styled_line_renders_inlines() {
let inlines = vec![
StyledInline::Plain("hello ".to_string()),
StyledInline::bold("bold".to_string()),
StyledInline::Plain(" world".to_string()),
];
let (mut terminal, theme) = setup_render(40, 1);
terminal
.draw(|frame| {
styled_line(frame, frame.area(), &inlines, &theme);
})
.unwrap();
let plain = terminal.backend().to_string();
insta::assert_snapshot!(plain);
}
#[test]
fn test_styled_line_applies_theme_color() {
let inlines = vec![StyledInline::colored("err".to_string(), Color::Red)];
let (mut terminal, theme) = setup_render(20, 1);
terminal
.draw(|frame| {
styled_line(frame, frame.area(), &inlines, &theme);
})
.unwrap();
let ansi = terminal.backend().to_ansi();
assert!(
ansi.contains("\x1b[31m"),
"expected red (31m) ANSI fg for Colored(Red) inline, got:\n{ansi}",
);
}
#[test]
fn test_styled_line_truncates_to_area_width() {
let inlines = vec![StyledInline::Plain(
"abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWX".to_string(),
)];
let (mut terminal, theme) = setup_render(20, 1);
terminal
.draw(|frame| {
styled_line(frame, frame.area(), &inlines, &theme);
})
.unwrap();
let plain = terminal.backend().to_string();
insta::assert_snapshot!(plain);
}
#[test]
fn test_styled_line_empty_inlines_renders_nothing() {
let inlines: &[StyledInline] = &[];
let (mut terminal, theme) = setup_render(40, 1);
terminal
.draw(|frame| {
styled_line(frame, frame.area(), inlines, &theme);
})
.unwrap();
let plain = terminal.backend().to_string();
insta::assert_snapshot!(plain);
}
#[test]
fn test_styled_line_no_chrome_drawn() {
let inlines = vec![StyledInline::Plain("only first row".to_string())];
let (mut terminal, theme) = setup_render(40, 3);
terminal
.draw(|frame| {
styled_line(frame, frame.area(), &inlines, &theme);
})
.unwrap();
let plain = terminal.backend().to_string();
insta::assert_snapshot!(plain);
let rows: Vec<&str> = plain.lines().collect();
assert!(
rows.len() >= 3,
"expected 3 rows, got {}: {plain}",
rows.len()
);
let row1_blank = rows[1].chars().all(|c| c == ' ');
let row2_blank = rows[2].chars().all(|c| c == ' ');
assert!(
row1_blank,
"row 1 should be blank (no chrome), got: {:?}",
rows[1]
);
assert!(
row2_blank,
"row 2 should be blank (no chrome), got: {:?}",
rows[2]
);
}
}