From 6ddc66d8648ba5b3f42b28448eb72b89ca5ba843 Mon Sep 17 00:00:00 2001 From: vikingowl Date: Sat, 27 Sep 2025 07:11:57 +0200 Subject: [PATCH] Refactor TUI message formatting: add role label toggle, improve indentation, and adjust role label styling logic. Optimize provider handling. --- crates/owlen-core/src/formatting.rs | 5 +++++ crates/owlen-tui/src/chat_app.rs | 4 ++-- crates/owlen-tui/src/ui.rs | 28 +++++++++++++++++----------- 3 files changed, 24 insertions(+), 13 deletions(-) diff --git a/crates/owlen-core/src/formatting.rs b/crates/owlen-core/src/formatting.rs index 2c7aa5c..6971cd5 100644 --- a/crates/owlen-core/src/formatting.rs +++ b/crates/owlen-core/src/formatting.rs @@ -30,6 +30,11 @@ impl MessageFormatter { self.wrap_width = width.max(20); } + /// Whether role labels should be shown alongside messages + pub fn show_role_labels(&self) -> bool { + self.show_role_labels + } + pub fn format_message(&self, message: &Message) -> Vec { // 1) Normalize line breaks to '\n' (handles CR, NEL, LS, PS) let normalized: String = message diff --git a/crates/owlen-tui/src/chat_app.rs b/crates/owlen-tui/src/chat_app.rs index c85f9d1..c6f174a 100644 --- a/crates/owlen-tui/src/chat_app.rs +++ b/crates/owlen-tui/src/chat_app.rs @@ -154,7 +154,7 @@ impl ChatApp { self.models = all_models; // Populate available_providers - let mut providers = self + let providers = self .models .iter() .map(|m| m.provider.clone()) @@ -410,7 +410,7 @@ impl ChatApp { self.models = all_models; // Populate available_providers - let mut providers = self + let providers = self .models .iter() .map(|m| m.provider.clone()) diff --git a/crates/owlen-tui/src/ui.rs b/crates/owlen-tui/src/ui.rs index 7fcd540..944a6a8 100644 --- a/crates/owlen-tui/src/ui.rs +++ b/crates/owlen-tui/src/ui.rs @@ -68,27 +68,33 @@ fn render_messages(frame: &mut Frame<'_>, area: Rect, app: &ChatApp) { let mut lines: Vec = Vec::new(); for (message_index, message) in conversation.messages.iter().enumerate() { - let (prefix, color) = match message.role { - Role::User => ("👤 You:", Color::LightBlue), - Role::Assistant => ("🤖 Assistant:", Color::LightMagenta), - Role::System => ("⚙️ System:", Color::Cyan), + let role = &message.role; + let prefix = match role { + Role::User => "👤 You:", + Role::Assistant => "🤖 Assistant:", + Role::System => "⚙️ System:", }; - let mut formatted = formatter.format_message(message); + let formatted = formatter.format_message(message); let is_streaming = message .metadata .get("streaming") .and_then(|v| v.as_bool()) .unwrap_or(false); - lines.push(Line::from(Span::styled( - prefix, - Style::default().fg(color).add_modifier(Modifier::BOLD), - ))); + let show_role_labels = formatter.show_role_labels(); + let indent = if show_role_labels { " " } else { "" }; + + if show_role_labels { + lines.push(Line::from(Span::styled( + prefix, + role_color(role).add_modifier(Modifier::BOLD), + ))); + } for (i, line) in formatted.iter().enumerate() { let mut spans = Vec::new(); - spans.push(Span::raw(format!(" {}", line.clone()))); + spans.push(Span::raw(format!("{indent}{line}"))); if i == formatted.len() - 1 && is_streaming { spans.push(Span::styled(" ▌", Style::default().fg(Color::Magenta))); } @@ -359,7 +365,7 @@ fn centered_rect(percent_x: u16, percent_y: u16, area: Rect) -> Rect { .split(vertical[1])[1] } -fn role_color(role: Role) -> Style { +fn role_color(role: &Role) -> Style { match role { Role::User => Style::default().fg(Color::LightBlue), Role::Assistant => Style::default().fg(Color::LightMagenta),