summaryrefslogtreecommitdiffstats
path: root/Scripts/paging.py
diff options
context:
space:
mode:
Diffstat (limited to 'Scripts/paging.py')
-rw-r--r--Scripts/paging.py121
1 files changed, 121 insertions, 0 deletions
diff --git a/Scripts/paging.py b/Scripts/paging.py
new file mode 100644
index 0000000..8cde278
--- /dev/null
+++ b/Scripts/paging.py
@@ -0,0 +1,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] == "")
+