mirror of
https://github.com/openai/codex.git
synced 2026-11-10 21:00:47 +00:00
## Why The TUI app module had grown past the 512K source-file cap enforced by CI/CD. This keeps the app entry point below that limit while preserving the existing runtime behavior and test surface. ## What changed - Kept the top-level `App` state and run-loop wiring in `tui/src/app.rs`. - Split app responsibilities into focused private submodules under `tui/src/app/`, covering event dispatch, thread routing, session lifecycle, config persistence, background requests, startup prompts, input, history UI, platform actions, and thread event buffering. - Moved the existing app-level tests into `tui/src/app/tests.rs` and reused the existing snapshot location rather than adding new tests or snapshots. - Added module header comments for `app.rs` and the new submodules. ## Follow-up A future cleanup can move narrow unit tests from `tui/src/app/tests.rs` into the specific app submodules they exercise. This PR keeps the existing app-level tests together so the refactor stays focused on the source-file split. ## Verification - `cargo test -p codex-tui --lib app::tests::agent_picker_item_name_snapshot` - `cargo test -p codex-tui --lib app::tests::clear_ui` - `cargo test -p codex-tui --lib app::tests::ctrl_l_clear_ui_after_long_transcript_reuses_clear_header_snapshot` - `just fix -p codex-tui` Full `cargo test -p codex-tui` still fails on model-catalog drift unrelated to this refactor, including stale `gpt-5.3-codex`/`gpt-5.1-codex` snapshot and migration expectations now resolving to `gpt-5.4`.
94 lines
3.3 KiB
Rust
94 lines
3.3 KiB
Rust
//! Terminal history and clear-screen UI helpers for the TUI app.
|
|
//!
|
|
//! This module owns rendering the fresh session header, clearing inline or alternate-screen UI
|
|
//! state, and resetting transcript-related app state after `/clear` or Ctrl-L.
|
|
|
|
use super::*;
|
|
|
|
impl App {
|
|
pub(super) fn open_url_in_browser(&mut self, url: String) {
|
|
if let Err(err) = webbrowser::open(&url) {
|
|
self.chat_widget
|
|
.add_error_message(format!("Failed to open browser for {url}: {err}"));
|
|
return;
|
|
}
|
|
|
|
self.chat_widget
|
|
.add_info_message(format!("Opened {url} in your browser."), /*hint*/ None);
|
|
}
|
|
|
|
pub(super) fn clear_ui_header_lines_with_version(
|
|
&self,
|
|
width: u16,
|
|
version: &'static str,
|
|
) -> Vec<Line<'static>> {
|
|
history_cell::SessionHeaderHistoryCell::new(
|
|
self.chat_widget.current_model().to_string(),
|
|
self.chat_widget.current_reasoning_effort(),
|
|
self.chat_widget.should_show_fast_status(
|
|
self.chat_widget.current_model(),
|
|
self.chat_widget.current_service_tier(),
|
|
),
|
|
self.config.cwd.to_path_buf(),
|
|
version,
|
|
)
|
|
.with_yolo_mode(history_cell::is_yolo_mode(&self.config))
|
|
.display_lines(width)
|
|
}
|
|
|
|
pub(super) fn clear_ui_header_lines(&self, width: u16) -> Vec<Line<'static>> {
|
|
self.clear_ui_header_lines_with_version(width, CODEX_CLI_VERSION)
|
|
}
|
|
|
|
pub(super) fn queue_clear_ui_header(&mut self, tui: &mut tui::Tui) {
|
|
let width = tui.terminal.last_known_screen_size.width;
|
|
let header_lines = self.clear_ui_header_lines(width);
|
|
if !header_lines.is_empty() {
|
|
tui.insert_history_lines(header_lines);
|
|
self.has_emitted_history_lines = true;
|
|
}
|
|
}
|
|
|
|
pub(super) fn clear_terminal_ui(
|
|
&mut self,
|
|
tui: &mut tui::Tui,
|
|
redraw_header: bool,
|
|
) -> Result<()> {
|
|
let is_alt_screen_active = tui.is_alt_screen_active();
|
|
|
|
// Drop queued history insertions so stale transcript lines cannot be flushed after /clear.
|
|
tui.clear_pending_history_lines();
|
|
|
|
if is_alt_screen_active {
|
|
tui.terminal.clear_visible_screen()?;
|
|
} else {
|
|
// Some terminals (Terminal.app, Warp) do not reliably drop scrollback when purge and
|
|
// clear are emitted as separate backend commands. Prefer a single ANSI sequence.
|
|
tui.terminal.clear_scrollback_and_visible_screen_ansi()?;
|
|
}
|
|
|
|
let mut area = tui.terminal.viewport_area;
|
|
if area.y > 0 {
|
|
// After a full clear, anchor the inline viewport at the top and redraw a fresh header
|
|
// box. `insert_history_lines()` will shift the viewport down by the rendered height.
|
|
area.y = 0;
|
|
tui.terminal.set_viewport_area(area);
|
|
}
|
|
self.has_emitted_history_lines = false;
|
|
|
|
if redraw_header {
|
|
self.queue_clear_ui_header(tui);
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
pub(super) fn reset_app_ui_state_after_clear(&mut self) {
|
|
self.overlay = None;
|
|
self.transcript_cells.clear();
|
|
self.deferred_history_lines.clear();
|
|
self.has_emitted_history_lines = false;
|
|
self.backtrack = BacktrackState::default();
|
|
self.backtrack_render_pending = false;
|
|
}
|
|
}
|