diff options
author | shadchin <shadchin@yandex-team.ru> | 2022-02-10 16:44:30 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:44:30 +0300 |
commit | 2598ef1d0aee359b4b6d5fdd1758916d5907d04f (patch) | |
tree | 012bb94d777798f1f56ac1cec429509766d05181 /contrib/python/prompt-toolkit/py3/prompt_toolkit/formatted_text/ansi.py | |
parent | 6751af0b0c1b952fede40b19b71da8025b5d8bcf (diff) | |
download | ydb-2598ef1d0aee359b4b6d5fdd1758916d5907d04f.tar.gz |
Restoring authorship annotation for <shadchin@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/python/prompt-toolkit/py3/prompt_toolkit/formatted_text/ansi.py')
-rw-r--r-- | contrib/python/prompt-toolkit/py3/prompt_toolkit/formatted_text/ansi.py | 506 |
1 files changed, 253 insertions, 253 deletions
diff --git a/contrib/python/prompt-toolkit/py3/prompt_toolkit/formatted_text/ansi.py b/contrib/python/prompt-toolkit/py3/prompt_toolkit/formatted_text/ansi.py index 3d57063357..2d8c5dac95 100644 --- a/contrib/python/prompt-toolkit/py3/prompt_toolkit/formatted_text/ansi.py +++ b/contrib/python/prompt-toolkit/py3/prompt_toolkit/formatted_text/ansi.py @@ -1,117 +1,117 @@ -from typing import Generator, List, Optional - -from prompt_toolkit.output.vt100 import BG_ANSI_COLORS, FG_ANSI_COLORS -from prompt_toolkit.output.vt100 import _256_colors as _256_colors_table - -from .base import StyleAndTextTuples - -__all__ = [ - "ANSI", - "ansi_escape", -] - - -class ANSI: - """ - ANSI formatted text. - Take something ANSI escaped text, for use as a formatted string. E.g. - - :: - - ANSI('\\x1b[31mhello \\x1b[32mworld') - - Characters between ``\\001`` and ``\\002`` are supposed to have a zero width - when printed, but these are literally sent to the terminal output. This can - be used for instance, for inserting Final Term prompt commands. They will - be translated into a prompt_toolkit '[ZeroWidthEscape]' fragment. - """ - - def __init__(self, value: str) -> None: - self.value = value - self._formatted_text: StyleAndTextTuples = [] - - # Default style attributes. - self._color: Optional[str] = None - self._bgcolor: Optional[str] = None - self._bold = False - self._underline = False - self._strike = False - self._italic = False - self._blink = False - self._reverse = False - self._hidden = False - - # Process received text. - parser = self._parse_corot() - parser.send(None) # type: ignore - for c in value: - parser.send(c) - - def _parse_corot(self) -> Generator[None, str, None]: - """ - Coroutine that parses the ANSI escape sequences. - """ - style = "" - formatted_text = self._formatted_text - - while True: +from typing import Generator, List, Optional + +from prompt_toolkit.output.vt100 import BG_ANSI_COLORS, FG_ANSI_COLORS +from prompt_toolkit.output.vt100 import _256_colors as _256_colors_table + +from .base import StyleAndTextTuples + +__all__ = [ + "ANSI", + "ansi_escape", +] + + +class ANSI: + """ + ANSI formatted text. + Take something ANSI escaped text, for use as a formatted string. E.g. + + :: + + ANSI('\\x1b[31mhello \\x1b[32mworld') + + Characters between ``\\001`` and ``\\002`` are supposed to have a zero width + when printed, but these are literally sent to the terminal output. This can + be used for instance, for inserting Final Term prompt commands. They will + be translated into a prompt_toolkit '[ZeroWidthEscape]' fragment. + """ + + def __init__(self, value: str) -> None: + self.value = value + self._formatted_text: StyleAndTextTuples = [] + + # Default style attributes. + self._color: Optional[str] = None + self._bgcolor: Optional[str] = None + self._bold = False + self._underline = False + self._strike = False + self._italic = False + self._blink = False + self._reverse = False + self._hidden = False + + # Process received text. + parser = self._parse_corot() + parser.send(None) # type: ignore + for c in value: + parser.send(c) + + def _parse_corot(self) -> Generator[None, str, None]: + """ + Coroutine that parses the ANSI escape sequences. + """ + style = "" + formatted_text = self._formatted_text + + while True: # NOTE: CSI is a special token within a stream of characters that # introduces an ANSI control sequence used to set the # style attributes of the following characters. - csi = False - - c = yield - - # Everything between \001 and \002 should become a ZeroWidthEscape. - if c == "\001": - escaped_text = "" - while c != "\002": - c = yield - if c == "\002": - formatted_text.append(("[ZeroWidthEscape]", escaped_text)) - c = yield - break - else: - escaped_text += c - + csi = False + + c = yield + + # Everything between \001 and \002 should become a ZeroWidthEscape. + if c == "\001": + escaped_text = "" + while c != "\002": + c = yield + if c == "\002": + formatted_text.append(("[ZeroWidthEscape]", escaped_text)) + c = yield + break + else: + escaped_text += c + # Check for CSI - if c == "\x1b": - # Start of color escape sequence. - square_bracket = yield - if square_bracket == "[": - csi = True - else: - continue - elif c == "\x9b": - csi = True - - if csi: - # Got a CSI sequence. Color codes are following. - current = "" - params = [] - - while True: - char = yield + if c == "\x1b": + # Start of color escape sequence. + square_bracket = yield + if square_bracket == "[": + csi = True + else: + continue + elif c == "\x9b": + csi = True + + if csi: + # Got a CSI sequence. Color codes are following. + current = "" + params = [] + + while True: + char = yield # Construct number - if char.isdigit(): - current += char + if char.isdigit(): + current += char # Eval number - else: + else: # Limit and save number value - params.append(min(int(current or 0), 9999)) + params.append(min(int(current or 0), 9999)) # Get delimiter token if present - if char == ";": - current = "" + if char == ";": + current = "" # Check and evaluate color codes - elif char == "m": - # Set attributes and token. - self._select_graphic_rendition(params) - style = self._create_style_string() - break + elif char == "m": + # Set attributes and token. + self._select_graphic_rendition(params) + style = self._create_style_string() + break # Check and evaluate cursor forward elif char == "C": @@ -120,163 +120,163 @@ class ANSI: formatted_text.append((style, " ")) break - else: - # Ignore unsupported sequence. - break - else: - # Add current character. - # NOTE: At this point, we could merge the current character - # into the previous tuple if the style did not change, - # however, it's not worth the effort given that it will - # be "Exploded" once again when it's rendered to the - # output. - formatted_text.append((style, c)) - - def _select_graphic_rendition(self, attrs: List[int]) -> None: - """ - Taken a list of graphics attributes and apply changes. - """ - if not attrs: - attrs = [0] - else: - attrs = list(attrs[::-1]) - - while attrs: - attr = attrs.pop() - - if attr in _fg_colors: - self._color = _fg_colors[attr] - elif attr in _bg_colors: - self._bgcolor = _bg_colors[attr] - elif attr == 1: - self._bold = True + else: + # Ignore unsupported sequence. + break + else: + # Add current character. + # NOTE: At this point, we could merge the current character + # into the previous tuple if the style did not change, + # however, it's not worth the effort given that it will + # be "Exploded" once again when it's rendered to the + # output. + formatted_text.append((style, c)) + + def _select_graphic_rendition(self, attrs: List[int]) -> None: + """ + Taken a list of graphics attributes and apply changes. + """ + if not attrs: + attrs = [0] + else: + attrs = list(attrs[::-1]) + + while attrs: + attr = attrs.pop() + + if attr in _fg_colors: + self._color = _fg_colors[attr] + elif attr in _bg_colors: + self._bgcolor = _bg_colors[attr] + elif attr == 1: + self._bold = True # elif attr == 2: # self._faint = True - elif attr == 3: - self._italic = True - elif attr == 4: - self._underline = True - elif attr == 5: + elif attr == 3: + self._italic = True + elif attr == 4: + self._underline = True + elif attr == 5: self._blink = True # Slow blink - elif attr == 6: + elif attr == 6: self._blink = True # Fast blink - elif attr == 7: - self._reverse = True - elif attr == 8: - self._hidden = True - elif attr == 9: - self._strike = True - elif attr == 22: + elif attr == 7: + self._reverse = True + elif attr == 8: + self._hidden = True + elif attr == 9: + self._strike = True + elif attr == 22: self._bold = False # Normal intensity - elif attr == 23: - self._italic = False - elif attr == 24: - self._underline = False - elif attr == 25: - self._blink = False - elif attr == 27: - self._reverse = False + elif attr == 23: + self._italic = False + elif attr == 24: + self._underline = False + elif attr == 25: + self._blink = False + elif attr == 27: + self._reverse = False elif attr == 28: self._hidden = False - elif attr == 29: - self._strike = False - elif not attr: + elif attr == 29: + self._strike = False + elif not attr: # Reset all style attributes - self._color = None - self._bgcolor = None - self._bold = False - self._underline = False - self._strike = False - self._italic = False - self._blink = False - self._reverse = False - self._hidden = False - - elif attr in (38, 48) and len(attrs) > 1: - n = attrs.pop() - - # 256 colors. - if n == 5 and len(attrs) >= 1: - if attr == 38: - m = attrs.pop() - self._color = _256_colors.get(m) - elif attr == 48: - m = attrs.pop() - self._bgcolor = _256_colors.get(m) - - # True colors. - if n == 2 and len(attrs) >= 3: - try: - color_str = "#%02x%02x%02x" % ( - attrs.pop(), - attrs.pop(), - attrs.pop(), - ) - except IndexError: - pass - else: - if attr == 38: - self._color = color_str - elif attr == 48: - self._bgcolor = color_str - - def _create_style_string(self) -> str: - """ - Turn current style flags into a string for usage in a formatted text. - """ - result = [] - if self._color: - result.append(self._color) - if self._bgcolor: - result.append("bg:" + self._bgcolor) - if self._bold: - result.append("bold") - if self._underline: - result.append("underline") - if self._strike: - result.append("strike") - if self._italic: - result.append("italic") - if self._blink: - result.append("blink") - if self._reverse: - result.append("reverse") - if self._hidden: - result.append("hidden") - - return " ".join(result) - - def __repr__(self) -> str: - return "ANSI(%r)" % (self.value,) - - def __pt_formatted_text__(self) -> StyleAndTextTuples: - return self._formatted_text - - def format(self, *args: str, **kwargs: str) -> "ANSI": - """ - Like `str.format`, but make sure that the arguments are properly - escaped. (No ANSI escapes can be injected.) - """ - # Escape all the arguments. - args = tuple(ansi_escape(a) for a in args) - kwargs = {k: ansi_escape(v) for k, v in kwargs.items()} - - return ANSI(self.value.format(*args, **kwargs)) - - -# Mapping of the ANSI color codes to their names. -_fg_colors = {v: k for k, v in FG_ANSI_COLORS.items()} -_bg_colors = {v: k for k, v in BG_ANSI_COLORS.items()} - -# Mapping of the escape codes for 256colors to their 'ffffff' value. -_256_colors = {} - -for i, (r, g, b) in enumerate(_256_colors_table.colors): - _256_colors[i] = "#%02x%02x%02x" % (r, g, b) - - -def ansi_escape(text: str) -> str: - """ - Replace characters with a special meaning. - """ - return text.replace("\x1b", "?").replace("\b", "?") + self._color = None + self._bgcolor = None + self._bold = False + self._underline = False + self._strike = False + self._italic = False + self._blink = False + self._reverse = False + self._hidden = False + + elif attr in (38, 48) and len(attrs) > 1: + n = attrs.pop() + + # 256 colors. + if n == 5 and len(attrs) >= 1: + if attr == 38: + m = attrs.pop() + self._color = _256_colors.get(m) + elif attr == 48: + m = attrs.pop() + self._bgcolor = _256_colors.get(m) + + # True colors. + if n == 2 and len(attrs) >= 3: + try: + color_str = "#%02x%02x%02x" % ( + attrs.pop(), + attrs.pop(), + attrs.pop(), + ) + except IndexError: + pass + else: + if attr == 38: + self._color = color_str + elif attr == 48: + self._bgcolor = color_str + + def _create_style_string(self) -> str: + """ + Turn current style flags into a string for usage in a formatted text. + """ + result = [] + if self._color: + result.append(self._color) + if self._bgcolor: + result.append("bg:" + self._bgcolor) + if self._bold: + result.append("bold") + if self._underline: + result.append("underline") + if self._strike: + result.append("strike") + if self._italic: + result.append("italic") + if self._blink: + result.append("blink") + if self._reverse: + result.append("reverse") + if self._hidden: + result.append("hidden") + + return " ".join(result) + + def __repr__(self) -> str: + return "ANSI(%r)" % (self.value,) + + def __pt_formatted_text__(self) -> StyleAndTextTuples: + return self._formatted_text + + def format(self, *args: str, **kwargs: str) -> "ANSI": + """ + Like `str.format`, but make sure that the arguments are properly + escaped. (No ANSI escapes can be injected.) + """ + # Escape all the arguments. + args = tuple(ansi_escape(a) for a in args) + kwargs = {k: ansi_escape(v) for k, v in kwargs.items()} + + return ANSI(self.value.format(*args, **kwargs)) + + +# Mapping of the ANSI color codes to their names. +_fg_colors = {v: k for k, v in FG_ANSI_COLORS.items()} +_bg_colors = {v: k for k, v in BG_ANSI_COLORS.items()} + +# Mapping of the escape codes for 256colors to their 'ffffff' value. +_256_colors = {} + +for i, (r, g, b) in enumerate(_256_colors_table.colors): + _256_colors[i] = "#%02x%02x%02x" % (r, g, b) + + +def ansi_escape(text: str) -> str: + """ + Replace characters with a special meaning. + """ + return text.replace("\x1b", "?").replace("\b", "?") |