Skip to content

Commit

Permalink
Fixed pagination edge cases
Browse files Browse the repository at this point in the history
  Screen was emptied when `prev_page()` reached the top of the history
  buffer
  • Loading branch information
superbobry committed Jun 27, 2011
1 parent a594475 commit e2c6470
Show file tree
Hide file tree
Showing 2 changed files with 133 additions and 8 deletions.
23 changes: 19 additions & 4 deletions pyte/screens.py
Expand Up @@ -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.
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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)))

Expand All @@ -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)))

Expand All @@ -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()
118 changes: 114 additions & 4 deletions tests/test_history.py
Expand Up @@ -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():
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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

0 comments on commit e2c6470

Please sign in to comment.