Files
llmx/codex-rs/tui/src/status/format.rs
Ahmed Ibrahim 7355ca48c5 fix (#4251)
# External (non-OpenAI) Pull Request Requirements

Before opening this Pull Request, please read the dedicated
"Contributing" markdown file or your PR may be closed:
https://github.com/openai/codex/blob/main/docs/contributing.md

If your PR conforms to our contribution guidelines, replace this text
with a detailed and high quality description of your changes.
2025-09-25 15:12:25 -07:00

148 lines
3.9 KiB
Rust

use ratatui::prelude::*;
use ratatui::style::Stylize;
use std::collections::BTreeSet;
use unicode_width::UnicodeWidthChar;
use unicode_width::UnicodeWidthStr;
#[derive(Debug, Clone)]
pub(crate) struct FieldFormatter {
indent: &'static str,
label_width: usize,
value_offset: usize,
value_indent: String,
}
impl FieldFormatter {
pub(crate) const INDENT: &'static str = " ";
pub(crate) fn from_labels<S>(labels: impl IntoIterator<Item = S>) -> Self
where
S: AsRef<str>,
{
let label_width = labels
.into_iter()
.map(|label| UnicodeWidthStr::width(label.as_ref()))
.max()
.unwrap_or(0);
let indent_width = UnicodeWidthStr::width(Self::INDENT);
let value_offset = indent_width + label_width + 1 + 3;
Self {
indent: Self::INDENT,
label_width,
value_offset,
value_indent: " ".repeat(value_offset),
}
}
pub(crate) fn line(
&self,
label: &'static str,
value_spans: Vec<Span<'static>>,
) -> Line<'static> {
Line::from(self.full_spans(label, value_spans))
}
pub(crate) fn continuation(&self, mut spans: Vec<Span<'static>>) -> Line<'static> {
let mut all_spans = Vec::with_capacity(spans.len() + 1);
all_spans.push(Span::from(self.value_indent.clone()).dim());
all_spans.append(&mut spans);
Line::from(all_spans)
}
pub(crate) fn value_width(&self, available_inner_width: usize) -> usize {
available_inner_width.saturating_sub(self.value_offset)
}
pub(crate) fn full_spans(
&self,
label: &str,
mut value_spans: Vec<Span<'static>>,
) -> Vec<Span<'static>> {
let mut spans = Vec::with_capacity(value_spans.len() + 1);
spans.push(self.label_span(label));
spans.append(&mut value_spans);
spans
}
fn label_span(&self, label: &str) -> Span<'static> {
let mut buf = String::with_capacity(self.value_offset);
buf.push_str(self.indent);
buf.push_str(label);
buf.push(':');
let label_width = UnicodeWidthStr::width(label);
let padding = 3 + self.label_width.saturating_sub(label_width);
for _ in 0..padding {
buf.push(' ');
}
Span::from(buf).dim()
}
}
pub(crate) fn push_label(labels: &mut Vec<String>, seen: &mut BTreeSet<String>, label: &str) {
if seen.contains(label) {
return;
}
let owned = label.to_string();
seen.insert(owned.clone());
labels.push(owned);
}
pub(crate) fn line_display_width(line: &Line<'static>) -> usize {
line.iter()
.map(|span| UnicodeWidthStr::width(span.content.as_ref()))
.sum()
}
pub(crate) fn truncate_line_to_width(line: Line<'static>, max_width: usize) -> Line<'static> {
if max_width == 0 {
return Line::from(Vec::<Span<'static>>::new());
}
let mut used = 0usize;
let mut spans_out: Vec<Span<'static>> = Vec::new();
for span in line.spans {
let text = span.content.into_owned();
let style = span.style;
let span_width = UnicodeWidthStr::width(text.as_str());
if span_width == 0 {
spans_out.push(Span::styled(text, style));
continue;
}
if used >= max_width {
break;
}
if used + span_width <= max_width {
used += span_width;
spans_out.push(Span::styled(text, style));
continue;
}
let mut truncated = String::new();
for ch in text.chars() {
let ch_width = UnicodeWidthChar::width(ch).unwrap_or(0);
if used + ch_width > max_width {
break;
}
truncated.push(ch);
used += ch_width;
}
if !truncated.is_empty() {
spans_out.push(Span::styled(truncated, style));
}
break;
}
Line::from(spans_out)
}