client-core: read an uppercase ASCII letter in a chord as the letter plus Shift #443

Merged
natsukium merged 4 commits from client-core/uppercase-letter-chords into main 2026-09-25 12:33:12 +09:00
Owner

A keymap chord written with an uppercase ASCII letter (shift+A) parsed without a warning but could never match: the client lifts every uppercase keypress to the lowercase letter plus Shift, while the parser kept A as written. Per the decision on the issue (option 1), the parser now folds the same way.

  • Chord::from_str reads a single uppercase ASCII letter as its lowercase letter plus SHIFT: A, shift+A and shift+a are one chord. Unit tests and a proptest pin the fold.
  • felis sessions send --key parses with the same grammar, so its key event now sends Shift plus a letter as the uppercase keystroke with that letter composed, as a keyboard (and the GUI) does. --key A keeps typing A, and --key shift+a now types A instead of a.
  • docs/reference/keybindings.md chord grammar states the fold; CHANGELOG "Fixed" entries for the keymap and the CLI.

Closes #386

A keymap chord written with an uppercase ASCII letter (`shift+A`) parsed without a warning but could never match: the client lifts every uppercase keypress to the lowercase letter plus Shift, while the parser kept `A` as written. Per the decision on the issue (option 1), the parser now folds the same way. - `Chord::from_str` reads a single uppercase ASCII letter as its lowercase letter plus SHIFT: `A`, `shift+A` and `shift+a` are one chord. Unit tests and a proptest pin the fold. - `felis sessions send --key` parses with the same grammar, so its key event now sends Shift plus a letter as the uppercase keystroke with that letter composed, as a keyboard (and the GUI) does. `--key A` keeps typing `A`, and `--key shift+a` now types `A` instead of `a`. - `docs/reference/keybindings.md` chord grammar states the fold; CHANGELOG "Fixed" entries for the keymap and the CLI. Closes #386
The client lifts every uppercase ASCII keypress to its lowercase letter
plus SHIFT before the keymap lookup, but the chord parser stored `A` as
written, so a binding such as `shift+A` loaded without a warning and
could never match. Folding in the parser puts the written and the
pressed chord under one rule, and configs that already parse start
firing. Rejecting the spelling with a diagnostic was the alternative;
it would break configs that load today for a spelling whose meaning is
unambiguous.

`A`, `shift+A` and `shift+a` are now three spellings of one chord, so
the existing rule for two spellings in one section (the later-sorting
string wins) covers them.

Assisted-by: Claude Code
`felis sessions send --key` parses its chord with the keymap grammar,
which now reads `A` as `shift+a`. Building the key event from the
folded chord sent `a` as the key and the composed text, so `--key A`
typed a lowercase letter where it used to type `A`, and `shift+a` never
typed `A` at all. A keyboard reports Shift plus a letter as the
uppercase letter with that letter composed, which is what the GUI
forwards, so the CLI now does the same and the daemon encodes both
identically.

Assisted-by: Claude Code
cli: record the shifted-letter --key fix in the changelog
Some checks failed
windows / detect relevant changes (pull_request) Successful in 32s
windows / windows docs-only no-op (pull_request) Has been skipped
pr / nix flake check (pull_request) Has been cancelled
pr / cargo build / clippy / test / deny (pull_request) Has been cancelled
bench / Criterion regression gate (pull_request) Has been cancelled
fuzz / cargo fuzz smoke (per target) (pull_request) Has been cancelled
pr / wire schema is compatible with the base (pull_request) Has been cancelled
pr / frontend smoke (x86_64-linux) (pull_request) Has been cancelled
pr / publish felis (x86_64-linux) (pull_request) Has been cancelled
bench / Criterion full-suite snapshot (pull_request) Has been skipped
fuzz / cargo fuzz nightly long-run (pull_request) Has been skipped
darwin / detect relevant changes (pull_request) Successful in 14s
darwin / darwin docs-only no-op (pull_request) Has been skipped
windows / cargo clippy (Windows cross) (pull_request) Has been cancelled
windows / cargo nextest (Windows) (pull_request) Has been cancelled
windows / frontend smoke (Windows) (pull_request) Has been cancelled
windows / package felis (x86_64-pc-windows-msvc) (pull_request) Has been cancelled
darwin / build felis (aarch64-darwin) (pull_request) Successful in 54s
darwin / publish felis (aarch64-darwin) (pull_request) Has been skipped
0c3dbace1b
The CLI now sends Shift plus a letter as the uppercase keystroke, which changes what `sessions send --key shift+a` types; that is user-visible CLI behavior, so it gets a Fixed entry.

Assisted-by: Claude Code
Merge remote-tracking branch 'origin/main' into client-core/uppercase-letter-chords
Some checks failed
darwin / build felis (aarch64-darwin) (pull_request) Successful in 53s
darwin / publish felis (aarch64-darwin) (pull_request) Has been skipped
bench / Criterion regression gate (pull_request) Has been cancelled
pr / nix flake check (pull_request) Has been cancelled
pr / cargo build / clippy / test / deny (pull_request) Has been cancelled
pr / wire schema is compatible with the base (pull_request) Has been cancelled
pr / frontend smoke (x86_64-linux) (pull_request) Has been cancelled
pr / publish felis (x86_64-linux) (pull_request) Has been cancelled
bench / Criterion full-suite snapshot (pull_request) Has been skipped
fuzz / cargo fuzz nightly long-run (pull_request) Has been skipped
darwin / detect relevant changes (pull_request) Successful in 14s
darwin / darwin docs-only no-op (pull_request) Has been skipped
windows / detect relevant changes (pull_request) Successful in 27s
windows / windows docs-only no-op (pull_request) Has been skipped
windows / cargo clippy (Windows cross) (pull_request) Has been cancelled
windows / cargo nextest (Windows) (pull_request) Has been cancelled
windows / frontend smoke (Windows) (pull_request) Has been cancelled
windows / package felis (x86_64-pc-windows-msvc) (pull_request) Has been cancelled
fuzz / cargo fuzz smoke (per target) (pull_request) Has been cancelled
6902bc0cf4
# Conflicts:
#	CHANGELOG.md
natsukium deleted branch client-core/uppercase-letter-chords 2026-09-25 12:33:12 +09:00
Commenting is not possible because the repository is archived.
No description provided.