Skip to content

fix(keys): treat keypad navigation keys as their main-block equivalents - #1225

Open
liziye627-design wants to merge 1 commit into
modem-dev:mainfrom
liziye627-design:fix/keypad-navigation-1223
Open

liziye627-design wants to merge 1 commit into
modem-dev:mainfrom
liziye627-design:fix/keypad-navigation-1223

Conversation

@liziye627-design

Copy link
Copy Markdown

Fixes #1223

Problem

In terminals that use the Kitty keyboard protocol (the report is Ghostty), OpenTUI decodes the numpad
PgUp/PgDn keys as kppageup/kppagedown. Hunk's chord matcher only accepts pageup/pagedown,
so the numpad keys do nothing. The same applies to the other keypad navigation keys (arrows,
Home/End, Insert/Delete).

Approach

matchesNamedKey in packages/hunk/src/extension-api/keys.ts now maps the ten keypad
navigation names to the main-block key before comparing. Because this happens in the shared matcher,
built-in shortcuts, user [keybindings] and extension matchesKey calls all get the fix. Modifier
matching is unchanged; for example, shift+numpad-PgDn still does not match a plain pagedown.

On reusing OpenTUI's aliases, as the issue suggests: the table mirrors the navigation
entries of OpenTUI's defaultKeyAliases. I couldn't import that map. It isn't in @opentui/core's
public types (0.5.6), and importing it at runtime fails with "Export named 'defaultKeyAliases' not
found". extension-api is also meant to be import-free per docs/module-boundaries.md. If you'd
prefer normalizing names once in the input pipeline instead, I'm happy to rework it.

Non-goals: keypad digits and operators (kp0, kpplus, …) and kpenter. These keys aren't
part of the reported bug, and mapping digits could change how text input behaves.

Why core

Every review surface shares chord matching, and extensions call the same published matcher.

Tests

  • New tests in packages/hunk/src/lib/commandKeys.test.ts pass the real Kitty sequences
    (ESC [ 57417…57426 u) through OpenTUI's parseKeypress and check each one against its chord.
    I ran them before changing keys.ts: 2 failed. After the change they pass.
  • bun test packages/hunk/src/lib/commandKeys.test.ts packages/hunk/src/extension-api/keys.test.ts: 24 pass
  • bun run typecheck, bun run lint, bun run format:check, bun run deps:check: pass
  • bun run test: shard 1 has 2519 pass, 24 skip, 1 fail; shard 2 has 2640 pass, 19 skip, 0 fail. The one failure is
    test/cli/npm-extension-install.test.ts ("installs npm extensions that import host APIs…"),
    which gets npm E401 from the test's local registry. On the same machine (checked with Bun 1.4.2) it also fails on unmodified
    main (c3af44f). The command and output are in the log.
  • Not run: the PTY, TTY smoke and review-conformance suites, because this change doesn't touch those areas.

Environment: Linux x86_64, Bun 1.4.4, Node v22.23.4. Not tested on macOS or Windows.

Visual evidence

I launched the real Hunk TUI (bun run packages/hunk/src/main.tsx -- diff) in a tuistory PTY
at 120x30 with the default theme. The diff is a 200-line file with 40 changed lines. I wrote the Kitty
numpad PageDown sequence ESC [ 57422 u to the terminal and captured the screen before and after:

  • main (c3af44f): the screen doesn't change.
  • With this fix: the view pages down. The top row moves from line 1 to line 21.

The before/after text captures are below. One limit: the PTY doesn't answer terminal
capability queries, so this shows OpenTUI decoding the raw Kitty sequence. It isn't a recording from
Ghostty with a physical numpad, which I don't have.

Text captures (120x30)

main-before

  File  View  Navigate  Agent  Help                  hunk1223-fx-wwRN56 working tree  1 file  +40  -40
 ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

  big.ts                                                                                                      +40 -40
 ▌@@ -1,199 +1,199 @@
 ▌  1     -  export const line001 = 1000;
 ▌      1 +  export const line001 = 2000;
 ▌  2   2    export const line002 = 1;
 ▌  3   3    export const line003 = 2;
 ▌  4   4    export const line004 = 3;
 ▌  5   5    export const line005 = 4;
 ▌  6     -  export const line006 = 1005;
 ▌      6 +  export const line006 = 2005;
 ▌  7   7    export const line007 = 6;
 ▌  8   8    export const line008 = 7;
 ▌  9   9    export const line009 = 8;
 ▌ 10  10    export const line010 = 9;
 ▌ 11     -  export const line011 = 1010;
 ▌     11 +  export const line011 = 2010;
 ▌ 12  12    export const line012 = 11;
 ▌ 13  13    export const line013 = 12;
 ▌ 14  14    export const line014 = 13;
 ▌ 15  15    export const line015 = 14;
 ▌ 16     -  export const line016 = 1015;
 ▌     16 +  export const line016 = 2015;
 ▌ 17  17    export const line017 = 16;
 ▌ 18  18    export const line018 = 17;
 ▌ 19  19    export const line019 = 18;
 ▌ 20  20    export const line020 = 19;
main-after

  File  View  Navigate  Agent  Help                  hunk1223-fx-wwRN56 working tree  1 file  +40  -40
 ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

  big.ts                                                                                                      +40 -40
 ▌@@ -1,199 +1,199 @@
 ▌  1     -  export const line001 = 1000;
 ▌      1 +  export const line001 = 2000;
 ▌  2   2    export const line002 = 1;
 ▌  3   3    export const line003 = 2;
 ▌  4   4    export const line004 = 3;
 ▌  5   5    export const line005 = 4;
 ▌  6     -  export const line006 = 1005;
 ▌      6 +  export const line006 = 2005;
 ▌  7   7    export const line007 = 6;
 ▌  8   8    export const line008 = 7;
 ▌  9   9    export const line009 = 8;
 ▌ 10  10    export const line010 = 9;
 ▌ 11     -  export const line011 = 1010;
 ▌     11 +  export const line011 = 2010;
 ▌ 12  12    export const line012 = 11;
 ▌ 13  13    export const line013 = 12;
 ▌ 14  14    export const line014 = 13;
 ▌ 15  15    export const line015 = 14;
 ▌ 16     -  export const line016 = 1015;
 ▌     16 +  export const line016 = 2015;
 ▌ 17  17    export const line017 = 16;
 ▌ 18  18    export const line018 = 17;
 ▌ 19  19    export const line019 = 18;
 ▌ 20  20    export const line020 = 19;
fix-before

  File  View  Navigate  Agent  Help                  hunk1223-fx-nE1nqQ working tree  1 file  +40  -40
 ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

  big.ts                                                                                                      +40 -40
 ▌@@ -1,199 +1,199 @@
 ▌  1     -  export const line001 = 1000;
 ▌      1 +  export const line001 = 2000;
 ▌  2   2    export const line002 = 1;
 ▌  3   3    export const line003 = 2;
 ▌  4   4    export const line004 = 3;
 ▌  5   5    export const line005 = 4;
 ▌  6     -  export const line006 = 1005;
 ▌      6 +  export const line006 = 2005;
 ▌  7   7    export const line007 = 6;
 ▌  8   8    export const line008 = 7;
 ▌  9   9    export const line009 = 8;
 ▌ 10  10    export const line010 = 9;
 ▌ 11     -  export const line011 = 1010;
 ▌     11 +  export const line011 = 2010;
 ▌ 12  12    export const line012 = 11;
 ▌ 13  13    export const line013 = 12;
 ▌ 14  14    export const line014 = 13;
 ▌ 15  15    export const line015 = 14;
 ▌ 16     -  export const line016 = 1015;
 ▌     16 +  export const line016 = 2015;
 ▌ 17  17    export const line017 = 16;
 ▌ 18  18    export const line018 = 17;
 ▌ 19  19    export const line019 = 18;
 ▌ 20  20    export const line020 = 19;
fix-after

  File  View  Navigate  Agent  Help                  hunk1223-fx-nE1nqQ working tree  1 file  +40  -40
 ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

  big.ts                                                                                                      +40 -40
 ▌ 21     -  export const line021 = 1020;
 ▌     21 +  export const line021 = 2020;
 ▌ 22  22    export const line022 = 21;
 ▌ 23  23    export const line023 = 22;
 ▌ 24  24    export const line024 = 23;
 ▌ 25  25    export const line025 = 24;
 ▌ 26     -  export const line026 = 1025;
 ▌     26 +  export const line026 = 2025;
 ▌ 27  27    export const line027 = 26;
 ▌ 28  28    export const line028 = 27;
 ▌ 29  29    export const line029 = 28;
 ▌ 30  30    export const line030 = 29;
 ▌ 31     -  export const line031 = 1030;
 ▌     31 +  export const line031 = 2030;
 ▌ 32  32    export const line032 = 31;
 ▌ 33  33    export const line033 = 32;
 ▌ 34  34    export const line034 = 33;
 ▌ 35  35    export const line035 = 34;
 ▌ 36     -  export const line036 = 1035;
 ▌     36 +  export const line036 = 2035;
 ▌ 37  37    export const line037 = 36;
 ▌ 38  38    export const line038 = 37;
 ▌ 39  39    export const line039 = 38;
 ▌ 40  40    export const line040 = 39;
 ▌ 41     -  export const line041 = 1040;

Changeset: .changeset/keypad-navigation-aliases.md (hunkdiff, patch).

Drafted with AI assistance; the tests above were run locally.

@greptile-apps

greptile-apps Bot commented Oct 24, 2026

Copy link
Copy Markdown
Contributor

PR author is not in the allowed authors list.

@vercel

vercel Bot commented Oct 24, 2026

Copy link
Copy Markdown

@liziye627-design is attempting to deploy a commit to the Modem Team on Vercel.

A member of the Team first needs to authorize it.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Numpad PgUp/PgDn do not scroll

1 participant