3 """Utilities for dealing with "text"."""
7 from typing import List, NamedTuple
9 from ansi import fg, reset
13 class RowsColumns(NamedTuple):
18 def get_console_rows_columns() -> RowsColumns:
19 rows, columns = exec_utils.cmd("stty size").split()
20 return RowsColumns(int(rows), int(columns))
28 fgcolor=fg("school bus yellow"),
33 percent = current / total
34 ret = "\r" if redraw else "\n"
41 right_end = right_end)
54 fgcolor=fg("school bus yellow"),
58 if percentage < 0.0 or percentage > 1.0:
59 raise ValueError(percentage)
61 text = f"{percentage*100.0:2.1f}%"
64 whole_width = math.floor(percentage * width)
65 if whole_width == width:
69 remainder_width = (percentage * width) % 1
70 part_width = math.floor(remainder_width * 8)
71 part_char = [" ", "▏", "▎", "▍", "▌", "▋", "▊", "▉"][part_width]
75 "█" * whole_width + part_char +
76 " " * (width - whole_width - 1) +
82 def distribute_strings(
89 subwidth = math.floor(width / len(strings))
91 for string in strings:
92 string = justify_string(
93 string, width=subwidth, alignment=alignment, padding=padding
99 def justify_string_by_chunk(
100 string: str, width: int = 80, padding: str = " "
103 first, *rest, last = string.split()
104 w = width - (len(first) + 1 + len(last) + 1)
106 first + padding + distribute_strings(rest, width=w, padding=padding)
108 while len(retval) + len(last) < width:
115 string: str, *, width: int = 80, alignment: str = "c", padding: str = " "
117 alignment = alignment[0]
119 while len(string) < width:
122 elif alignment == "r":
123 string = padding + string
124 elif alignment == "j":
125 return justify_string_by_chunk(
130 elif alignment == "c":
131 if len(string) % 2 == 0:
134 string = padding + string
140 def justify_text(text: str, *, width: int = 80, alignment: str = "c") -> str:
144 for word in text.split():
145 if len(line) + len(word) > width:
147 line = justify_string(line, width=width, alignment=alignment)
148 retval = retval + "\n" + line
150 line = line + " " + word
152 retval += "\n" + line[1:]