Ugh, a bunch of things. @overrides. --lmodule. Chromecasts. etc...
[python_utils.git] / text_utils.py
index 1a8fa18499193084db27f4be02e8a985f877fe1a..36cfe2fd720d9e0cb479992495a70d66161ae132 100644 (file)
@@ -16,6 +16,8 @@ class RowsColumns(NamedTuple):
 
 
 def get_console_rows_columns() -> RowsColumns:
+    """Returns the number of rows/columns on the current console."""
+
     from exec_utils import cmd
     rows, columns = cmd("stty size").split()
     return RowsColumns(int(rows), int(columns))
@@ -31,6 +33,8 @@ def progress_graph(
     right_end="]",
     redraw=True,
 ) -> None:
+    """Draws a progress graph."""
+
     percent = current / total
     ret = "\r" if redraw else "\n"
     bar = bar_graph(
@@ -53,9 +57,17 @@ def bar_graph(
     include_text=True,
     width=70,
     fgcolor=fg("school bus yellow"),
+    reset=reset(),
     left_end="[",
     right_end="]",
 ) -> None:
+    """Returns a string containing a bar graph.
+
+    >>> bar_graph(0.5, fgcolor='', reset='')
+    '[███████████████████████████████████                                   ] 50.0%'
+
+    """
+
     if percentage < 0.0 or percentage > 1.0:
         raise ValueError(percentage)
     if include_text:
@@ -75,7 +87,7 @@ def bar_graph(
         fgcolor +
         "█" * whole_width + part_char +
         " " * (width - whole_width - 1) +
-        reset() +
+        reset +
         right_end + " " +
         text)
 
@@ -87,6 +99,17 @@ def distribute_strings(
     alignment: str = "c",
     padding: str = " ",
 ) -> str:
+    """
+    Distributes strings into a line with a particular justification.
+
+    >>> distribute_strings(['this', 'is', 'a', 'test'], width=40)
+    '   this       is         a       test   '
+    >>> distribute_strings(['this', 'is', 'a', 'test'], width=40, alignment='l')
+    'this      is        a         test      '
+    >>> distribute_strings(['this', 'is', 'a', 'test'], width=40, alignment='r')
+    '      this        is         a      test'
+
+    """
     subwidth = math.floor(width / len(strings))
     retval = ""
     for string in strings:
@@ -100,6 +123,15 @@ def distribute_strings(
 def justify_string_by_chunk(
     string: str, width: int = 80, padding: str = " "
 ) -> str:
+    """
+    Justifies a string.
+
+    >>> justify_string_by_chunk("This is a test", 40)
+    'This       is              a        test'
+    >>> justify_string_by_chunk("This is a test", 20)
+    'This  is    a   test'
+
+    """
     padding = padding[0]
     first, *rest, last = string.split()
     w = width - (len(first) + 1 + len(last) + 1)
@@ -115,6 +147,18 @@ def justify_string_by_chunk(
 def justify_string(
     string: str, *, width: int = 80, alignment: str = "c", padding: str = " "
 ) -> str:
+    """Justify a string.
+
+    >>> justify_string('This is another test', width=40, alignment='c')
+    '          This is another test          '
+    >>> justify_string('This is another test', width=40, alignment='l')
+    'This is another test                    '
+    >>> justify_string('This is another test', width=40, alignment='r')
+    '                    This is another test'
+    >>> justify_string('This is another test', width=40, alignment='j')
+    'This       is           another     test'
+
+    """
     alignment = alignment[0]
     padding = padding[0]
     while len(string) < width:
@@ -139,7 +183,13 @@ def justify_string(
 
 
 def justify_text(text: str, *, width: int = 80, alignment: str = "c") -> str:
-    print("-" * width)
+    """
+    Justifies text.
+
+    >>> justify_text('This is a test of the emergency broadcast system.  This is only a test.',
+    ...              width=40, alignment='j')  #doctest: +NORMALIZE_WHITESPACE
+    'This  is    a  test  of   the  emergency\\nbroadcast system. This is only a test.'
+    """
     retval = ""
     line = ""
     for word in text.split():
@@ -169,7 +219,20 @@ def generate_padded_columns(text: List[str]) -> str:
         yield out
 
 
-class Indenter:
+def wrap_string(text: str, n: int) -> str:
+    chunks = text.split()
+    out = ''
+    width = 0
+    for chunk in chunks:
+        if width + len(chunk) > n:
+            out += '\n'
+            width = 0
+        out += chunk + ' '
+        width += len(chunk) + 1
+    return out
+
+
+class Indenter(object):
     """
     with Indenter(pad_count = 8) as i:
         i.print('test')
@@ -203,3 +266,30 @@ class Indenter:
         import string_utils
         text = string_utils.sprintf(*arg, **kwargs)
         print(self.pad_prefix + self.padding * self.level + text, end='')
+
+
+def header(title: str, *, width: int = 80, color: str = ''):
+    """
+    Returns a nice header line with a title.
+
+    >>> header('title', width=60, color='')
+    '----[ title ]-----------------------------------------------'
+
+    """
+    w = width
+    w -= (len(title) + 4)
+    if w >= 4:
+        left = 4 * '-'
+        right = (w - 4) * '-'
+        if color != '' and color is not None:
+            r = reset()
+        else:
+            r = ''
+        return f'{left}[ {color}{title}{r} ]{right}'
+    else:
+        return ''
+
+
+if __name__ == '__main__':
+    import doctest
+    doctest.testmod()