Implement erase_in_screen()

This commit is contained in:
Kovid Goyal 2016-10-19 13:49:27 +05:30
parent fd7a6b20e0
commit fea7c2dcb0
3 changed files with 51 additions and 15 deletions

View File

@ -70,7 +70,7 @@ class Screen(QObject):
@property
def display(self) -> Sequence[str]:
return [str(l) for l in self.linebuf]
return tuple(map(str, self.linebuf))
def reset(self):
"""Resets the terminal to its initial state.
@ -630,7 +630,7 @@ class Screen(QObject):
line.clear_text(s, n)
else:
line.apply_cursor(c, s, n, clear_char=True)
self.update_cell_range(y, s, min(s + n, self.columns - 1))
self.update_cell_range(y, s, min(s + n, self.columns) - 1)
def erase_in_display(self, how=0, private=False):
"""Erases display in a specific way.
@ -643,28 +643,33 @@ class Screen(QObject):
including cursor position.
* ``2`` -- Erases complete display. All lines are erased
and changed to single-width. Cursor does not move.
:param bool private: when ``True`` character attributes are left
unchanged **not implemented**.
:param bool private: when ``True`` character attributes are left unchanged
"""
if how == 0:
# a) erase from cursor to the end of the display, including
# the cursor,
interval = range(self.cursor.y + 1, self.lines)
interval = self.cursor.y + 1, self.lines
elif how == 1:
# b) erase from the beginning of the display to the cursor,
# including it,
interval = range(self.cursor.y)
interval = 0, self.cursor.y
elif how == 2:
# c) erase the whole display.
interval = range(self.lines)
interval = 0, self.lines
else:
return
for line in interval:
self.buffer[line][:] = \
(self.cursor.attrs for _ in range(self.columns))
if interval[1] > interval[0]:
for line in range(*interval):
if private:
self.linebuf[line].clear_text(0, self.columns)
else:
self.linebuf[line].apply_cursor(self.cursor, 0, self.columns, clear_char=True)
self.update_line_range(interval[0], interval[1] - 1)
# In case of 0 or 1 we have to erase the line with the cursor.
if how == 0 or how == 1:
self.erase_in_line(how)
# In case of 0 or 1 we have to erase the line with the cursor also
if how != 2:
self.erase_in_line(how, private=private)
def set_tab_stop(self):
"""Sets a horizontal tab stop at cursor position."""

View File

@ -81,7 +81,7 @@ class ChangeTracker(QObject):
else:
if self.changed_lines:
for y in self.changed_lines:
del self.changed_cells[y]
self.changed_cells.pop(y, None)
for y, cell_ranges in self.changed_cells.items():
self.changed_cells[y] = tuple(merge_ranges(cell_ranges))
changes = {'screen': self.screen_changed, 'cursor': self.changed_cursor, 'lines': self.changed_lines,

View File

@ -153,7 +153,7 @@ class TestScreen(BaseTest):
init()
s.erase_in_line(1)
self.ae(str(s.linebuf[0]), ' cde')
self.assertChanges(t, cells={0: ((0, 2),)})
self.assertChanges(t, cells={0: ((0, 1),)})
init()
s.erase_in_line(2)
self.ae(str(s.linebuf[0]), ' ')
@ -161,3 +161,34 @@ class TestScreen(BaseTest):
init()
s.erase_in_line(2, private=True)
self.ae((False, False, False, False, False), tuple(map(lambda i: s.linebuf[0].cursor_from(i).bold, range(5))))
def test_erase_in_screen(self):
s, t = self.create_screen()
def init():
s.reset()
s.draw(b'12345' * 5)
t.reset()
s.cursor.x, s.cursor.y = 2, 1
s.cursor.bold = True
init()
s.erase_in_display()
self.ae(s.display, ('12345', '12 ', ' ', ' ', ' '))
self.assertChanges(t, lines={2, 3, 4}, cells={1: ((2, 4),)})
init()
s.erase_in_display(1)
self.ae(s.display, (' ', ' 45', '12345', '12345', '12345'))
self.assertChanges(t, lines={0}, cells={1: ((0, 2),)})
init()
s.erase_in_display(2)
self.ae(s.display, (' ', ' ', ' ', ' ', ' '))
self.assertChanges(t, lines=set(range(5)))
self.assertTrue(s.linebuf[0].cursor_from(1).bold)
init()
s.erase_in_display(2, private=True)
self.ae(s.display, (' ', ' ', ' ', ' ', ' '))
self.assertChanges(t, lines=set(range(5)))
self.assertFalse(s.linebuf[0].cursor_from(1).bold)