1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
#!/usr/bin/env python3
from math import ceil
from text_wrapping import TextWrapper
def getSlice(msg: str, idx: int, slice_len: int) -> str:
begin = idx * slice_len
end = (idx + 1) * slice_len
msg_len = len(msg)
if msg_len >= end:
return msg[begin:end]
if msg_len > begin:
return msg[begin:end] + (" " * (end - msg_len))
return None
def setSlice(msg: str, idx: int, slice_len: int, msg_slice: str) -> str:
begin = idx * slice_len
end = (idx + 1) * slice_len
prefix = msg[0:begin]
prefix += " " * (begin - len(prefix))
suffix = msg[end:]
msg = prefix + msg_slice + suffix
return msg
class SingleLinePager:
def __init__(self, slice_len: int):
self.msg = ""
self.slice_len = slice_len
def reset(self):
self.msg = ""
def getNextSlice(self, msg) -> tuple[str, int]:
for i in range(0, ceil(len(msg) / self.slice_len)):
old_slice = getSlice(self.msg, i, self.slice_len)
new_slice = getSlice(msg, i, self.slice_len)
if old_slice != new_slice:
self.msg = setSlice(self.msg, i, self.slice_len, new_slice)
return new_slice, i
return "", -1
class MultiLinePager:
def __init__(self, slice_len: int, rows: int, cols: int):
# This is a list of lists of SingleLinePagers.
# It represents a list of pages, each containing a list of lines.
self.pages = []
self.slice_len = slice_len
self.rows = rows
self.cols = cols
def reset(self):
self.pages = []
def getNextSlice(self, msg) -> tuple[str, int]:
pages = TextWrapper(self.rows, self.cols).wrap(msg)
# Wrapping split the input message along line boundaries and along page
# boundaries. However, we're going to treat each page like a single
# line, so that `slice_idx` can be used as a region index. Therefore,
# we need exactly one SingleLinePager per page.
for pi in range(len(self.pages), len(pages)):
self.pages.append(SingleLinePager(self.slice_len))
for pi in range(0, len(pages)):
line = "".join(pages[pi])
pager = self.pages[pi]
msg_slice, slice_idx = pager.getNextSlice(line)
if slice_idx != -1:
return msg_slice, slice_idx
return "", -1
if __name__ == "__main__":
assert(getSlice("abcdefghij", 0, 1) == "a")
assert(getSlice("abcdefghij", 9, 1) == "j")
assert(getSlice("abcdefghij", 0, 2) == "ab")
assert(getSlice("abcdefghij", 1, 2) == "cd")
assert(getSlice("abcdefghij", 3, 3) == "j ")
assert(getSlice("abcdefghij", 10, 1) == None)
assert(getSlice("abcdefghij", 11, 1) == None)
assert(setSlice("abcdefghij", 1, 2, "kl") == "abklefghij")
assert(setSlice("abc", 1, 2, "de") == "abde")
assert(setSlice("abc", 0, 2, "de") == "dec")
slice_len = 2
p = SingleLinePager(slice_len)
p.msg = "test"
assert(p.getNextSlice("test")[0] == "")
assert(p.getNextSlice("tast")[0] == "ta")
assert(p.getNextSlice("tast")[0] == "")
p.msg = ""
assert(p.getNextSlice("test")[0] == "te")
assert(p.msg == "te")
assert(p.getNextSlice("test")[0] == "st")
assert(p.msg == "test")
assert(p.getNextSlice("test")[0] == "")
assert(p.msg == "test")
assert(p.getNextSlice("tests")[0] == "s ")
slice_len = 2
rows = 2
cols = 4
p = MultiLinePager(slice_len, rows, cols)
assert(p.getNextSlice("")[0] == "")
assert(p.getNextSlice("yo")[0] == "yo")
assert(p.getNextSlice("yogi")[0] == "gi")
assert(p.getNextSlice("yugi")[0] == "yu")
assert(p.getNextSlice("yugi is a")[0] == "is")
assert(p.getNextSlice("yugi is a")[0] == " a")
assert(p.getNextSlice("yugi is a pussy")[0] == "pu")
assert(p.getNextSlice("yugi is a pussy")[0] == "s-")
assert(p.getNextSlice("yugi is a pussy")[0] == "sy")
p = MultiLinePager(slice_len, rows, cols)
assert(p.getNextSlice("yo")[0] == "yo")
assert(p.getNextSlice("yo")[0] == " ")
assert(p.getNextSlice("yo")[0] == " ")
assert(p.getNextSlice("yo")[0] == " ")
assert(p.getNextSlice("yo")[0] == "")
|