Compare commits

...

3 Commits

Author SHA1 Message Date
easong-openai
930abf46e8 fmt 2025-08-25 20:01:31 -07:00
easong-openai
b242da8a41 fmt 2025-08-25 19:59:44 -07:00
easong-openai
6215f7fd54 wrap for short terminals 2025-08-25 19:42:28 -07:00

View File

@@ -144,7 +144,13 @@ impl ChatComposer {
pub fn desired_height(&self, width: u16) -> u16 {
self.textarea.desired_height(width - 1)
+ match &self.active_popup {
ActivePopup::None => 1u16,
ActivePopup::None => {
if self.token_usage_info.is_some() && width < 90 {
2
} else {
1
}
}
ActivePopup::Command(c) => c.calculate_required_height(),
ActivePopup::File(c) => c.calculate_required_height(),
}
@@ -154,7 +160,13 @@ impl ChatComposer {
let popup_height = match &self.active_popup {
ActivePopup::Command(popup) => popup.calculate_required_height(),
ActivePopup::File(popup) => popup.calculate_required_height(),
ActivePopup::None => 1,
ActivePopup::None => {
if self.token_usage_info.is_some() && area.width < 90 {
2
} else {
1
}
}
};
let [textarea_rect, _] =
Layout::vertical([Constraint::Min(1), Constraint::Max(popup_height)]).areas(area);
@@ -1143,10 +1155,18 @@ impl ChatComposer {
impl WidgetRef for ChatComposer {
fn render_ref(&self, area: Rect, buf: &mut Buffer) {
// Determine if we should render a second footer row for tokens/context.
let needs_tokens_line = self.token_usage_info.is_some() && area.width < 90;
let popup_height = match &self.active_popup {
ActivePopup::Command(popup) => popup.calculate_required_height(),
ActivePopup::File(popup) => popup.calculate_required_height(),
ActivePopup::None => 1,
ActivePopup::None => {
if needs_tokens_line {
2
} else {
1
}
}
};
let [textarea_rect, popup_rect] =
Layout::vertical([Constraint::Min(1), Constraint::Max(popup_height)]).areas(area);
@@ -1191,8 +1211,7 @@ impl WidgetRef for ChatComposer {
hint.push(Span::from(" edit prev"));
}
// Append token/context usage info to the footer hints when available.
if let Some(token_usage_info) = &self.token_usage_info {
if !needs_tokens_line && let Some(token_usage_info) = &self.token_usage_info {
let token_usage = &token_usage_info.total_token_usage;
hint.push(Span::from(" "));
hint.push(
@@ -1220,6 +1239,34 @@ impl WidgetRef for ChatComposer {
Line::from(hint)
.style(Style::default().dim())
.render_ref(bottom_line_rect, buf);
if needs_tokens_line && let Some(token_usage_info) = &self.token_usage_info {
let token_usage = &token_usage_info.total_token_usage;
let mut text = String::from(" ");
text.push_str(&format!("{} tokens used", token_usage.blended_total()));
if let Some(context_window) = token_usage_info.model_context_window {
let last_token_usage = &token_usage_info.last_token_usage;
let percent_remaining: u8 = if context_window > 0 {
last_token_usage.percent_of_context_window_remaining(
context_window,
token_usage_info.initial_prompt_tokens,
)
} else {
100
};
text.push_str(" ");
text.push_str(&format!("{percent_remaining}% context left"));
}
Line::from(text).style(Style::default().dim()).render_ref(
Rect::new(
bottom_line_rect.x,
bottom_line_rect.y + 1,
bottom_line_rect.width,
1,
),
buf,
);
}
}
}
let border_style = if self.has_focus {