From 7fb91cc12527f530b28a455150dc2a59c508371f Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Mon, 23 Dec 2024 12:50:43 +1100 Subject: [PATCH] Implement scroll up and down sequences --- pyte/escape.py | 6 ++++++ pyte/screens.py | 36 ++++++++++++++++++++++++++++++++++++ pyte/streams.py | 4 +++- 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/pyte/escape.py b/pyte/escape.py index 7dfd6b8..3cfc1e7 100644 --- a/pyte/escape.py +++ b/pyte/escape.py @@ -150,3 +150,9 @@ #: *Horizontal position adjust*: Same as :data:`CHA`. HPA = "'" + +#: *Scroll up*: scroll up +SU = "S" + +#: *Scroll down*: scroll up +SD = "T" diff --git a/pyte/screens.py b/pyte/screens.py index ebbac7c..7f655bf 100644 --- a/pyte/screens.py +++ b/pyte/screens.py @@ -576,6 +576,28 @@ def reverse_index(self) -> None: else: self.cursor_up() + def scroll_up(self, count: Optional[int] = None) -> None: + """Scroll the screen up # lines. Cursor does not move. + """ + for _ in range(count or 1): + top, bottom = self.margins or Margins(0, self.lines - 1) + # TODO: mark only the lines within margins? + self.dirty.update(range(self.lines)) + for y in range(top, bottom): + self.buffer[y] = self.buffer[y + 1] + self.buffer.pop(bottom, None) + + def scroll_down(self, count: Optional[int] = None) -> None: + """Scroll the screen down # lines. Cursor does not move. + """ + for _ in range(count or 1): + top, bottom = self.margins or Margins(0, self.lines - 1) + # TODO: mark only the lines within margins? + self.dirty.update(range(self.lines)) + for y in range(bottom, top, -1): + self.buffer[y] = self.buffer[y - 1] + self.buffer.pop(top, None) + def linefeed(self) -> None: """Perform an index and, if :data:`~pyte.modes.LNM` is set, a carriage return. @@ -1230,6 +1252,20 @@ def reverse_index(self) -> None: super(HistoryScreen, self).reverse_index() + def scroll_up(self, count: Optional[int] = None) -> None: + """Overloaded to update top history with the removed lines.""" + for _ in range(count or 1): + top, bottom = self.margins or Margins(0, self.lines - 1) + self.history.top.append(self.buffer[top]) + super(HistoryScreen, self).scroll_up() + + def scroll_down(self, count: Optional[int] = None) -> None: + """Overloaded to update bottom history with the removed lines.""" + for _ in range(count or 1): + top, bottom = self.margins or Margins(0, self.lines - 1) + self.history.bottom.append(self.buffer[bottom]) + super(HistoryScreen, self).scroll_down() + def prev_page(self) -> None: """Move the screen page up through the history buffer. Page size is defined by ``history.ratio``, so for instance diff --git a/pyte/streams.py b/pyte/streams.py index cd0f51c..012d334 100644 --- a/pyte/streams.py +++ b/pyte/streams.py @@ -121,7 +121,9 @@ class Stream: esc.SGR: "select_graphic_rendition", esc.DSR: "report_device_status", esc.DECSTBM: "set_margins", - esc.HPA: "cursor_to_column" + esc.HPA: "cursor_to_column", + esc.SU: "scroll_up", + esc.SD: "scroll_down" } #: A set of all events dispatched by the stream.