From cf7da1843c45a4c2df7a749f7886a2d2ba0ee92a Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Mon, 15 Apr 2024 19:25:40 +0200 Subject: Adding upstream version 7.2.6. Signed-off-by: Daniel Baumann --- sphinx/util/console.py | 129 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 sphinx/util/console.py (limited to 'sphinx/util/console.py') diff --git a/sphinx/util/console.py b/sphinx/util/console.py new file mode 100644 index 0000000..0fc9450 --- /dev/null +++ b/sphinx/util/console.py @@ -0,0 +1,129 @@ +"""Format colored console output.""" + +from __future__ import annotations + +import os +import re +import shutil +import sys + +try: + # check if colorama is installed to support color on Windows + import colorama +except ImportError: + colorama = None + + +_ansi_re: re.Pattern[str] = re.compile('\x1b\\[(\\d\\d;){0,2}\\d\\dm') +codes: dict[str, str] = {} + + +def terminal_safe(s: str) -> str: + """Safely encode a string for printing to the terminal.""" + return s.encode('ascii', 'backslashreplace').decode('ascii') + + +def get_terminal_width() -> int: + """Return the width of the terminal in columns.""" + return shutil.get_terminal_size().columns - 1 + + +_tw: int = get_terminal_width() + + +def term_width_line(text: str) -> str: + if not codes: + # if no coloring, don't output fancy backspaces + return text + '\n' + else: + # codes are not displayed, this must be taken into account + return text.ljust(_tw + len(text) - len(_ansi_re.sub('', text))) + '\r' + + +def color_terminal() -> bool: + if 'NO_COLOR' in os.environ: + return False + if sys.platform == 'win32' and colorama is not None: + colorama.init() + return True + if 'FORCE_COLOR' in os.environ: + return True + if not hasattr(sys.stdout, 'isatty'): + return False + if not sys.stdout.isatty(): + return False + if 'COLORTERM' in os.environ: + return True + term = os.environ.get('TERM', 'dumb').lower() + if term in ('xterm', 'linux') or 'color' in term: + return True + return False + + +def nocolor() -> None: + if sys.platform == 'win32' and colorama is not None: + colorama.deinit() + codes.clear() + + +def coloron() -> None: + codes.update(_orig_codes) + + +def colorize(name: str, text: str, input_mode: bool = False) -> str: + def escseq(name: str) -> str: + # Wrap escape sequence with ``\1`` and ``\2`` to let readline know + # it is non-printable characters + # ref: https://tiswww.case.edu/php/chet/readline/readline.html + # + # Note: This hack does not work well in Windows (see #5059) + escape = codes.get(name, '') + if input_mode and escape and sys.platform != 'win32': + return '\1' + escape + '\2' + else: + return escape + + return escseq(name) + text + escseq('reset') + + +def strip_colors(s: str) -> str: + return re.compile('\x1b.*?m').sub('', s) + + +def create_color_func(name: str) -> None: + def inner(text: str) -> str: + return colorize(name, text) + globals()[name] = inner + + +_attrs = { + 'reset': '39;49;00m', + 'bold': '01m', + 'faint': '02m', + 'standout': '03m', + 'underline': '04m', + 'blink': '05m', +} + +for _name, _value in _attrs.items(): + codes[_name] = '\x1b[' + _value + +_colors = [ + ('black', 'darkgray'), + ('darkred', 'red'), + ('darkgreen', 'green'), + ('brown', 'yellow'), + ('darkblue', 'blue'), + ('purple', 'fuchsia'), + ('turquoise', 'teal'), + ('lightgray', 'white'), +] + +for i, (dark, light) in enumerate(_colors, 30): + codes[dark] = '\x1b[%im' % i + codes[light] = '\x1b[%im' % (i + 60) + +_orig_codes = codes.copy() + +for _name in codes: + create_color_func(_name) -- cgit v1.2.3