mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-25 00:51:20 +00:00
fix(tui): pager supports scrolling (up/down/page/top/bottom)
The pager overlay backing /history, /toolsets, /help and any paged slash output only advanced with Enter/Space and closed at the end. Could not scroll back, scroll line-by-line, or jump to endpoints. Adds Up/Down (↑↓, j/k), PgUp (b), g/G for top/bottom, keeps existing Enter/Space/PgDn forward-and-auto-close, and clamps offset so over-scrolling past the last page is a no-op.
This commit is contained in:
parent
ce98e1ef11
commit
887dfc4067
22 changed files with 258 additions and 82 deletions
|
|
@ -7,7 +7,6 @@ import type {
|
|||
SudoRespondResponse,
|
||||
VoiceRecordResponse
|
||||
} from '../gatewayTypes.js'
|
||||
|
||||
import { isAction, isMac } from '../lib/platform.js'
|
||||
|
||||
import { getInputSelection } from './inputSelectionStore.js'
|
||||
|
|
@ -174,14 +173,60 @@ export function useInputHandlers(ctx: InputHandlerContext): InputHandlerResult {
|
|||
|
||||
if (isBlocked) {
|
||||
if (overlay.pager) {
|
||||
if (key.return || ch === ' ') {
|
||||
const nextOffset = overlay.pager.offset + pagerPageSize
|
||||
if (key.escape || isCtrl(key, ch, 'c') || ch === 'q') {
|
||||
return patchOverlayState({ pager: null })
|
||||
}
|
||||
|
||||
patchOverlayState({
|
||||
pager: nextOffset >= overlay.pager.lines.length ? null : { ...overlay.pager, offset: nextOffset }
|
||||
const move = (delta: number | 'top' | 'bottom') =>
|
||||
patchOverlayState(prev => {
|
||||
if (!prev.pager) {
|
||||
return prev
|
||||
}
|
||||
|
||||
const { lines, offset } = prev.pager
|
||||
const max = Math.max(0, lines.length - pagerPageSize)
|
||||
const step = delta === 'top' ? -lines.length : delta === 'bottom' ? lines.length : delta
|
||||
const next = Math.max(0, Math.min(offset + step, max))
|
||||
|
||||
return next === offset ? prev : { ...prev, pager: { ...prev.pager, offset: next } }
|
||||
})
|
||||
|
||||
if (key.upArrow || ch === 'k') {
|
||||
return move(-1)
|
||||
}
|
||||
|
||||
if (key.downArrow || ch === 'j') {
|
||||
return move(1)
|
||||
}
|
||||
|
||||
if (key.pageUp || ch === 'b') {
|
||||
return move(-pagerPageSize)
|
||||
}
|
||||
|
||||
if (ch === 'g') {
|
||||
return move('top')
|
||||
}
|
||||
|
||||
if (ch === 'G') {
|
||||
return move('bottom')
|
||||
}
|
||||
|
||||
if (key.return || ch === ' ' || key.pageDown) {
|
||||
patchOverlayState(prev => {
|
||||
if (!prev.pager) {
|
||||
return prev
|
||||
}
|
||||
|
||||
const { lines, offset } = prev.pager
|
||||
const max = Math.max(0, lines.length - pagerPageSize)
|
||||
|
||||
// Auto-close only when already at the last page — otherwise clamp
|
||||
// to `max` so the offset matches what the line/page-back handlers
|
||||
// can reach (prevents a snap-back jump on the next ↑/↓/PgUp).
|
||||
return offset >= max
|
||||
? { ...prev, pager: null }
|
||||
: { ...prev, pager: { ...prev.pager, offset: Math.min(offset + pagerPageSize, max) } }
|
||||
})
|
||||
} else if (key.escape || isCtrl(key, ch, 'c') || ch === 'q') {
|
||||
patchOverlayState({ pager: null })
|
||||
}
|
||||
|
||||
return
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue