From 8feda1828475234ccec48a9458f981df2503d073 Mon Sep 17 00:00:00 2001 From: liruifengv Date: Wed, 24 Jun 2026 20:50:31 +0800 Subject: [PATCH] feat(tui): add Ctrl+U/Ctrl+D paging in the task output viewer PgUp/PgDn are often captured by terminal or tmux scrollback, so add Ctrl+U and Ctrl+D as full-page up and down alternatives, matching the existing PgUp/PgDn behavior. --- .changeset/task-output-ctrl-ud-paging.md | 5 +++++ .../components/dialogs/task-output-viewer.ts | 15 ++++++++++++--- .../test/tui/task-output-viewer.test.ts | 18 ++++++++++++++++++ 3 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 .changeset/task-output-ctrl-ud-paging.md diff --git a/.changeset/task-output-ctrl-ud-paging.md b/.changeset/task-output-ctrl-ud-paging.md new file mode 100644 index 0000000000..436dd21ca7 --- /dev/null +++ b/.changeset/task-output-ctrl-ud-paging.md @@ -0,0 +1,5 @@ +--- +"@moonshot-ai/kimi-code": patch +--- + +Add Ctrl+U and Ctrl+D as page up and page down shortcuts in the task output viewer. diff --git a/apps/kimi-code/src/tui/components/dialogs/task-output-viewer.ts b/apps/kimi-code/src/tui/components/dialogs/task-output-viewer.ts index a1718a5eb3..fdcd81aac4 100644 --- a/apps/kimi-code/src/tui/components/dialogs/task-output-viewer.ts +++ b/apps/kimi-code/src/tui/components/dialogs/task-output-viewer.ts @@ -125,11 +125,20 @@ export class TaskOutputViewer extends Container implements Focusable { this.scrollBy(1); return; } - if (matchesKey(data, Key.pageUp) || k === ' ' || data === '\u0002' /* C-b */) { + if ( + matchesKey(data, Key.pageUp) || + matchesKey(data, Key.ctrl('u')) || + k === ' ' || + data === '\u0002' /* C-b */ + ) { this.scrollBy(-Math.max(1, visible - 1)); return; } - if (matchesKey(data, Key.pageDown) || data === '\u0006' /* C-f */) { + if ( + matchesKey(data, Key.pageDown) || + matchesKey(data, Key.ctrl('d')) || + data === '\u0006' /* C-f */ + ) { this.scrollBy(Math.max(1, visible - 1)); return; } @@ -240,7 +249,7 @@ export class TaskOutputViewer extends Container implements Focusable { ); const keys = `${key('↑↓')} ${dim('line')} ` + - `${key('PgUp/PgDn')} ${dim('page')} ` + + `${key('PgUp/PgDn/Ctrl+U/D')} ${dim('page')} ` + `${key('g/G')} ${dim('top/bot')} ` + `${key('Q/Esc')} ${dim('cancel')}`; const left = ` ${keys}`; diff --git a/apps/kimi-code/test/tui/task-output-viewer.test.ts b/apps/kimi-code/test/tui/task-output-viewer.test.ts index a7cbfe0dfa..2a3880e3d0 100644 --- a/apps/kimi-code/test/tui/task-output-viewer.test.ts +++ b/apps/kimi-code/test/tui/task-output-viewer.test.ts @@ -144,6 +144,24 @@ describe('TaskOutputViewer — scrolling', () => { expect(out).not.toContain('line-001'); }); + it('Ctrl+D scrolls a page down', () => { + const viewer = makeViewer({ output: bigOutput(50), rows: 12 }); + viewer.handleInput('\u0004'); // Ctrl+D + const out = strip(viewer.render(120).join('\n')); + // Same page size as PageDown: body has 8 viewable rows, page = 7 lines. + expect(out).toContain('line-008'); + expect(out).not.toContain('line-001'); + }); + + it('Ctrl+U scrolls a page up', () => { + const viewer = makeViewer({ output: bigOutput(50), rows: 12 }); + viewer.handleInput('G'); // jump to bottom first + viewer.handleInput('\u0015'); // Ctrl+U + const out = strip(viewer.render(120).join('\n')); + expect(out).toContain('line-036'); + expect(out).not.toContain('line-050'); + }); + it('G jumps to the bottom', () => { const viewer = makeViewer({ output: bigOutput(100), rows: 14 }); viewer.handleInput('G');