X-Git-Url: https://wannabe.guru.org/gitweb/?a=blobdiff_plain;f=ansi.py;h=dee52424fefa6bd80daccc3d8830c0a707e12b6a;hb=532df2c5b57c7517dfb3dddd8c1358fbadf8baf3;hp=6897291ba252f91c866b967cd18e0aa13f0f151d;hpb=971d4ba141459f78d10d5770b9459d1ead7d49a0;p=python_utils.git diff --git a/ansi.py b/ansi.py index 6897291..dee5242 100755 --- a/ansi.py +++ b/ansi.py @@ -1,16 +1,26 @@ #!/usr/bin/env python3 -from abc import abstractmethod +# © Copyright 2021-2022, Scott Gasch + +"""A bunch of color names mapped into RGB tuples and some methods for +setting the text color, background, etc... using ANSI escape +sequences. + +""" + +import contextlib import difflib import io import logging import re import sys -from typing import Any, Callable, Dict, Iterable, Optional, Tuple +from abc import abstractmethod +from typing import Any, Callable, Dict, Iterable, Literal, Optional, Tuple from overrides import overrides import logging_utils +import string_utils logger = logging.getLogger(__name__) @@ -1641,7 +1651,7 @@ def strike_through() -> str: def is_16color(num: int) -> bool: - return num == 255 or num == 128 + return num in (255, 128) def is_216color(num: int) -> bool: @@ -1751,8 +1761,6 @@ def fg( b'G1szODs1OzIxbQ==\\n' """ - import string_utils - if name is not None and name == 'reset': return '\033[39m' @@ -1776,9 +1784,7 @@ def fg( if (is_16color(red) and is_16color(green) and is_16color(blue)) or force_16color: logger.debug("Using 16-color strategy") return fg_16color(red, green, blue) - if ( - is_216color(red) and is_216color(green) and is_216color(blue) - ) or force_216color: + if (is_216color(red) and is_216color(green) and is_216color(blue)) or force_216color: logger.debug("Using 216-color strategy") return fg_216color(red, green, blue) logger.debug("Using 24-bit color strategy") @@ -1812,8 +1818,6 @@ def pick_contrasting_color( (0, 0, 0) """ - import string_utils - if name is not None and string_utils.is_full_string(name): rgb = _find_color_by_name(name) else: @@ -1834,10 +1838,11 @@ def guess_name(name: str) -> str: max_ratio = r best_guess = possibility assert best_guess is not None - logger.debug(f"Best guess at color name is {best_guess}") + logger.debug("Best guess at color name is %s", best_guess) return best_guess +@logging_utils.squelch_repeated_log_messages(1) def bg( name: Optional[str] = "", red: Optional[int] = None, @@ -1855,8 +1860,6 @@ def bg( b'G1s0ODs1OzE5Nm0=\\n' """ - import string_utils - if name is not None and name == 'reset': return '\033[49m' @@ -1879,17 +1882,18 @@ def bg( if (is_16color(red) and is_16color(green) and is_16color(blue)) or force_16color: logger.debug("Using 16-color strategy") return bg_16color(red, green, blue) - if ( - is_216color(red) and is_216color(green) and is_216color(blue) - ) or force_216color: + if (is_216color(red) and is_216color(green) and is_216color(blue)) or force_216color: logger.debug("Using 216-color strategy") return bg_216color(red, green, blue) logger.debug("Using 24-bit color strategy") return bg_24bit(red, green, blue) -class StdoutInterceptor(io.TextIOBase): +class StdoutInterceptor(io.TextIOBase, contextlib.AbstractContextManager): + """An interceptor for data written to stdout. Use as a context.""" + def __init__(self): + super().__init__() self.saved_stdout: io.TextIO = None self.buf = '' @@ -1902,19 +1906,24 @@ class StdoutInterceptor(io.TextIOBase): sys.stdout = self return self - def __exit__(self, *args) -> Optional[bool]: + def __exit__(self, *args) -> Literal[False]: sys.stdout = self.saved_stdout print(self.buf) - return None + return False class ProgrammableColorizer(StdoutInterceptor): + """A colorizing interceptor; pass it re.Patterns -> methods that do + something (usually add color to) the match. + + """ + def __init__( self, patterns: Iterable[Tuple[re.Pattern, Callable[[Any, re.Pattern], str]]], ): super().__init__() - self.patterns = [_ for _ in patterns] + self.patterns = list(patterns) @overrides def write(self, s: str): @@ -1938,9 +1947,6 @@ if __name__ == '__main__': _ = pick_contrasting_color(possibility) xf = fg(None, _[0], _[1], _[2]) xb = bg(None, _[0], _[1], _[2]) - print( - f'{f}{xb}{possibility}{reset()}\t\t\t' - f'{b}{xf}{possibility}{reset()}' - ) + print(f'{f}{xb}{possibility}{reset()}\t\t\t' f'{b}{xf}{possibility}{reset()}') main()