From 55aa4b6766233158d17854cc845aaf6878d095d1 Mon Sep 17 00:00:00 2001 From: Tristan Simas Date: Sun, 25 Oct 2026 02:44:42 -0400 Subject: [PATCH 1/2] Shift+PageUp/PageDown scroll a quarter page (draft) Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_013ejYrMLnLWah8wCDDcb57V From f7443110cd58d1abcd577e9ae7f193b580239e55 Mon Sep 17 00:00:00 2001 From: Tristan Simas Date: Sun, 25 Oct 2026 02:45:29 -0400 Subject: [PATCH 2/2] Scroll a quarter page with Shift+PageUp/PageDown Two ConversationAction members bind the keys; HistoryWindow owns the scroll beside page_up/page_down and goes through the same lazy-history guard. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_013ejYrMLnLWah8wCDDcb57V --- src/toad/conversation_actions.py | 17 +++++++++++++++++ src/toad/widgets/history_anchor.py | 4 ++++ 2 files changed, 21 insertions(+) diff --git a/src/toad/conversation_actions.py b/src/toad/conversation_actions.py index c4b62c263..9387a6f8a 100644 --- a/src/toad/conversation_actions.py +++ b/src/toad/conversation_actions.py @@ -60,6 +60,23 @@ class VimCancelAction(CancelAction): vim_profile = True +class QuarterPageUpAction(ConversationAction): + """Scroll the conversation up a quarter page.""" + + keys = ("shift+pageup",) + direction = -1 + + async def apply(self, conversation): + conversation.window.scroll_quarter_page(self.direction) + + +class QuarterPageDownAction(QuarterPageUpAction): + """Scroll the conversation down a quarter page.""" + + keys = ("shift+pagedown",) + direction = 1 + + class ExpandBlockAction(ConversationAction): """Expand the block under the cursor.""" diff --git a/src/toad/widgets/history_anchor.py b/src/toad/widgets/history_anchor.py index 2cc4d5a52..9ad62e957 100644 --- a/src/toad/widgets/history_anchor.py +++ b/src/toad/widgets/history_anchor.py @@ -478,6 +478,10 @@ def _on_mouse_scroll_down(self, event: events.MouseScrollDown) -> None: def action_page_down(self) -> None: self._scroll_or_prepare(max(1, self.scrollable_content_region.height), super().action_page_down) + def scroll_quarter_page(self, direction: int) -> None: + distance = direction * max(1, self.scrollable_content_region.height // 4) + self._scroll_or_prepare(distance, self.scroll_relative, None, distance) + def _on_mouse_scroll_left(self, event: events.MouseScrollLeft) -> None: event.prevent_default() super()._on_mouse_scroll_left(event)