Codex Handbook
tui/src/bottom_pane/status_surface_preview.rs 279 lines
use std::collections::BTreeMap;use ratatui::text::Line;use super::status_line_from_segments;use super::status_line_setup::StatusLineItem;#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]pub(crate) enum StatusSurfacePreviewItem {    AppName,    ProjectName,    ProjectRoot,    CurrentDir,    Status,    ThreadTitle,    GitBranch,    PullRequestNumber,    BranchChanges,    Permissions,    ApprovalMode,    ContextRemaining,    ContextUsed,    FiveHourLimit,    WeeklyLimit,    CodexVersion,    ContextWindowSize,    UsedTokens,    TotalInputTokens,    TotalOutputTokens,    SessionId,    FastMode,    RawOutput,    Model,    ModelWithReasoning,    Reasoning,    TaskProgress,}impl StatusSurfacePreviewItem {    fn placeholder(self) -> &'static str {        match self {            StatusSurfacePreviewItem::AppName => "codex",            StatusSurfacePreviewItem::ProjectName => "my-project",            StatusSurfacePreviewItem::ProjectRoot => "my-project",            StatusSurfacePreviewItem::CurrentDir => "~/my-project/subdir",            StatusSurfacePreviewItem::Status => "Working",            StatusSurfacePreviewItem::ThreadTitle => "thread title",            StatusSurfacePreviewItem::GitBranch => "feat/awesome-feature",            StatusSurfacePreviewItem::PullRequestNumber => "PR #123",            StatusSurfacePreviewItem::BranchChanges => "+12 -3",            StatusSurfacePreviewItem::Permissions => "Workspace",            StatusSurfacePreviewItem::ApprovalMode => "on-request",            StatusSurfacePreviewItem::ContextRemaining => "Context 0% left",            StatusSurfacePreviewItem::ContextUsed => "Context 0% used",            StatusSurfacePreviewItem::FiveHourLimit => "primary 0%",            StatusSurfacePreviewItem::WeeklyLimit => "secondary 0%",            StatusSurfacePreviewItem::CodexVersion => "0.0.0",            StatusSurfacePreviewItem::ContextWindowSize => "0 window",            StatusSurfacePreviewItem::UsedTokens => "0 used",            StatusSurfacePreviewItem::TotalInputTokens => "0 in",            StatusSurfacePreviewItem::TotalOutputTokens => "0 out",            StatusSurfacePreviewItem::SessionId => "550e8400-e29b-41d4",            StatusSurfacePreviewItem::FastMode => "Fast on",            StatusSurfacePreviewItem::RawOutput => "raw output",            StatusSurfacePreviewItem::Model => "gpt-5.2-codex",            StatusSurfacePreviewItem::ModelWithReasoning => "gpt-5.2-codex medium",            StatusSurfacePreviewItem::Reasoning => "medium",            StatusSurfacePreviewItem::TaskProgress => "Tasks 0/0",        }    }    pub(crate) fn iter() -> impl Iterator<Item = Self> {        [            Self::AppName,            Self::ProjectName,            Self::ProjectRoot,            Self::CurrentDir,            Self::Status,            Self::ThreadTitle,            Self::GitBranch,            Self::PullRequestNumber,            Self::BranchChanges,            Self::Permissions,            Self::ApprovalMode,            Self::ContextRemaining,            Self::ContextUsed,            Self::FiveHourLimit,            Self::WeeklyLimit,            Self::CodexVersion,            Self::ContextWindowSize,            Self::UsedTokens,            Self::TotalInputTokens,            Self::TotalOutputTokens,            Self::SessionId,            Self::FastMode,            Self::RawOutput,            Self::Model,            Self::ModelWithReasoning,            Self::Reasoning,            Self::TaskProgress,        ]        .into_iter()    }}#[derive(Clone, Debug, Eq, PartialEq)]struct PreviewValue {    text: String,    is_placeholder: bool,}#[derive(Clone, Debug, Eq, PartialEq)]pub(crate) struct StatusSurfacePreviewData {    values: BTreeMap<StatusSurfacePreviewItem, PreviewValue>,}impl Default for StatusSurfacePreviewData {    fn default() -> Self {        let mut data = Self {            values: BTreeMap::new(),        };        for item in StatusSurfacePreviewItem::iter() {            data.set_placeholder(item, item.placeholder());        }        data    }}impl StatusSurfacePreviewData {    pub(crate) fn from_iter<I, V>(values: I) -> Self    where        I: IntoIterator<Item = (StatusSurfacePreviewItem, V)>,        V: Into<String>,    {        let mut data = Self::default();        for (item, value) in values {            data.set_live(item, value);        }        data    }    pub(crate) fn set_live<V>(&mut self, item: StatusSurfacePreviewItem, value: V)    where        V: Into<String>,    {        self.values.insert(            item,            PreviewValue {                text: value.into(),                is_placeholder: false,            },        );    }    pub(crate) fn set_placeholder<V>(&mut self, item: StatusSurfacePreviewItem, value: V)    where        V: Into<String>,    {        if self            .values            .get(&item)            .is_some_and(|value| !value.is_placeholder)        {            return;        }        self.values.insert(            item,            PreviewValue {                text: value.into(),                is_placeholder: true,            },        );    }    pub(crate) fn suppress_placeholder(&mut self, item: StatusSurfacePreviewItem) {        if self            .values            .get(&item)            .is_some_and(|value| value.is_placeholder)        {            self.values.remove(&item);        }    }    pub(crate) fn rate_limit_item_name(        &self,        item: StatusSurfacePreviewItem,        fallback: &str,    ) -> String {        self.live_value_for(item)            .and_then(rate_limit_preview_copy)            .map(|copy| copy.name.to_string())            .unwrap_or_else(|| fallback.to_string())    }    pub(crate) fn rate_limit_item_description(        &self,        item: StatusSurfacePreviewItem,        fallback: &str,    ) -> String {        self.live_value_for(item)            .and_then(rate_limit_preview_copy)            .map(|copy| copy.description.to_string())            .unwrap_or_else(|| fallback.to_string())    }    pub(crate) fn value_for(&self, item: StatusSurfacePreviewItem) -> Option<&str> {        self.values.get(&item).map(|value| value.text.as_str())    }    fn live_value_for(&self, item: StatusSurfacePreviewItem) -> Option<&str> {        self.values            .get(&item)            .filter(|value| !value.is_placeholder)            .map(|value| value.text.as_str())    }    pub(crate) fn status_line_for_items<I>(        &self,        items: I,        use_theme_colors: bool,    ) -> Option<Line<'static>>    where        I: IntoIterator<Item = StatusLineItem>,    {        let segments = items.into_iter().filter_map(|item| {            self.value_for(item.preview_item())                .map(|value| (item, value.to_string()))        });        status_line_from_segments(segments, use_theme_colors)    }}struct RateLimitPreviewCopy {    name: &'static str,    description: &'static str,}fn rate_limit_preview_copy(value: &str) -> Option<RateLimitPreviewCopy> {    let value = value.trim_start();    if value.starts_with("secondary usage ") {        Some(RateLimitPreviewCopy {            name: "secondary-usage-limit",            description: "Remaining usage on the secondary usage limit (omitted when unavailable)",        })    } else if value.starts_with("usage ") {        Some(RateLimitPreviewCopy {            name: "usage-limit",            description: "Remaining usage on the primary usage limit (omitted when unavailable)",        })    } else if value.starts_with("5h ") {        Some(RateLimitPreviewCopy {            name: "five-hour-limit",            description: "Remaining usage on the 5-hour usage limit (omitted when unavailable)",        })    } else if value.starts_with("daily ") {        Some(RateLimitPreviewCopy {            name: "daily-limit",            description: "Remaining usage on the daily usage limit (omitted when unavailable)",        })    } else if value.starts_with("weekly ") {        Some(RateLimitPreviewCopy {            name: "weekly-limit",            description: "Remaining usage on the weekly usage limit (omitted when unavailable)",        })    } else if value.starts_with("monthly ") {        Some(RateLimitPreviewCopy {            name: "monthly-limit",            description: "Remaining usage on the monthly usage limit (omitted when unavailable)",        })    } else if value.starts_with("annual ") {        Some(RateLimitPreviewCopy {            name: "annual-limit",            description: "Remaining usage on the annual usage limit (omitted when unavailable)",        })    } else {        None    }}