From 75e00d438c9afa702c0cdcfee6156989a217f05d Mon Sep 17 00:00:00 2001 From: Levi Neely Date: Wed, 1 Apr 2026 00:24:19 +0200 Subject: [PATCH] Add chat history scrolling via PageUp/PageDown and ctrl+u/ctrl+d Configure viewport keymap to use page-based scroll keys only, leaving up/down arrows free for textarea cursor movement. Viewport is now initialized once with the custom keymap and resized (not recreated) on window resize. Key messages are routed to both viewport and textarea. Co-Authored-By: Claude Sonnet 4.6 --- main.go | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/main.go b/main.go index 5598f6b..5c54f21 100644 --- a/main.go +++ b/main.go @@ -173,8 +173,19 @@ func main() { ta.KeyMap.InsertNewline = key.NewBinding(key.WithKeys("ctrl+j")) ta.Focus() + vp := viewport.New(0, 0) + vp.KeyMap = viewport.KeyMap{ + PageDown: key.NewBinding(key.WithKeys("pgdown")), + PageUp: key.NewBinding(key.WithKeys("pgup")), + HalfPageDown: key.NewBinding(key.WithKeys("ctrl+d")), + HalfPageUp: key.NewBinding(key.WithKeys("ctrl+u")), + Down: key.NewBinding(key.WithKeys()), + Up: key.NewBinding(key.WithKeys()), + } + p := tea.NewProgram(model{ textarea: ta, + viewport: vp, loopcfg: loopcfg, hooks: hooks, }) @@ -204,15 +215,11 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { switch msg := msg.(type) { case tea.WindowSizeMsg: - if !m.ready { - m.viewport = viewport.New(msg.Width, msg.Height-5) - m.ready = true - } else { - m.viewport.Width = msg.Width - m.viewport.Height = msg.Height - 5 - } + m.viewport.Width = msg.Width + m.viewport.Height = msg.Height - 5 m.textarea.SetWidth(msg.Width) m.viewport.SetContent(m.renderDisplay()) + m.ready = true case responseMsg: m.display = msg.display @@ -243,8 +250,10 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { } } + var vpCmd tea.Cmd + m.viewport, vpCmd = m.viewport.Update(msg) m.textarea, cmd = m.textarea.Update(msg) - return m, cmd + return m, tea.Batch(cmd, vpCmd) } func (m model) runLoop(input string) tea.Cmd {