fix(tui): scroll transcript when composer is empty, not history

Restore pre-#1117 behaviour where plain Up/Down scroll the transcript
when the composer is empty.  Terminals that map trackpad gestures to
arrow keys rely on this to scroll the history area.

When the composer has text, Up/Down still navigate input history.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
lbcheng
2026-05-08 22:33:59 +08:00
parent f183501fbd
commit f0de2b2de8
2 changed files with 35 additions and 5 deletions
+16 -2
View File
@@ -3513,13 +3513,27 @@ fn handle_composer_history_arrow(
return false;
}
// When the composer is empty, plain Up/Down scroll the transcript so
// terminals that map trackpad gestures to arrow keys can still scroll
// the history area. When the composer has text, they navigate input
// history so the user can recall previous prompts.
let composer_empty = app.input.trim().is_empty();
match key.code {
KeyCode::Up => {
app.history_up();
if composer_empty {
app.scroll_up(1);
} else {
app.history_up();
}
true
}
KeyCode::Down => {
app.history_down();
if composer_empty {
app.scroll_down(1);
} else {
app.history_down();
}
true
}
_ => false,
+19 -3
View File
@@ -3925,14 +3925,28 @@ fn history_arrow_handles_empty_input() {
let mut app = create_test_app();
app.input_history.push("previous prompt".to_string());
// Empty composer: Up scrolls the transcript, not navigates history.
assert!(handle_composer_history_arrow(
&mut app,
KeyEvent::new(KeyCode::Up, KeyModifiers::NONE),
false,
false,
));
assert_eq!(app.viewport.pending_scroll_delta, -1, "empty composer Up should scroll up");
assert!(app.input.is_empty(), "input should stay empty, not load history");
}
assert_eq!(app.input, "previous prompt");
#[test]
fn history_arrow_handles_empty_input_down() {
let mut app = create_test_app();
// Empty composer: Down scrolls the transcript.
assert!(handle_composer_history_arrow(
&mut app,
KeyEvent::new(KeyCode::Down, KeyModifiers::NONE),
false,
false,
));
assert_eq!(app.viewport.pending_scroll_delta, 1, "empty composer Down should scroll down");
}
#[test]
@@ -3942,14 +3956,15 @@ fn history_arrow_handles_whitespace_input() {
app.cursor_position = app.input.chars().count();
app.input_history.push("previous prompt".to_string());
// Whitespace-only composer: Up scrolls transcript.
assert!(handle_composer_history_arrow(
&mut app,
KeyEvent::new(KeyCode::Up, KeyModifiers::NONE),
false,
false,
));
assert_eq!(app.input, "previous prompt");
assert_eq!(app.viewport.pending_scroll_delta, -1);
assert_eq!(app.input, " ", "whitespace-only input should stay unchanged");
}
#[test]
@@ -3959,6 +3974,7 @@ fn history_arrow_handles_nonempty_input() {
app.cursor_position = app.input.chars().count();
app.input_history.push("previous prompt".to_string());
// Non-empty composer: Up navigates input history.
assert!(handle_composer_history_arrow(
&mut app,
KeyEvent::new(KeyCode::Up, KeyModifiers::NONE),