From 1b0d237de688d5e9f85ad2140e49ce1b737c8590 Mon Sep 17 00:00:00 2001 From: TheArchitectit Date: Mon, 15 Jun 2026 08:55:19 -0500 Subject: [PATCH] fix(tui): input stays in box during/after turn - mark input bar turn-in-progress on submit - re-enable input after turn resumes - clear input area before redraw - clear completion popup before redraw - resume re-enters alternate screen and clears cleanly This prevents typed text from overwriting itself and stops redraws from spilling word-wrapped text outside the input box. --- rust/crates/rusty-claude-cli/src/main.rs | 1 + rust/crates/rusty-claude-cli/src/tui/app.rs | 13 +++++++++++-- .../src/tui/components/input_bar.rs | 13 ++++--------- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/rust/crates/rusty-claude-cli/src/main.rs b/rust/crates/rusty-claude-cli/src/main.rs index 77fd3223..5287ca1e 100644 --- a/rust/crates/rusty-claude-cli/src/main.rs +++ b/rust/crates/rusty-claude-cli/src/main.rs @@ -7301,6 +7301,7 @@ fn run_tui_repl(mut cli: LiveCli) -> Result<(), Box> { let result = cli.run_turn_to(&trimmed, &mut buf, false); drop(stdout); app.resume()?; + app.set_turn_in_progress(false); { let messages = &cli.runtime.session().messages; diff --git a/rust/crates/rusty-claude-cli/src/tui/app.rs b/rust/crates/rusty-claude-cli/src/tui/app.rs index bc40481d..b972ff46 100644 --- a/rust/crates/rusty-claude-cli/src/tui/app.rs +++ b/rust/crates/rusty-claude-cli/src/tui/app.rs @@ -107,10 +107,14 @@ impl TuiApp { /// Resume TUI after suspend. pub fn resume(&mut self) -> Result<(), Box> { + crossterm::execute!( + io::stdout(), + crossterm::terminal::EnterAlternateScreen, + Clear(ClearType::All), + crossterm::cursor::Hide + )?; enable_raw_mode()?; - let _ = crossterm::execute!(io::stdout(), Clear(ClearType::All), crossterm::cursor::MoveTo(0, 0)); let _ = io::stdout().flush(); - self.terminal.hide_cursor()?; self.terminal.clear()?; Ok(()) } @@ -226,6 +230,10 @@ impl TuiApp { self.keymap.set_preset(preset); } + pub fn set_turn_in_progress(&mut self, in_progress: bool) { + self.input_bar.set_turn_in_progress(in_progress); + } + pub fn key_preset_name(&self) -> &'static str { match self.keymap.preset() { KeyPreset::Emacs => "Emacs", @@ -284,6 +292,7 @@ impl TuiApp { match outcome { InputOutcome::Submit(text) => { self.input_bar.push_history(&text); + self.set_turn_in_progress(true); Ok(TuiReadOutcome::Submit(text)) } InputOutcome::Cancel => Ok(TuiReadOutcome::Cancel), diff --git a/rust/crates/rusty-claude-cli/src/tui/components/input_bar.rs b/rust/crates/rusty-claude-cli/src/tui/components/input_bar.rs index 18f5c019..6ca82037 100644 --- a/rust/crates/rusty-claude-cli/src/tui/components/input_bar.rs +++ b/rust/crates/rusty-claude-cli/src/tui/components/input_bar.rs @@ -105,6 +105,7 @@ impl InputBar { pub fn set_turn_in_progress(&mut self, in_progress: bool) { self.turn_in_progress = in_progress; + self.dirty = true; } /// Push text to history. @@ -293,23 +294,17 @@ impl InputBar { width: area.width.min(40), height: (matches.len() as u16 + 2).min(10), }; + frame.render_widget(ratatui::widgets::Clear, popup); frame.render_widget(list, popup); } } impl Component for InputBar { fn render(&self, area: Rect, frame: &mut Frame, theme: &TuiTheme) { + frame.render_widget(ratatui::widgets::Clear, area); let widget = self.textarea.clone(); frame.render_widget(&widget, area); - - // Render completions popup above the input area - if self.showing_completions { - // Note: can't call self.render_completions() from &self here - // because we need mutable access to check state but render is &self. - // Workaround: render completions in the draw_frame function directly. - // This is acceptable for Phase 1 — will be refined later. - let _ = (area, frame, theme); - } + self.render_completions(area, frame, theme); } fn is_dirty(&self) -> bool {