From f562301aa2bf08254479ef1ddfbe5de5f49ee07b Mon Sep 17 00:00:00 2001 From: Dhanji Prasanna Date: Sat, 4 Oct 2025 13:30:11 +1000 Subject: [PATCH] tweaks to newline --- crates/g3-cli/src/lib.rs | 3 -- crates/g3-cli/src/retro_tui.rs | 80 ++++++++++++++--------------- crates/g3-cli/src/ui_writer_impl.rs | 2 +- crates/g3-core/src/lib.rs | 2 +- 4 files changed, 42 insertions(+), 45 deletions(-) diff --git a/crates/g3-cli/src/lib.rs b/crates/g3-cli/src/lib.rs index 2591ff9..256bf26 100644 --- a/crates/g3-cli/src/lib.rs +++ b/crates/g3-cli/src/lib.rs @@ -208,9 +208,6 @@ async fn run_interactive_retro(config: Config, show_prompt: bool, show_code: boo } } - tui.output(""); - tui.output(""); - // Track multiline input let mut multiline_buffer = String::new(); let mut in_multiline = false; diff --git a/crates/g3-cli/src/retro_tui.rs b/crates/g3-cli/src/retro_tui.rs index be19cc0..bf5033c 100644 --- a/crates/g3-cli/src/retro_tui.rs +++ b/crates/g3-cli/src/retro_tui.rs @@ -179,15 +179,18 @@ impl TerminalState { corner_br )); self.output_history.push(String::new()); // Empty line after box - // Auto-scroll to bottom only if user hasn't manually scrolled + + // Auto-scroll to bottom only if user hasn't manually scrolled if !self.manual_scroll { let total_lines = self.output_history.len(); let visible_height = self.last_visible_height.max(1); - self.scroll_offset = if total_lines > visible_height { - total_lines.saturating_sub(visible_height) + + // Calculate scroll to show the last visible_height lines + if total_lines > visible_height { + self.scroll_offset = total_lines.saturating_sub(visible_height); } else { - 0 - }; + self.scroll_offset = 0; + } } } @@ -231,11 +234,13 @@ impl TerminalState { if !self.manual_scroll { let total_lines = self.output_history.len(); let visible_height = self.last_visible_height.max(1); - self.scroll_offset = if total_lines > visible_height { - total_lines.saturating_sub(visible_height) + + // Calculate scroll to show the last visible_height lines + if total_lines > visible_height { + self.scroll_offset = total_lines.saturating_sub(visible_height); } else { - 0 - }; + self.scroll_offset = 0; + } } } @@ -461,18 +466,21 @@ impl RetroTui { let visible_height = area.height.saturating_sub(2) as usize; // Account for borders let total_lines = output_history.len(); - // Calculate the maximum valid scroll position to ensure we can see all lines - // The max scroll should allow us to position the viewport such that the last line is visible - let max_scroll = total_lines.saturating_sub(1); - - // Ensure scroll offset is within valid range - // Clamp the scroll offset but ensure we can still see content at the bottom - let scroll = if scroll_offset + visible_height > total_lines && total_lines > visible_height - { - // Adjust scroll to show the last visible_height lines - total_lines.saturating_sub(visible_height) + // Calculate the proper scroll position + let scroll = if total_lines <= visible_height { + // If all content fits, no scrolling needed + 0 } else { - scroll_offset.min(max_scroll) + // Ensure scroll offset doesn't leave empty space at the bottom + // The maximum scroll position should be such that the last line is at the bottom of the viewport + let max_scroll = total_lines.saturating_sub(visible_height); + + // If the requested scroll would show past the end, adjust it + if scroll_offset > max_scroll { + max_scroll + } else { + scroll_offset + } }; // Get visible lines @@ -721,12 +729,10 @@ impl RetroTui { let total_lines = state.output_history.len(); let visible_height = state.last_visible_height.max(1); - // Calculate max scroll position - should position viewport to show last lines - let max_scroll = if total_lines > visible_height { - total_lines.saturating_sub(visible_height) - } else { - 0 - }; + // Calculate max scroll position + // Ensure we can scroll to see all content + let max_scroll = total_lines.saturating_sub(visible_height); + state.scroll_offset = (state.scroll_offset + 1).min(max_scroll); } } @@ -753,20 +759,16 @@ impl RetroTui { if let Ok(mut state) = self.state.lock() { state.manual_scroll = true; let total_lines = state.output_history.len(); - // Use the last known visible height, or a reasonable default + let visible_height = state.last_visible_height.max(1); + let page_size = if state.last_visible_height > 0 { state.last_visible_height.saturating_sub(2) // Leave a couple lines for context } else { 15 // Reasonable default }; - // Calculate max scroll position - should position viewport to show last lines - let visible_height = state.last_visible_height.max(1); - let max_scroll = if total_lines > visible_height { - total_lines.saturating_sub(visible_height) - } else { - 0 - }; + // Calculate max scroll position + let max_scroll = total_lines.saturating_sub(visible_height); // Scroll down by a page, but don't go past the end state.scroll_offset = (state.scroll_offset + page_size).min(max_scroll); @@ -783,12 +785,10 @@ impl RetroTui { if let Ok(mut state) = self.state.lock() { let total_lines = state.output_history.len(); let visible_height = state.last_visible_height.max(1); - // Scroll to show the last page of content - position viewport at the bottom - state.scroll_offset = if total_lines > visible_height { - total_lines.saturating_sub(visible_height) - } else { - 0 - }; + + // Scroll to show the last page of content + state.scroll_offset = total_lines.saturating_sub(visible_height); + // When scrolling to end, disable manual scroll so auto-scroll resumes state.manual_scroll = false; } diff --git a/crates/g3-cli/src/ui_writer_impl.rs b/crates/g3-cli/src/ui_writer_impl.rs index 71c7c57..bd3720d 100644 --- a/crates/g3-cli/src/ui_writer_impl.rs +++ b/crates/g3-cli/src/ui_writer_impl.rs @@ -185,7 +185,7 @@ impl UiWriter for RetroTuiWriter { } fn print_agent_prompt(&self) { - self.tui.output("šŸ’¬ "); + self.tui.output("\nšŸ’¬ "); } fn print_agent_response(&self, content: &str) { diff --git a/crates/g3-core/src/lib.rs b/crates/g3-core/src/lib.rs index d986f5c..23ffcec 100644 --- a/crates/g3-core/src/lib.rs +++ b/crates/g3-core/src/lib.rs @@ -2219,7 +2219,7 @@ fn filter_json_tool_calls(content: &str) -> String { } // Check if this looks like the start of a JSON tool call (larger chunks) - let pattern = Regex::new(r#"\{\s*"tool"\s*:"#).unwrap(); + let pattern = Regex::new(r#"\s*\{\s*"tool"\s*:"#).unwrap(); if pattern.is_match(trimmed) { // This might be the start of a JSON tool call // Enter suppression mode preemptively