diff --git a/pyte/escape.py b/pyte/escape.py index dc06b8b..1564fb1 100644 --- a/pyte/escape.py +++ b/pyte/escape.py @@ -152,3 +152,9 @@ #: *Horizontal position adjust*: Same as :data:`CHA`. HPA = "'" + +#: *Scroll up* +SU = "S" + +#: *Scroll down* +SD = "T" diff --git a/pyte/screens.py b/pyte/screens.py index a297092..0b45f27 100644 --- a/pyte/screens.py +++ b/pyte/screens.py @@ -139,6 +139,11 @@ def __init__(self, default): def __missing__(self, key): return self.default + def copy(self): + new_static_default_dict = type(self)(self.default) + new_static_default_dict.update(self) + return new_static_default_dict + class Screen(object): """ @@ -1043,6 +1048,26 @@ def debug(self, *args, **kwargs): By default is a noop. """ + def scroll_up(self, lines): + """Scroll up `lines` lines.""" + lines_to_scroll = range(self.margins.top, self.margins.bottom + 1) + for y in lines_to_scroll: + if y + lines in set(lines_to_scroll): + self.buffer[y] = self.buffer[y + lines].copy() + else: + self.buffer[y].clear() + self.dirty = set(lines_to_scroll) + + def scroll_down(self, lines): + """Scroll down `lines` lines.""" + lines_to_scroll = range(self.margins.bottom, self.margins.top - 1, -1) + for y in lines_to_scroll: + if y - lines in set(lines_to_scroll): + self.buffer[y] = self.buffer[y - lines].copy() + else: + self.buffer[y].clear() + self.dirty = set(lines_to_scroll) + class DiffScreen(Screen): """ diff --git a/pyte/streams.py b/pyte/streams.py index 6d684f6..7bbcc3e 100644 --- a/pyte/streams.py +++ b/pyte/streams.py @@ -117,7 +117,9 @@ class Stream(object): 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.SD: "scroll_down", + esc.SU: "scroll_up" } #: A set of all events dispatched by the stream. diff --git a/tests/test_screen.py b/tests/test_screen.py index b171b5e..b7481c5 100644 --- a/tests/test_screen.py +++ b/tests/test_screen.py @@ -1505,3 +1505,54 @@ def test_screen_set_icon_name_title(): screen.set_title(text) assert screen.title == text + + +def test_scroll_down(): + screen = pyte.Screen(1, 5) + screen.set_mode(mo.LNM) + screen.linefeed() + for i in "abcd": + screen.draw(i) + screen.linefeed() + screen.draw("e") + + screen.set_margins(top=2, bottom=4) + + assert screen.display == ["a", + "b", + "c", + "d", + "e"] + + screen.scroll_down(2) + + assert screen.display == ["a", + " ", + " ", + "b", + "e"] + +def test_scroll_up(): + screen = pyte.Screen(1, 5) + screen.set_mode(mo.LNM) + screen.linefeed() + for i in "abcd": + screen.draw(i) + screen.linefeed() + screen.draw("e") + + screen.set_margins(top=2, bottom=4) + + assert screen.display == ["a", + "b", + "c", + "d", + "e"] + + screen.scroll_up(2) + + assert screen.display == ["a", + "d", + " ", + " ", + "e"]