Skip to content

CPLAT-12440: keep the pre-rebind shortcut keys working as aliases - #169

Merged
gavin-jeong merged 1 commit into
masterfrom
CPLAT-12440-restore-legacy-key-aliases
Sep 29, 2026
Merged

gavin-jeong merged 1 commit into
masterfrom
CPLAT-12440-restore-legacy-key-aliases

Conversation

@gavin-jeong

Copy link
Copy Markdown
Collaborator

JIRA: https://sendbird.atlassian.net/browse/CPLAT-12440

Regression from #167 (CPLAT-12413), reported as "shift+hjkl used to switch between resources / execution contexts and now doesn't".

What #167 got right, and what it got wrong

It moved ten actions off bare uppercase letters because a 2-set Korean layout genuinely cannot produce them — K/J arrive as ㅏ/ㅓ, which the langmap turns into lowercase k/j (list up/down), so the uppercase binding was unreachable. I re-verified that; it holds.

The mistake was treating the rebind as a swap rather than an addition. Terminal apps are usually driven in English, where K/J worked fine and had been the region-nav keys since CPLAT-10969. Replacing them took a working, muscle-memory binding away from everyone not typing in Korean — and the migration rewrote their config.yaml, so they could not fall back either.

Both groups can have it

The new key stays the default and the one the help shows; the old key is accepted as an alias.

Scope Old Current default
session V, D v, d
actions F, M, X b, a, z
conversation A, K, J, L, I a, ctrl+p, ctrl+n, ctrl+l, w
preview F u
config / plugins reverse search N b

resolveLegacyKey(scope, key) rewrites an old key to whatever triggers that action now. It runs once per view, past the text-input and pane-proxy guards, so a pre-rebind key typed into a filter or forwarded to tmux stays literal. An alias is skipped when that key is bound to something else in the same scope, so a user's own override always wins rather than being shadowed.

The region-nav help row shows ^P / ^N (K/J) while the defaults are in effect, since K/J is the spelling fingers reach for.

Test plan

  • go build ./... && go vet ./... && go test ./... green
  • Three guards, each verified by removing an alias and confirming the test fails:
    • TestLegacyKeysStillWork — every moved key resolves to its replacement; unrelated keys pass through untouched
    • TestLegacyAliasYieldsToUserBinding — an alias never shadows a key the user bound themselves
    • TestLegacyAliasesCoverEveryRebind — ties the alias table to the migration table in state.go, so a future rebind cannot quietly drop a key people still press
  • Region nav exercised end-to-end through the real Update loop with both spellings (K/ctrl+p, J/ctrl+n) against the existing conversation fixture
  • Confirmed the Korean premise still holds before building on it: physical K/J under 2-set produce ㅏ/ㅓ -> k/j, never uppercase

Notes for reviewers

  • The alias table is the inverse of migrateKeymapDefaults's rewrite list. TestLegacyAliasesCoverEveryRebind asserts that relationship rather than leaving the two to drift.
  • scopeKeys is only built when an alias actually matches, so the common path is one map lookup.
  • Users whose config.yaml was rewritten by CPLAT-12413: make shortcuts reachable under a Korean input source #167's migration keep the new key and regain the old one; no further migration needed.

Security checklist

  • No SecurityGroup rule changes
  • No 0.0.0.0/0 inbound
  • No public subnet resources
  • No IAM user changes
  • No secrets in code, commits, or logs

CPLAT-12413 moved ten actions off bare uppercase letters because a 2-set
Korean layout cannot produce them — K/J arrive as ㅏ/ㅓ, which the
langmap turns into lowercase k/j (list up/down), so the uppercase
binding was genuinely unreachable. That much was right.

What it got wrong was treating the rebind as a swap rather than an
addition. Terminal apps are usually driven in English, where K/J worked
fine and had been the region-nav keys since CPLAT-10969. Replacing them
took a working binding away from everyone not typing in Korean, and the
migration rewrote their config.yaml so they could not fall back either.
It surfaced as "shift+hjkl used to move between resources and execution
contexts and now does nothing".

Both groups can have it. The new key stays the default and the one the
help shows; the old key is accepted as an alias:

  session       V D          -> v d
  actions       F M X        -> b a z
  conversation  A K J L I    -> a ctrl+p ctrl+n ctrl+l w
  preview       F            -> u
  config/plugins reverse search  N -> b

resolveLegacyKey(scope, key) rewrites an old key to whatever triggers
that action now. It runs once per view, past the text-input and
pane-proxy guards, so a pre-rebind key typed into a filter or forwarded
to tmux stays literal. An alias is skipped when that key is bound to
something else in the same scope, so a user's own override always wins
rather than being shadowed.

The region-nav help row shows "^P / ^N (K/J)" while the defaults are in
effect, since K/J is the spelling fingers reach for.

Three guards, each verified by removing an alias and confirming the test
fails. TestLegacyAliasesCoverEveryRebind ties the alias table to the
migration table in state.go, so a future rebind cannot quietly drop a
key people still press. Region nav is also exercised end-to-end through
the real Update loop with both spellings.
@upwind-code-us

upwind-code-us Bot commented Sep 29, 2026 •

Copy link
Copy Markdown

Upwind Upwind Code Scan - ✅ Passed

0 newly introduced vulnerabilities · 0 resolved · 1 total in this PR vs master

Total breakdown: 🔶 1 High

View full analysis in Upwind Console

Scan completed in 19s

Scan history (1 scan)
Commit Scanned at New Resolved Net
c833db4 < 2026-09-29 04:42 UTC 0 0 0

Last scanned: c833db4 · 2026-09-29 04:42 UTC

@upwind-code-us

upwind-code-us Bot commented Sep 29, 2026 •

Copy link
Copy Markdown

Upwind Upwind IaC Scan - ✅ Passed

0 newly introduced misconfigurations · 0 resolved · 0 total in this PR vs master

View full analysis in Upwind Console →

Scan completed in 4s

Scan history (1 scan)
Commit Scanned at New Resolved Net
c833db4 < 2026-09-29 04:42 UTC 0 0 0

Last scanned: c833db4 · 2026-09-29 04:42 UTC

@Kairo-Kim Kairo-Kim added the auto-review/approved Auto-approved by the Slack auto-reviewer bot label Sep 29, 2026

@jinsekim jinsekim left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@gavin-jeong
gavin-jeong merged commit c3fa620 into master Sep 29, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

auto-review/approved Auto-approved by the Slack auto-reviewer bot

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants