fix(input): match Shift+letter bindings when terminal omits SHIFT modifier#2001
Open
sinelaw wants to merge 1 commit into
Open
fix(input): match Shift+letter bindings when terminal omits SHIFT modifier#2001sinelaw wants to merge 1 commit into
sinelaw wants to merge 1 commit into
Conversation
…ifier
Without kitty keyboard protocol, terminals typically encode Shift+letter
by sending the uppercase character alone — no SHIFT modifier accompanies
it. The previous normalization lowercased the char but kept the empty
modifier set, so a binding stored as `(Char('p'), SHIFT)` never matched
the incoming `(Char('P'), NONE)` event. As reported in #1899, this made
Shift+letter shortcuts only fire while Caps Lock was on (which causes
some terminals to invert the case and re-introduce the SHIFT modifier).
When an uppercase letter arrives with no other modifiers, infer SHIFT
during normalization. Leave the existing CapsLock+Ctrl+letter path alone
(uppercase + CONTROL) so it continues to fold to Ctrl+letter as before.
The same fix is applied to the keybinding editor recording paths — the
"Add binding" dialog and the record-key search — so that pressing
Shift+P in a non-kitty terminal saves a `Shift+P` binding rather than a
plain `p` one.
https://claude.ai/code/session_01H6FpwGdLrCA7zquAbVrhX9
Owner
Author
|
In my terminal (xfce terminal) when enabling caps lock the editor receives only modifier "shift", i.e. "shift"+"A" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #1899.
Without kitty keyboard protocol, terminals typically encode
Shift+letterby sending the uppercase character alone — noSHIFTmodifier accompanies it. The previousnormalize_keylowercased the char but kept the empty modifier set, so a binding stored as(Char('p'), SHIFT)never matched the incoming(Char('P'), NONE)event.As reported in #1899, this made
Shift+lettershortcuts only fire while Caps Lock was on (which causes some terminals to invert the case and re-introduce theSHIFTmodifier on lowercase letters). The same root cause meant the keybinding editor's add-binding dialog capturedShift+Pas plainp, losing the shift information at save time.Approach
normalize_keynow infersSHIFTwhen an uppercase letter arrives with no other modifiers. TheCapsLock+Ctrl+letter→Ctrl+lettercollapse is preserved (uppercase +CONTROLis intentionally not given aSHIFTbecause that case is ambiguous between caps lock and a real shift, and the existing behavior is to fold caps lock away).view/keybinding_editor.rs) and the record-key search (app/keybinding_editor/editor.rs) route the recorded event throughnormalize_keyso they captureShift+Pconsistently — no matter whether the terminal reportedSHIFT.InsertCharis unaffected: it uses the original event, so typing capitalZin a buffer still insertsZ.Tests
test_shift_letter_binding_works_without_terminal_shift_modifier— the core regression:Char('P')with no modifier now matches aShift+Pbinding.test_capslock_ctrl_letter_still_matches_ctrl_letter_binding— guards the existing CapsLock+Ctrl+A → Ctrl+A behavior.test_uppercase_without_binding_falls_through_to_insert_char— confirms typing capital letters still inserts them when no binding exists.record_search_key_normalizes_uppercase_letter_to_shift— the record-key search captures theSHIFTmodifier even when the terminal omits it.add_dialog_records_shift_when_terminal_omits_shift_modifier/add_dialog_records_shift_when_terminal_includes_shift_modifier/add_dialog_preserves_ctrl_when_capturing_upper_letter— full end-to-end dialog drive: send the simulated event throughhandle_keybinding_editor_inputand assert the captured(key_code, modifiers).Full lib test suite: 2468 passed, 0 failed.
Manual validation
Reproduced and verified the fix end-to-end:
Shift+P → savebinding in~/.config/fresh/config.json.Xinitial content) infreshunder tmux.P. The status bar transitioned toSaved, the unsaved-changes marker[+]and the buffer's*cleared, and the file on disk reflects the new content.Test plan
cargo test -p fresh-editor --libcargo check --all-targetscargo check --all-targets --features guicargo fmt --checkShift+Ptriggerssavevia custom binding.https://claude.ai/code/session_01H6FpwGdLrCA7zquAbVrhX9
Generated by Claude Code