#!/usr/bin/env python3
+from abc import abstractmethod
import difflib
+import io
import logging
+import re
import sys
-from typing import Dict, Optional, Tuple
+from typing import Any, Callable, Dict, Iterable, Optional, Tuple
-import string_utils
+from overrides import overrides
+
+import logging_utils
logger = logging.getLogger(__name__)
def italics() -> str:
- return "\e[3m"
+ return italic()
def underline() -> str:
def strike_through() -> str:
- return "\e[9m"
+ return strikethrough()
def is_16color(num: int) -> bool:
return rgb
+@logging_utils.squelch_repeated_log_messages(1)
def fg(name: Optional[str] = "",
red: Optional[int] = None,
green: Optional[int] = None,
*,
force_16color: bool = False,
force_216color: bool = False) -> str:
+ import string_utils
+
+ if name is not None and name == 'reset':
+ return '\033[39m'
+
if name is not None and string_utils.is_full_string(name):
rgb = _find_color_by_name(name)
return fg(
red: Optional[int] = None,
green: Optional[int] = None,
blue: Optional[int] = None) -> Tuple[int, int, int]:
+ import string_utils
+
if name is not None and string_utils.is_full_string(name):
rgb = _find_color_by_name(name)
else:
*,
force_16color: bool = False,
force_216color: bool = False) -> str:
+ import string_utils
+
+ if name is not None and name == 'reset':
+ return '\033[49m'
+
if name is not None and string_utils.is_full_string(name):
rgb = _find_color_by_name(name)
return bg(
return bg_24bit(red, green, blue)
-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):
+ def __init__(self):
+ self.saved_stdout: Optional[io.TextIOBase] = None
+ self.buf = ''
+
+ @abstractmethod
+ def write(self, s: str):
+ pass
+
+ def __enter__(self) -> None:
+ self.saved_stdout = sys.stdout
+ sys.stdout = self
+ return None
+
+ def __exit__(self, *args) -> bool:
+ sys.stdout = self.saved_stdout
+ print(self.buf)
+ return None
+
+
+class ProgrammableColorizer(StdoutInterceptor):
+ def __init__(self, patterns: Iterable[Tuple[re.Pattern, Callable[[Any, re.Pattern], str]]]):
+ super().__init__()
+ self.patterns = [_ for _ in patterns]
+
+ @overrides
+ def write(self, s: str):
+ for pattern in self.patterns:
+ s = pattern[0].sub(pattern[1], s)
+ self.buf += s
if __name__ == '__main__':
+ 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()}')
main()