tuxbot-bot/tuxbot/core/utils/functions/cli.py

90 lines
2.7 KiB
Python

import codecs
import itertools
import sys
def bordered(*columns: dict) -> str:
"""
credits to https://github.com/Cog-Creators/Red-DiscordBot/blob/V3/develop/redbot/core/utils/chat_formatting.py
Get two blocks of text in a borders.
Note
----
This will only work with a monospaced font.
Parameters
----------
*columns : `sequence` of `str`
The columns of text, each being a list of lines in that column.
Returns
-------
str
The bordered text.
"""
encoder = codecs.getencoder(sys.stdout.encoding)
try:
encoder("┌┐└┘─│") # border symbols
except UnicodeEncodeError:
ascii_border = True
else:
ascii_border = False
borders = {
"TL": "+" if ascii_border else "", # Top-left
"TR": "+" if ascii_border else "", # Top-right
"BL": "+" if ascii_border else "", # Bottom-left
"BR": "+" if ascii_border else "", # Bottom-right
"HZ": "-" if ascii_border else "", # Horizontal
"VT": "|" if ascii_border else "", # Vertical
}
sep = " " * 4 # Separator between boxes
widths = tuple(
max(len(row) for row in column.get("rows")) + 9 for column in columns
) # width of each col
cols_done = [False] * len(columns) # whether or not each column is done
lines = [""]
for i, column in enumerate(columns):
lines[0] += (
"{TL}"
+ "{HZ}"
+ column.get("title")
+ "{HZ}" * (widths[i] - len(column.get("title")) - 1)
+ "{TR}"
+ sep
)
for line in itertools.zip_longest(*[column.get("rows") for column in columns]):
row = []
for colidx, column in enumerate(line):
width = widths[colidx]
done = cols_done[colidx]
if column is None:
if not done:
# bottom border of column
column = "{HZ}" * width
row.append("{BL}" + column + "{BR}")
cols_done[colidx] = True # mark column as done
else:
# leave empty
row.append(" " * (width + 2))
else:
column += " " * (width - len(column)) # append padded spaces
row.append("{VT}" + column + "{VT}")
lines.append(sep.join(row))
final_row = []
for width, done in zip(widths, cols_done):
if not done:
final_row.append("{BL}" + "{HZ}" * width + "{BR}")
else:
final_row.append(" " * (width + 2))
lines.append(sep.join(final_row))
return "\n".join(lines).format(**borders)