Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Fixed pagination edge cases

  Screen was emptied when `prev_page()` reached the top of the history
  buffer
  • Loading branch information...
commit e2c64705249c0d5afe2d25ff28480ba1f50f071f 1 parent a594475
@superbobry superbobry authored
Showing with 133 additions and 8 deletions.
  1. +19 −4 pyte/screens.py
  2. +114 −4 tests/test_history.py
View
23 pyte/screens.py
@@ -395,7 +395,8 @@ def draw(self, char):
if mo.IRM in self.mode:
self.insert_characters(1)
- self[self.cursor.y][self.cursor.x] = self.cursor.attrs._replace(data=char)
+ self[self.cursor.y][self.cursor.x] = self.cursor.attrs \
+ ._replace(data=char)
# .. note:: We can't use :meth:`cursor_forward()`, because that
# way, we'll never know when to linefeed.
@@ -941,7 +942,7 @@ class HistoryScreen(DiffScreen):
def __init__(self, columns, lines, history=100, ratio=.5):
self.history = History(deque(maxlen=history // 2),
- deque(maxlen=history - history // 2),
+ deque(maxlen=history),
float(ratio),
history,
history)
@@ -970,6 +971,13 @@ def __after__(self, command):
self[idx] = line + take(self.columns - len(line),
self.default_line)
+ # If we're at the bottom of the history buffer and `DECTCEM`
+ # mode is set -- show the cursor.
+ self.cursor.hidden = not (
+ abs(self.history.position - self.history.size) < self.lines and
+ mo.DECTCEM in self.mode
+ )
+
super(HistoryScreen, self).__after__(command)
def reset(self):
@@ -1007,7 +1015,7 @@ def prev_page(self):
``ratio = .5`` means that half the screen is restored from
history on page switch.
"""
- if self.history.position > self.lines:
+ if self.history.position > self.lines and self.history.top:
mid = min(len(self.history.top),
int(math.ceil(self.lines * self.history.ratio)))
@@ -1021,9 +1029,13 @@ def prev_page(self):
self.dirty = set(range(self.lines))
+ if len(self) is not self.lines or self.history.position > self.history.size:
+ import pdb; pdb.set_trace()
+
+
def next_page(self):
"""Moves the screen page down through the history buffer."""
- if self.history.position < self.history.size:
+ if self.history.position < self.history.size and self.history.bottom:
mid = min(len(self.history.bottom),
int(math.ceil(self.lines * self.history.ratio)))
@@ -1036,3 +1048,6 @@ def next_page(self):
]
self.dirty = set(range(self.lines))
+
+ if len(self) is not self.lines or self.history.position > self.history.size:
+ import pdb; pdb.set_trace()
View
118 tests/test_history.py
@@ -72,10 +72,10 @@ def test_reverse_index():
assert screen.history.bottom[1] == line
# c) rotation.
- for _ in range(len(screen) * screen.lines):
+ for _ in range(len(screen) ** screen.lines):
screen.reverse_index()
- assert len(screen.history.bottom) == 25 # pages // 2 * lines
+ assert len(screen.history.bottom) == 50
def test_prev_page():
@@ -153,8 +153,6 @@ def test_prev_page():
# c) same with odd number of lines.
screen = HistoryScreen(5, 5, history=50)
- # Once again filling the screen with line numbers, but this time,
- # we need them to span on multiple lines.
for idx in range(len(screen) * 10):
map(screen.draw, unicode(idx))
screen.linefeed()
@@ -188,7 +186,97 @@ def test_prev_page():
" ",
]
+ # d) same with cursor in the middle of the screen.
+ screen = HistoryScreen(5, 5, history=50)
+
+ for idx in range(len(screen) * 10):
+ map(screen.draw, unicode(idx))
+ screen.linefeed()
+
+ assert screen.history.top
+ assert not screen.history.bottom
+ assert screen.history.position == 50
+ assert screen.display == [
+ "46 ",
+ "47 ",
+ "48 ",
+ "49 ",
+ " "
+ ]
+
+ screen.cursor_to_line(screen.lines // 2)
+
+ while screen.history.position > screen.lines:
+ screen.prev_page()
+
+ assert screen.history.position == screen.lines
+ assert len(screen) == screen.lines
+ assert screen.display == [
+ "21 ",
+ "22 ",
+ "23 ",
+ "24 ",
+ "25 "
+ ]
+
+ while screen.history.position < screen.history.size:
+ screen.next_page()
+ assert screen.history.position == screen.history.size
+ assert len(screen) == screen.lines
+ assert screen.display == [
+ "46 ",
+ "47 ",
+ "48 ",
+ "49 ",
+ " "
+ ]
+
+ # e) same with cursor near the middle of the screen.
+ screen = HistoryScreen(5, 5, history=50)
+
+ for idx in range(len(screen) * 10):
+ map(screen.draw, unicode(idx))
+ screen.linefeed()
+
+ assert screen.history.top
+ assert not screen.history.bottom
+ assert screen.history.position == 50
+ assert screen.display == [
+ "46 ",
+ "47 ",
+ "48 ",
+ "49 ",
+ " "
+ ]
+
+ screen.cursor_to_line(screen.lines // 2 - 2)
+
+ while screen.history.position > screen.lines:
+ screen.prev_page()
+
+ assert screen.history.position == screen.lines
+ assert len(screen) == screen.lines
+ assert screen.display == [
+ "21 ",
+ "22 ",
+ "23 ",
+ "24 ",
+ "25 "
+ ]
+
+ while screen.history.position < screen.history.size:
+ screen.next_page()
+
+ assert screen.history.position == screen.history.size
+ assert len(screen) == screen.lines
+ assert screen.display == [
+ "46 ",
+ "47 ",
+ "48 ",
+ "49 ",
+ " "
+ ]
def test_next_page():
screen = HistoryScreen(5, 5, history=50)
@@ -386,3 +474,25 @@ def test_draw():
"24 ",
"x "
]
+
+
+def test_cursor_is_hidden():
+ screen = HistoryScreen(5, 5, history=50)
+ stream = Stream()
+ stream.attach(screen)
+ stream.escape["N"] = "next_page"
+ stream.escape["P"] = "prev_page"
+
+ for idx in range(len(screen) * 5):
+ map(stream.feed, unicode(idx) + "\n")
+
+ assert not screen.cursor.hidden
+
+ stream.feed(ctrl.ESC + "P")
+ assert screen.cursor.hidden
+ stream.feed(ctrl.ESC + "P")
+ assert screen.cursor.hidden
+ stream.feed(ctrl.ESC + "N")
+ assert screen.cursor.hidden
+ stream.feed(ctrl.ESC + "N")
+ assert not screen.cursor.hidden
Please sign in to comment.
Something went wrong with that request. Please try again.