Fancy text tables
This commit is contained in:
parent
c367d642d8
commit
2578fdca75
3 changed files with 179 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
*.py[ocd]
|
65
draw_memory_map.py
Normal file
65
draw_memory_map.py
Normal 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
113
table_drawing.py
Normal 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,
|
||||
)
|
||||
)
|
Loading…
Reference in a new issue