feat(coding-agent): add page-up/down navigation to session selector (#662)

* feat(tui): add pageUp/pageDown key support and selectPageUp/selectPageDown actions

* feat(coding-agent): add page-up/down navigation to session selector
This commit is contained in:
Aliou Diallo 2026-01-12 17:01:46 +01:00 committed by GitHub
parent 8f95a13e07
commit 638fbc459b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 37 additions and 0 deletions

View file

@ -7,6 +7,7 @@
- Session naming: `/name <name>` command sets a display name shown in the session selector instead of the first message. Useful for distinguishing forked sessions. Extensions can use `pi.setSessionName()` and `pi.getSessionName()`. ([#650](https://github.com/badlogic/pi-mono/pull/650) by [@scutifer](https://github.com/scutifer))
- Extension example: `notify.ts` for desktop notifications via OSC 777 escape sequence ([#658](https://github.com/badlogic/pi-mono/pull/658) by [@ferologics](https://github.com/ferologics))
- Inline hint for queued messages showing the `Alt+Up` restore shortcut ([#657](https://github.com/badlogic/pi-mono/pull/657) by [@tmustier](https://github.com/tmustier))
- Page-up/down navigation in `/resume` session selector to jump by 5 items ([#662](https://github.com/badlogic/pi-mono/pull/662) by [@aliou](https://github.com/aliou))
### Fixed

View file

@ -227,6 +227,14 @@ class SessionList implements Component {
else if (kb.matches(keyData, "selectDown")) {
this.selectedIndex = Math.min(this.filteredSessions.length - 1, this.selectedIndex + 1);
}
// Page up - jump up by maxVisible items
else if (kb.matches(keyData, "selectPageUp")) {
this.selectedIndex = Math.max(0, this.selectedIndex - this.maxVisible);
}
// Page down - jump down by maxVisible items
else if (kb.matches(keyData, "selectPageDown")) {
this.selectedIndex = Math.min(this.filteredSessions.length - 1, this.selectedIndex + this.maxVisible);
}
// Enter
else if (kb.matches(keyData, "selectConfirm")) {
const selected = this.filteredSessions[this.selectedIndex];

View file

@ -2,6 +2,10 @@
## [Unreleased]
### Added
- `pageUp` and `pageDown` key support with `selectPageUp`/`selectPageDown` editor actions ([#662](https://github.com/badlogic/pi-mono/pull/662) by [@aliou](https://github.com/aliou))
## [0.43.0] - 2026-01-11
### Added

View file

@ -26,6 +26,8 @@ export type EditorAction =
// Selection/autocomplete
| "selectUp"
| "selectDown"
| "selectPageUp"
| "selectPageDown"
| "selectConfirm"
| "selectCancel"
// Clipboard
@ -67,6 +69,8 @@ export const DEFAULT_EDITOR_KEYBINDINGS: Required<EditorKeybindingsConfig> = {
// Selection/autocomplete
selectUp: "up",
selectDown: "down",
selectPageUp: "pageUp",
selectPageDown: "pageDown",
selectConfirm: "enter",
selectCancel: ["escape", "ctrl+c"],
// Clipboard

View file

@ -114,6 +114,8 @@ type SpecialKey =
| "delete"
| "home"
| "end"
| "pageUp"
| "pageDown"
| "up"
| "down"
| "left"
@ -164,6 +166,8 @@ export const Key = {
delete: "delete" as const,
home: "home" as const,
end: "end" as const,
pageUp: "pageUp" as const,
pageDown: "pageDown" as const,
up: "up" as const,
down: "down" as const,
left: "left" as const,
@ -611,6 +615,18 @@ export function matchesKey(data: string, keyId: KeyId): boolean {
}
return matchesKittySequence(data, FUNCTIONAL_CODEPOINTS.end, modifier);
case "pageUp":
if (modifier === 0) {
return data === "\x1b[5~" || matchesKittySequence(data, FUNCTIONAL_CODEPOINTS.pageUp, 0);
}
return matchesKittySequence(data, FUNCTIONAL_CODEPOINTS.pageUp, modifier);
case "pageDown":
if (modifier === 0) {
return data === "\x1b[6~" || matchesKittySequence(data, FUNCTIONAL_CODEPOINTS.pageDown, 0);
}
return matchesKittySequence(data, FUNCTIONAL_CODEPOINTS.pageDown, modifier);
case "up":
if (modifier === 0) {
return data === "\x1b[A" || matchesKittySequence(data, ARROW_CODEPOINTS.up, 0);
@ -713,6 +729,8 @@ export function parseKey(data: string): string | undefined {
else if (codepoint === FUNCTIONAL_CODEPOINTS.delete) keyName = "delete";
else if (codepoint === FUNCTIONAL_CODEPOINTS.home) keyName = "home";
else if (codepoint === FUNCTIONAL_CODEPOINTS.end) keyName = "end";
else if (codepoint === FUNCTIONAL_CODEPOINTS.pageUp) keyName = "pageUp";
else if (codepoint === FUNCTIONAL_CODEPOINTS.pageDown) keyName = "pageDown";
else if (codepoint === ARROW_CODEPOINTS.up) keyName = "up";
else if (codepoint === ARROW_CODEPOINTS.down) keyName = "down";
else if (codepoint === ARROW_CODEPOINTS.left) keyName = "left";
@ -749,6 +767,8 @@ export function parseKey(data: string): string | undefined {
if (data === "\x1b[H") return "home";
if (data === "\x1b[F") return "end";
if (data === "\x1b[3~") return "delete";
if (data === "\x1b[5~") return "pageUp";
if (data === "\x1b[6~") return "pageDown";
// Raw Ctrl+letter
if (data.length === 1) {