From 7c5706ead9e18a0b1d59e0a05af18fc594aa1084 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 11 May 2021 14:35:47 +0530 Subject: [PATCH] Add the ability to unscroll the screen to the ``kitty @ scroll-window`` remote control command Fixes #3604 --- docs/changelog.rst | 3 +++ kitty/fast_data_types.pyi | 3 +++ kitty/rc/scroll_window.py | 24 +++++++++++++++--------- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index e6fac764b..625bb04e1 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -25,6 +25,9 @@ To update |kitty|, :doc:`follow the instructions `. - Add a configurable mouse action to select from the clicked point to the end of the line. (:iss:`3585`) +- Add the ability to unscroll the screen to the ``kitty @ scroll-window`` + remote control command (:iss:`3604`) + - Unicode input kitten: Fix a regression in 0.20.0 that broke keyboard handling when the num lock or caps lock modifiers were engaged. (:iss:`3587`) diff --git a/kitty/fast_data_types.pyi b/kitty/fast_data_types.pyi index 07ccdad5f..4d6682b45 100644 --- a/kitty/fast_data_types.pyi +++ b/kitty/fast_data_types.pyi @@ -1001,6 +1001,9 @@ class Screen: def scroll_to_next_mark(self, mark: int = 0, backwards: bool = True) -> bool: pass + def reverse_scroll(self, amt: int, fill_from_scrollback: bool = False) -> bool: + pass + def clear_selection(self) -> None: pass diff --git a/kitty/rc/scroll_window.py b/kitty/rc/scroll_window.py index 2eaf24e6f..9aefd705c 100644 --- a/kitty/rc/scroll_window.py +++ b/kitty/rc/scroll_window.py @@ -19,7 +19,8 @@ class ScrollWindow(RemoteCommand): ''' amount+: The amount to scroll, a two item list with the first item being \ either a number or the keywords, start and end. \ - And the second item being either 'p' for pages or 'l' for lines. + And the second item being either 'p' for pages or 'l' for lines or 'u' + for unscrolling by lines. match: The window to scroll ''' @@ -28,7 +29,8 @@ class ScrollWindow(RemoteCommand): 'Scroll the specified window, if no window is specified, scroll the window this command is run inside.' ' SCROLL_AMOUNT can be either the keywords :code:`start` or :code:`end` or an' ' argument of the form [unit][+-]. For example, 30 will scroll down 30 lines and 2p- will' - ' scroll up 2 pages.' + ' scroll up 2 pages. 3u will *unscroll* by 3 lines, which means that 3 lines will move from the' + ' scrollback buffer onto the top of the screen.' ) argspec = 'SCROLL_AMOUNT' options_spec = MATCH_WINDOW_OPTION @@ -38,10 +40,11 @@ class ScrollWindow(RemoteCommand): amount: Tuple[Union[str, int], Optional[str]] = (amt, None) if amt not in ('start', 'end'): pages = 'p' in amt + unscroll = 'u' in amt amt = amt.replace('p', '') - mult = -1 if amt.endswith('-') else 1 + mult = -1 if amt.endswith('-') and not unscroll else 1 q = int(amt.replace('-', '')) - amount = q * mult, 'p' if pages else 'l' + amount = q * mult, 'p' if pages else ('u' if unscroll else 'l') return {'match': opts.match, 'amount': amount} @@ -59,11 +62,14 @@ class ScrollWindow(RemoteCommand): getattr(window, {'start': 'scroll_home'}.get(amt[0], 'scroll_end'))() else: amt, unit = amt - unit = 'page' if unit == 'p' else 'line' - direction = 'up' if amt < 0 else 'down' - func = getattr(window, 'scroll_{}_{}'.format(unit, direction)) - for i in range(abs(amt)): - func() + if unit == 'u': + window.screen.reverse_scroll(abs(amt), True) + else: + unit = 'page' if unit == 'p' else 'line' + direction = 'up' if amt < 0 else 'down' + func = getattr(window, 'scroll_{}_{}'.format(unit, direction)) + for i in range(abs(amt)): + func() scroll_window = ScrollWindow()