Fancy text tables

This commit is contained in:
Odd Stråbø 2021-11-02 23:43:16 +01:00
parent c367d642d8
commit 2578fdca75
3 changed files with 179 additions and 0 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
*.py[ocd]

65
draw_memory_map.py Normal file
View file

@ -0,0 +1,65 @@
# -*- coding: utf-8 -*-
from typing import Iterable
from table_drawing import table
def memory_table(data: Iterable[int], start: int = 0, wordsize: int = 2):
data_iter = iter(data)
data_rows = []
position = start
try:
while True:
try:
row_id = position
row = []
for _ in range(16):
try:
cell = []
for _ in range(wordsize):
d = data_iter.__next__() & 0xFF
cell.append(d)
position += 1
finally:
if cell:
row.append(cell)
finally:
if row:
row_hex = [" ".join([f"{n:02X}" for n in cell]) for cell in row]
row_ascii = [
" ".join(
[
" " + chr(n) if chr(n).isprintable() else " "
for n in cell
]
)
for cell in row
]
row_head = f"{row_id:04X}"[:3] + "·"
data_rows.append([row_head] + row_hex)
if " ".join(row_ascii).strip():
data_rows.append([""] + row_ascii)
except StopIteration:
pass
headers = [""] + [
("" if wordsize % 2 else " ") + "···{:01X}".format(x) for x in range(16)
]
return table(
data_rows,
headers=headers,
justify="^",
header_interval=8 * 2,
)
data = list(range(256))
print(memory_table(data, wordsize=1))
#
# rows = [[f"{x:03X}·"] for x in range(32)]
#

113
table_drawing.py Normal file
View file

@ -0,0 +1,113 @@
# -*- coding: utf-8 -*-
from typing import Collection, Optional, Union
C_UL = ""
C_UR = ""
C_LL = ""
C_LR = ""
C_V = ""
C_VL = ""
C_VR = ""
C_H = ""
C_HD = ""
C_HU = ""
C_X = ""
def row(
fields: Collection[str],
sep: str = C_V,
start: str = C_V,
end: str = C_V,
) -> str:
res = []
for i, field in enumerate(fields):
if not i:
res.append(start)
else:
res.append(sep)
res.append(field)
res.append(end)
return "".join(res)
def table(
data: Collection[Collection[str]],
headers: Optional[Collection] = None,
header_interval: Optional[int] = None,
justify: Optional[Union[str, Collection[str]]] = None,
):
res = []
if not data:
return ""
columns = max([len(x) for x in data])
if headers:
columns = max(columns, len(headers))
if isinstance(justify, str):
justify = [justify] * columns
elif not justify:
justify = []
justify = list(justify) + ["^"] * (columns - len(justify))
colwidths = [0] * columns
if headers:
for i, col in enumerate(headers):
colwidths[i] = max(colwidths[i], len(col))
for data_row in data:
for i, col in enumerate(data_row):
colwidths[i] = max(colwidths[i], len(col))
def row_iterable():
if headers and not header_interval:
yield headers
for i, data_row in enumerate(data):
if header_interval and i % header_interval == 0:
yield headers
yield data_row
for i, data_row in enumerate(row_iterable()):
if not i:
res.append(
row([C_H * colw for colw in colwidths], start=C_UL, sep=C_HD, end=C_UR)
)
else:
res.append(
row([C_H * colw for colw in colwidths], start=C_VL, sep=C_X, end=C_VR)
)
padding = [""] * (columns - len(data_row))
padded_row = [
f"{cell:{justify[j]}{colwidths[j]}s}"
for j, cell in enumerate(list(data_row) + padding)
]
res.append(row(padded_row))
res.append(row([C_H * colw for colw in colwidths], start=C_LL, sep=C_HU, end=C_LR))
return "\n".join(res)
if __name__ == "__main__":
headers = [""] + ["···{:01X}".format(x) for x in range(16)]
data = [[f"{x:03X}·"] for x in range(32)]
print(
table(
data,
headers=headers,
justify=">",
header_interval=8,
)
)