-def main() -> None:
- name = " ".join(sys.argv[1:])
- for possibility in COLOR_NAMES_TO_RGB:
- if name in possibility:
- f = fg(possibility)
- b = bg(possibility)
- _ = 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()}')
+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 = ''
+
+ @abstractmethod
+ def write(self, s: str):
+ pass
+
+ def __enter__(self):
+ self.saved_stdout = sys.stdout
+ sys.stdout = self
+ return self
+
+ def __exit__(self, *args) -> Literal[False]:
+ sys.stdout = self.saved_stdout
+ print(self.buf)
+ 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 = list(patterns)
+
+ @overrides
+ def write(self, s: str):
+ for pattern in self.patterns:
+ s = pattern[0].sub(pattern[1], s)
+ self.buf += s