Refactor TUI message formatting: add role label toggle, improve indentation, and adjust role label styling logic. Optimize provider handling.
This commit is contained in:
@@ -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<String> {
|
||||
// 1) Normalize line breaks to '\n' (handles CR, NEL, LS, PS)
|
||||
let normalized: String = message
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -68,27 +68,33 @@ fn render_messages(frame: &mut Frame<'_>, area: Rect, app: &ChatApp) {
|
||||
|
||||
let mut lines: Vec<Line> = 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),
|
||||
|
||||
Reference in New Issue
Block a user