Skip to content

Instantly share code, notes, and snippets.

@jwarner112
Last active July 3, 2021 06:23
Show Gist options
  • Save jwarner112/714e2245677c324b6cd5014a6d6c103e to your computer and use it in GitHub Desktop.
Save jwarner112/714e2245677c324b6cd5014a6d6c103e to your computer and use it in GitHub Desktop.
Unicode Textbox Utility
import textboxutil
LOREM_IPSUM = """
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque porttitor porttitor nulla id cursus. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Duis eu viverra enim, quis hendrerit neque. Curabitur pellentesque fringilla eros, sit amet varius ex pellentesque eu. Fusce cursus lacinia congue. Vivamus dignissim diam sed sagittis vestibulum. Curabitur a finibus lorem, et rhoncus arcu. Donec fringilla, justo non interdum mattis, lorem mauris egestas nulla, vel molestie quam mauris in turpis. Nullam rutrum sapien sit amet ipsum elementum commodo. Donec sed orci tellus. Sed id scelerisque odio. Vestibulum rhoncus nisi consequat finibus posuere. Quisque mollis porta magna feugiat consectetur. Donec sed feugiat nisl.
Phasellus commodo suscipit ante ac efficitur. Integer egestas vestibulum ornare. Curabitur luctus faucibus sodales. Aenean et nibh purus. Vestibulum tempor pulvinar imperdiet. Nullam egestas quam ac nisl hendrerit, et semper tellus maximus. In suscipit feugiat erat, vitae efficitur elit egestas commodo. Fusce tortor turpis, dictum sed euismod sed, euismod at nunc. Duis id nulla a elit dapibus rhoncus. Etiam ultrices tempor placerat. Proin ullamcorper et mi tristique ultrices. Donec quis iaculis ex.
Aliquam et lacinia nisi. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nullam placerat ligula ut risus porta, id finibus massa blandit. Nam sed tellus commodo, sodales nibh ornare, rutrum odio. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Mauris finibus diam arcu, ac cursus diam aliquam eu. Integer ac lorem ut mi dictum vehicula eget sit amet lorem. Vestibulum congue et mauris eu dignissim. Morbi quis nisi blandit lorem tempus finibus. Suspendisse at lacus in ante tincidunt maximus.
Etiam vitae accumsan nisl, ut porttitor risus. Cras est purus, pharetra eget blandit sed, faucibus sit amet massa. Sed id dui finibus, semper libero et, interdum massa. Maecenas varius, enim in dapibus commodo, dolor augue feugiat leo, quis sodales risus mi ut diam. Maecenas bibendum mi in fermentum pretium. Cras quis dictum sapien. Etiam tempor, sapien id bibendum ultricies, dui urna luctus turpis, eget ultrices mi odio eget magna. Curabitur vel facilisis mi, id euismod leo. Suspendisse a consectetur nunc.
Nam facilisis semper velit a laoreet. Curabitur ultricies sit amet libero quis congue. Donec quis lorem non nibh accumsan posuere. Phasellus nec nisl lorem. Vivamus ut eros vehicula, efficitur metus ut, efficitur neque. Maecenas ac dui facilisis, facilisis neque nec, efficitur velit. Duis id metus neque. Quisque facilisis lacinia sapien. Maecenas ultrices faucibus erat in lacinia.
In hac habitasse platea dictumst. Donec a consequat metus. Nam faucibus nibh et tristique bibendum. In sed fringilla risus, id tincidunt lacus. Aliquam erat volutpat. Sed aliquam tellus nisi, in varius ligula aliquet id. Duis in dolor ac tellus porttitor ornare. Vestibulum porttitor erat id est bibendum consequat. Aenean et sodales libero, ut feugiat leo. Proin porta lorem pretium massa porta, sit amet lacinia mi hendrerit.
"""
paragraphs = [p for p in LOREM_IPSUM.strip().split('\n') if p.strip() != ""]
print(boxify(p[2], 80, 78, title="Lorem Ipsum 1", style="double"))
# ╔══════════════════════════════════════════════════════════════════════════════╗
# ║ Lorem Ipsum 1 ║
# ╟┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄╢
# ║Aliquam et lacinia nisi. Orci varius natoque penatibus et magnis dis ║
# ║parturient montes, nascetur ridiculus mus. Nullam placerat ligula ut risus ║
# ║porta, id finibus massa blandit. Nam sed tellus commodo, sodales nibh ornare, ║
# ║rutrum odio. Pellentesque habitant morbi tristique senectus et netus et ║
# ║malesuada fames ac turpis egestas. Mauris finibus diam arcu, ac cursus diam ║
# ║aliquam eu. Integer ac lorem ut mi dictum vehicula eget sit amet lorem. ║
# ║Vestibulum congue et mauris eu dignissim. Morbi quis nisi blandit lorem tempus║
# ║finibus. Suspendisse at lacus in ante tincidunt maximus. ║
# ╚══════════════════════════════════════════════════════════════════════════════╝
print(boxify(p[4], 80, 70, title="Lorem Ipsum 2", style="light"))
# ┌──────────────────────────────────────────────────────────────────────────────┐
# │ Lorem Ipsum 2 │
# ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┤
# │ Nam facilisis semper velit a laoreet. Curabitur ultricies sit amet │
# │ libero quis congue. Donec quis lorem non nibh accumsan posuere. │
# │ Phasellus nec nisl lorem. Vivamus ut eros vehicula, efficitur metus │
# │ ut, efficitur neque. Maecenas ac dui facilisis, facilisis neque nec, │
# │ efficitur velit. Duis id metus neque. Quisque facilisis lacinia │
# │ sapien. Maecenas ultrices faucibus erat in lacinia. │
# └──────────────────────────────────────────────────────────────────────────────┘
print(boxify(p[5], 80, 90, title="Lorem Ipsum 3", style="light"))
# ---------------------------------------------------------------------------
# AssertionError Traceback (most recent call last)
# <ipython-input-10-cf4ac7aad2eb> in <module>
# ----> 1 print(boxify(p[5], 80, 90, title="Lorem Ipsum 3", style="light"))
#
# ~/Documents/textutil.py in boxify(message, box_width, text_width, title, style)
# 49 if any(aligned_title_block):
# 50 for line in aligned_title_block:
# ---> 51 rows.append(f"{box_chars[1]}{line}{box_chars[1]}")
# 52 rows.append(f"{box_chars[7]}{box_chars[2]*line_width}{box_chars[8]}")
# 53 for line in aligned_msg_block:
#
# AssertionError: text rows too wide to fit in box
from textwrap import wrap, dedent
BOX_CHARS = {
# 0 1 2 3 4 5 6 7 8
"light": ['─', '│', '┄', '┌', '┐', '└', '┘', '├', '┤'],
"heavy": ['━', '┃', '┅', '┏', '┓', '┗', '┛', '┣', '┫'],
"double": ['═', '║', '┄', '╔', '╗', '╚', '╝', '╟', '╢'],
}
def block(message, width, alignment="left"):
assert width > 0, "width must be a positive number"
assert alignment in ["left", "center", "right"]
wrapped = wrap(message, width)
if alignment == "left":
aligned = [l.ljust(width) for l in wrapped]
elif alignment == "right":
aligned = [l.rjust(width) for l in wrapped]
else:
aligned = [l.center(width) for l in wrapped]
return aligned
def boxify(message, box_width, text_width, title="", style="light"):
assert box_width > 0, "box width must be a positive number"
assert text_width > 0, "line length must be a positive number"
line_width = box_width - 2
assert line_width >= text_width, "text rows too wide to fit in box"
assert style in ["light", "heavy", "double"], "inapplicable box style"
title_block = None
aligned_title_block = None
if title != "":
title_block = block(title, text_width, alignment="center")
aligned_title_block = [l.center(line_width) for l in title_block]
msg_block = block(message, text_width)
aligned_msg_block = [l.center(line_width) for l in msg_block]
box_chars = BOX_CHARS[style]
rows = []
rows.append(f"{box_chars[3]}{box_chars[0]*line_width}{box_chars[4]}") # top
if aligned_title_block is not None and any(aligned_title_block):
for line in aligned_title_block:
rows.append(f"{box_chars[1]}{line}{box_chars[1]}")
rows.append(f"{box_chars[7]}{box_chars[2]*line_width}{box_chars[8]}")
for line in aligned_msg_block:
rows.append(f"{box_chars[1]}{line}{box_chars[1]}")
rows.append(f"{box_chars[5]}{box_chars[0]*line_width}{box_chars[6]}") # bot
return "\n".join(rows)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment