refactor(input): EventContext, dispatch split, bugfixes & test quality#84
Conversation
Implements docs/pr-plan/pr-08-input-main-infra.md (PR8). Bugs (with value-asserting tests): - dialogs: pass trimmed dest to resolve_user_path (extract/create archive) - menu: surface menu-bar width overflow (debug_log + saturate) not silent 0 - mouse: guard panel_bounds for tiny terminals (no impossible row range) - main: recover_terminal_state no longer reports a working terminal as a failure Refactor: - EventContext bundles loop state; collapses dispatch_event/dispatch_key_event (drops too_many_arguments), per-mode dispatch table, run_app split - handlers migrated to &mut EventContext; drop dead _viewer_state params - mouse/mode_dispatch/normal/dialogs/pickers/menu_actions/directory_tree: helper extraction, shared matchers, named constants, fewer hot-path clones - lib.rs: drop dead root re-exports (module-path public API surface) - input/mod.rs: pub(crate) Build: - Cargo.toml: [profile.release] lto + codegen-units=1, [profile.dev] opt-level=1 Tests: - value-asserting key/mouse outcomes, picker/history coverage, parameterized dialog cases, loader-exposing harness No behavior change beyond the listed fixes. Gate green: fmt, clippy -D warnings, 1225 tests, release build.
There was a problem hiding this comment.
Sorry @leszek3737, your pull request is larger than the review limit of 150000 diff characters
There was a problem hiding this comment.
Code Review
This pull request refactors the input handling layer by introducing an EventContext struct to consolidate long-lived, per-frame mutable state, simplifying parameter lists across various event dispatch and mode handlers. It also deduplicates archive dialog logic, optimizes string building to reduce allocations, cleans up public API exports, and updates the integration test suite to match the new signatures. Feedback on the changes suggests trimming the dialog input text to prevent accidental leading or trailing whitespace during input-based actions.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| @@ -318,77 +389,32 @@ fn handle_input_action( | |||
| terminal_height: u16, | |||
| ) { | |||
| let input = state.input.dialog_input.text().to_owned(); | |||
There was a problem hiding this comment.
Trimming the input here ensures that all input-based actions (such as creating directories, renaming files, filtering, and quick-cd) are protected against accidental leading or trailing whitespace. This is especially helpful when users copy-paste names or paths into the TUI dialogs, preventing the accidental creation of files or directories with trailing spaces which can be difficult to manage on some filesystems.
| let input = state.input.dialog_input.text().to_owned(); | |
| let input = state.input.dialog_input.text().trim().to_owned(); |
Greptile SummaryLarge input-layer refactor that introduces
Confidence Score: 4/5Safe to merge after fixing the archive dialog Left/Right dual-action regression; all four advertised bug fixes are correct, the EventContext refactor is well-structured, and the test suite is genuinely improved. The archive extract and create dialogs now respond to Left/Right by both toggling the OK/Cancel button focus and moving the text cursor in the destination path field. In the old code those keys returned early after toggling the button and never reached apply_dialog_text_edit. The change is unintentional (the PR description says no behaviour change beyond the listed fixes), and no test covers Left/Right navigation in archive dialogs, so the regression was invisible to the test suite. src/input/dialogs.rs — specifically the ArchiveNav::Continue return value for KeyCode::Left | KeyCode::Right in archive_dialog_nav Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[crossterm Event] --> B[dispatch_event]
B -->|Key| C[dispatch_key_event]
B -->|Mouse| D[dispatch_mouse_event]
B -->|Resize| E[ctx.term_size updated]
C --> F{ctx.state.mode}
F -->|Normal| G[handle_normal_mode]
F -->|Viewing| H[handle_viewer_mode]
F -->|Dialog| I[handle_dialog]
F -->|Menu| J[handle_menu_mode]
F -->|Search| K[handle_search_mode]
F -->|DirectoryTree| L[handle_directory_tree]
F -->|ListPicker| M[handle_list_picker]
F -->|CommandLine| N[handle_command_line]
D --> O[handle_mouse_event]
O -->|NormalKey| G
O -->|MenuAction| Q[run_selected_menu_action]
G -.->|ctx| S[(EventContext)]
I -.->|ctx| S
J -.->|ctx| S
Reviews (1): Last reviewed commit: "refactor(input): EventContext, dispatch ..." | Re-trigger Greptile |
| KeyCode::Left | KeyCode::Right => { | ||
| state.input.dialog_selection = if state.input.dialog_selection == 0 { | ||
| 1 | ||
| } else { | ||
| 0 | ||
| }; | ||
| return; | ||
| ArchiveNav::Continue | ||
| } |
There was a problem hiding this comment.
Left/Right keys in the archive extract/create dialogs now trigger two independent actions in sequence: archive_dialog_nav toggles dialog_selection (OK→Cancel or Cancel→OK) and returns ArchiveNav::Continue, then apply_dialog_text_edit also moves the text cursor one position left or right in the destination path field. In the old code both handle_archive_extract_dialog and handle_archive_create_dialog returned early on Left/Right, so the text cursor was never touched. The Continue variant's doc comment explicitly says "fall through to text edit", which makes the dual-action behaviour look intentional, but it produces confusing UX and contradicts the PR description's "No behaviour change beyond the listed fixes".
| KeyCode::Left | KeyCode::Right => { | |
| state.input.dialog_selection = if state.input.dialog_selection == 0 { | |
| 1 | |
| } else { | |
| 0 | |
| }; | |
| return; | |
| ArchiveNav::Continue | |
| } | |
| KeyCode::Left | KeyCode::Right => { | |
| state.input.dialog_selection = if state.input.dialog_selection == 0 { | |
| 1 | |
| } else { | |
| 0 | |
| }; | |
| ArchiveNav::Handled | |
| } |
PR Review: refactor(input): EventContext, dispatch split, bugfixes & test qualityValidation
Overall AssessmentHigh-quality refactor. Approve with minor comments. The Strengths
Issues / Suggestions1. PR description oversells the test coverage of bug fixes — mediumThe body claims "Bugs (with value-asserting tests)" but the specific bugs aren't directly tested:
The new value-asserting tests ( 2. Verbose reborrow in
|
…t-action paths From external code review: - archive dialogs: Left/Right toggled OK/Cancel AND moved the dest-path text cursor — a regression from the PR8 extract/create handler merge (the old handlers returned early on Left/Right). Add ArchiveNav::Handled so the toggle no longer falls through to apply_dialog_text_edit. - handle_input_action: trim create-directory/rename/chmod/filter/quick-cd input so pasted leading/trailing whitespace no longer creates badly-named entries. Viewer search and find-file keep raw input (spaces are significant there, e.g. searching indented text). Regression tests added for both. Gate green: fmt, clippy -D warnings, 1227 tests, release build.
ratatui-widgets 0.3.1 added a non-Sync Shadow (Arc<dyn CellEffect>) to Block, so Paragraph is no longer Sync and `static CELLS: OnceLock<[Paragraph; 10]>` failed to compile (E0277) on any non --locked build. Rendering is single-threaded, so move the once-built cell cache into a thread_local!, which does not require Sync. Builds against both ratatui-widgets 0.3.0 and 0.3.1; render behavior unchanged.
PR Review: refactor(input): EventContext, dispatch split, bugfixes & test qualityValidation
Overall AssessmentApprove. High-quality refactor with all gates green. The PR has already incorporated fixes for the issues raised by earlier reviewers (Greptile's P1 archive Left/Right regression and Gemini's trim suggestion were both addressed in follow-up commit Strengths
Issues / Suggestions1. Missing regression test for archive-dialog trim fix — mediumThe PR description claims "Bugs (with value-asserting tests)" but only 2. Verbose reborrow in
|


Implements docs/pr-plan/pr-08-input-main-infra.md (PR8).
Bugs (with value-asserting tests):
Refactor:
Build:
Tests:
No behavior change beyond the listed fixes. Gate green: fmt, clippy -D warnings, 1225 tests, release build.