diff --git a/src/rich_cli/pager.py b/src/rich_cli/pager.py index 419d3a0..e669ce8 100644 --- a/src/rich_cli/pager.py +++ b/src/rich_cli/pager.py @@ -46,6 +46,8 @@ def __rich_measure__( class PagerApp(App): """App to scroll renderable""" + _g_key_pressed_before = False + def __init__( self, *args, @@ -59,18 +61,46 @@ async def on_load(self, event: events.Load) -> None: await self.bind("q", "quit", "Quit") async def on_key(self, event: events.Key) -> None: - if event.key == "j": + def body_scroll_to_y(y: float, easing: str): + self.body.target_y = y + self.body.animate("y", self.body.target_y, easing=easing) + + # for `gg` to scroll to top + if event.key == "g": + if not self._g_key_pressed_before: + self._g_key_pressed_before = True + else: + body_scroll_to_y(0, easing="out_expo") + self._g_key_pressed_before = False + + return + + self._g_key_pressed_before = False + + if event.key == "G": + body_scroll_to_y(self.body.max_scroll_y, easing="out_expo") + elif event.key == "j": self.body.scroll_up() elif event.key == "k": self.body.scroll_down() elif event.key == " ": self.body.page_down() - elif event.key == "ctrl+u": - self.body.target_y -= self.body.size.height // 2 - self.body.animate("y", self.body.target_y, easing="out_cubic") - elif event.key == "ctrl+d": - self.body.target_y += self.body.size.height // 2 - self.body.animate("y", self.body.target_y, easing="out_cubic") + elif event.key in ["u", "ctrl+u"]: + body_scroll_to_y( + self.body.target_y - self.body.size.height // 2, easing="out_cubic" + ) + elif event.key in ["d", "ctrl+d"]: + body_scroll_to_y( + self.body.target_y + self.body.size.height // 2, easing="out_cubic" + ) + elif event.key in ["b", "ctrl+b"]: + body_scroll_to_y( + self.body.target_y - self.body.size.height, easing="out_quart" + ) + elif event.key in ["f", "ctrl+f"]: + body_scroll_to_y( + self.body.target_y + self.body.size.height, easing="out_quart" + ) async def on_mount(self, event: events.Mount) -> None: self.body = body = ScrollView(auto_width=True)