@setoelkahfi / sigit / commits / c385aa9

Add Banner role for colorized banner art rendering

Seto Elkahfi committed Apr 14, 2026 at 18:42 UTC c385aa96ddccc2d7deafeb398085a2c8091dfb59
1 file changed +27 -3
src/chat.rs
+27 -3
index 79ecbf9..c85a611 100644 --- a/src/chat.rs +++ b/src/chat.rs @@ -25,6 +25,8 @@ enum Role { User, Assistant, System, + /// Banner art — rendered with per-character digit colorization. + Banner, } struct ChatMessage { @@ -53,6 +55,13 @@ impl ChatMessage { text: text.into(), } } + + fn banner(text: impl Into<String>) -> Self { + Self { + role: Role::Banner, + text: text.into(), + } + } } // ── App state ──────────────────────────────────────────────────────────────── @@ -89,7 +98,7 @@ impl App { fn new() -> Self { let mut messages = Vec::new(); for line in BANNER_ART.lines() { - messages.push(ChatMessage::system(line)); + messages.push(ChatMessage::banner(line)); } messages.push(ChatMessage::system("")); messages.push(ChatMessage::system(format!( @@ -161,12 +170,16 @@ impl App { } } +fn banner_char_color(_ch: char) -> Color { + Color::White +} + /// Estimate how many terminal rows a message takes once wrapped. fn wrapped_line_count(text: &str, role: Role, width: usize) -> u16 { let prefix_len = match role { Role::User => 6, // "you > " - Role::Assistant => 7, // "siGit > " — wait, that's 8. Let's just use 7 for "siGit> " - Role::System => 0, + Role::Assistant => 8, // "siGit > " + Role::System | Role::Banner => 0, }; let effective = if width > prefix_len { width - prefix_len @@ -343,6 +356,17 @@ fn render_chat_message<'a>(lines: &mut Vec<Line<'a>>, msg: &ChatMessage) { ))); } } + Role::Banner => { + for segment in &text_lines { + let spans: Vec<Span<'_>> = segment + .chars() + .map(|ch| { + Span::styled(ch.to_string(), Style::default().fg(banner_char_color(ch))) + }) + .collect(); + lines.push(Line::from(spans)); + } + } } }