Codex Handbook
tui/src/status/format.rs 147 lines
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)}