fix: handle held-key repeat in modal dispatch - #1972
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (4)
🚧 Files skipped from review as they are similar to previous changes (4)
📝 WalkthroughWalkthroughKey repeat handling now uses a mode-aware held-key map instead of a suppression set. Headless and runtime paths share modal repeat gating, while clipboard actions and input-source cleanup update the new state. Tests cover navigation, modal behavior, typing, detachment, and unrecorded repeats. ChangesMode-aware key repeat tracking
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant InputSource
participant App
participant Terminal
InputSource->>App: key press
App->>App: record HeldKeyRepeat
InputSource->>App: key repeat
App->>App: check modal_repeat_allowed and held state
App->>Terminal: forward terminal-owned repeat
InputSource->>App: key release
App->>App: clear held repeat state
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
Greptile SummaryRoutes held-key kitty-protocol Repeat events into modal handlers when the press was recorded in the same mode.
Confidence Score: 5/5Safe to merge; no remaining blocking failures were identified from prior threads or this follow-up pass. No blocking failure remains. Prior Greptile inline threads were not available in this environment, and the follow-up eligibility gate therefore admits no new comments; the held-key repeat routing and mode/exclusion guards are covered by the new tests.
|
| Filename | Overview |
|---|---|
| src/app/mod.rs | Introduces HeldKeyRepeat, modal_repeat_allowed, headless Repeat routing, and regression tests. |
| src/app/runtime.rs | Mirrors held-key Repeat routing for the monolithic input path. |
| src/app/input/clipboard.rs | Clipboard interception records HeldKeyRepeat::Blocked instead of a bare suppress set. |
| src/app/input/terminal.rs | Input-source detach clears held_key_repeats for that source. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
Press[KeyEventKind::Press] --> TermCheck{popup or Terminal?}
TermCheck -->|yes| Clear[held_key_repeats.remove]
TermCheck -->|no| Record[insert InMode current mode]
Clear --> HandlePress[handle_key / terminal path]
Record --> HandleModal[handle_key / non-terminal]
Repeat[KeyEventKind::Repeat] --> TermR{popup or Terminal?}
TermR -->|yes| Blocked{key in held_key_repeats?}
Blocked -->|yes| DropT[ignore]
Blocked -->|no| FwdT[forward to terminal]
TermR -->|no| ModalOK{modal_repeat_allowed and InMode matches?}
ModalOK -->|yes| HandleR[handle modal again]
ModalOK -->|no| DropM[ignore]
Release[KeyEventKind::Release] --> Cleared[held_key_repeats.remove]
Reviews (3): Last reviewed commit: "fix: handle held-key repeat in modal dis..." | Re-trigger Greptile
360ab51 to
9bb38db
Compare
9bb38db to
176ff61
Compare
Current behavior
Holding a key in any non-terminal mode acts once. Hold Down in the keybinds list or the navigator and the selection moves a single row. Hold Backspace in either search box and one character is deleted. Copy mode has the same problem (#1341, #1387).
Reproduces in Ghostty and Alacritty on macOS and Linux.
Cause
Herdr requests
REPORT_EVENT_TYPES, so kitty-protocol terminals report auto-repeat asKeyEventKind::Repeat. But theRepeatarm only reaches a pane or the terminal-mode handler. Nothing routes it into the modal dispatch, so every modal drops it.Introduced by 10b17a6, which correctly stopped repeats leaking into a pane after a held key changed the mode, but scoped the whole repeat path to terminal mode.
Fix
suppressed_repeat_keys: HashSet<_>held_key_repeats: HashMap<_, HeldKeyRepeat>(Blocked | InMode(Mode))separating the clipboard interception's deliberate block from a press having been handled in a modal.
Repeatgains a branch that dispatches to the modal handler when the recorded mode still equals the current one.Tests
Eleven new tests in
src/app/mod.rscovering both input paths, the mode guard, each exclusion, and input-source cleanup. All fail before the change and pass after. The existing repeat-suppression and clipboard Ctrl-C tests are unchanged.Also checked by hand against 0.7.5 does not move on the repeats, this branch does.
Checks
cargo fmt --check,cargo clippy --all-targets --locked -- -D warnings,just integration-assets-testandjust plugin-marketplace-testare clean.cargo nextest run --lockedis 3093/3097. The four failures areauto_detect_default_socket_path_from_config_dir,auto_detect_writes_client_and_server_logs_to_separate_files,no_session_writes_startup_logs_to_monolith_fileandserver_start_restores_legacy_session_through_api_identity. All four fail identically on an unmodified checkout of the same commit, and none of them send a key event.Note: Very cool app!