feat/multiline composer arrow navigation#1719
Conversation
… history Replace direct history_up()/history_down() calls with vim_move_up()/ vim_move_down() in handle_composer_history_arrow. These functions already implement the desired behaviour: move the cursor one logical line within the composer when the input is multiline (preserving column position), and fall back to input-history navigation only at the first or last line. Previously plain Up/Down always jumped to the previous/next history entry, making it impossible to edit the line above in a multi-line prompt without leaving the composer. Also rename composer_arrows_scroll_nonempty_still_navigates_history to composer_arrows_scroll_singleline_navigates_history and add two new tests covering multiline arrow navigation.
…scroll On terminals with mouse capture (Windows Terminal, most modern terminals), the composer_arrows_scroll default is now false: empty-composer Up/Down navigates input history instead of scrolling the transcript. Previously default_composer_arrows_scroll_for_platform returned is_windows || !use_mouse_capture, forcing true on all Windows machines. Now it returns only !use_mouse_capture, so: - Mouse capture ON -> default false -> Up/Down navigates history - Mouse capture OFF -> default true -> Up/Down scrolls transcript (for terminals that map mouse-wheel events to arrow keys, e.g. CMD.exe) Added 6 tests for the composer arrow + history navigation matrix: - Empty composer Down restores draft (arrows-scroll=false) - Down walks forward through multiple history entries - Up at first line of multiline input falls back to history_up - Down at last line of multiline input falls back to history_down - Up-then-Down round-trip restores draft with cursor position
There was a problem hiding this comment.
Code Review
This pull request updates the TUI composer's arrow key behavior to support multiline navigation and standardizes the composer_arrows_scroll default across platforms. Specifically, it replaces direct history navigation with vim_move_up and vim_move_down, allowing users to move between lines within the composer before falling back to history. Feedback was provided to refine the scroll_on_empty heuristic, as the current implementation using trim().is_empty() would incorrectly trigger transcript scrolling for whitespace-only multiline inputs instead of allowing line navigation.
…tespace
Replace `trim().is_empty()` with a check that treats multiline inputs
(those containing '\n') as non-empty, even when whitespace-only.
Before: `" \n ".trim()` → `""` → scroll_on_empty = true → scrolls
After: `" \n ".contains('\n')` → true → scroll_on_empty = false → line nav
Single-line whitespace (`" "`) is still treated as empty, preserving
the existing behavior tested in history_arrow_handles_whitespace_input.
|
Good catch — Fixed in b0c7acd: the heuristic now only treats the composer as "empty" when it's truly empty or contains only single-line whitespace. If let scroll_on_empty = app.composer_arrows_scroll
&& (app.input.is_empty()
|| (!app.input.contains('\n') && app.input.trim().is_empty()));Added a test ( |
|
Thanks for the detailed composer work. The multiline arrow-navigation fix and useful tests were harvested into v0.8.39 via #1734 and credited in the changelog, so I am closing this PR to keep the queue clean. The broader empty-composer Windows default remains open as #1720 under v0.8.40, where we want a full Windows terminal/mouse-capture matrix before changing defaults again. |
See #1720
See #1721
Problem
Issue 1 (#1720): On Windows, pressing Up on an empty composer scrolled the transcript instead of navigating to the previous submitted message. Typing even one character and pressing Up correctly navigated history — but an empty composer did something completely different.
Issue 2 (#1721): In a multiline composer, Up/Down should navigate within the input text (moving cursor between lines), not immediately jump to input history.
Fix
Changed
default_composer_arrows_scroll_for_platformto return!use_mouse_captureonly (removedis_windows ||):false→ Up/Down navigates historytrue→ scrolls transcript (mouse-wheel fallback)The multiline cursor navigation (
vim_move_up/vim_move_down) was already working correctly — the second fix ensures the boundary fallback to history only happens at the first/last line.Changes
crates/tui/src/tui/app.rsis_windows ||from default; updated field doc comment; renamed testcrates/tui/src/tui/ui/tests.rsNew tests (6)
history_arrow_down_handles_empty_inputhistory_arrow_down_walks_forward_through_entriescomposer_arrow_up_at_first_line_falls_back_to_history_uphistory_up()composer_arrow_down_at_last_line_falls_back_to_history_downhistory_down()history_roundtrip_up_then_down_restores_draftRelated
composer_arrows_scrollintroduced in fix(tui): scroll transcript when composer is empty, not history #1211