From f3072a5c665cce7efe6fb0e99a4bdc2e537b06d2 Mon Sep 17 00:00:00 2001 From: delameter <0.delameter@gmail.com> Date: Wed, 11 Jan 2023 04:45:23 +0300 Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=80=20RELEASE:=20=20v1.4.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.dist | 2 +- README.md | 3 + kolombos/version.py | 2 +- pytermor/__init__.py | 117 +- pytermor/__main__.py | 2 +- pytermor/_version.py | 4 +- pytermor/ansi.py | 1130 ++++++++---------- pytermor/color.py | 1379 +++++++++------------- pytermor/common.py | 202 +--- pytermor/cval.py | 2002 -------------------------------- pytermor/cval.py.tpl | 20 - pytermor/render.py | 777 +++++++++++++ pytermor/renderer.py | 658 ----------- pytermor/style.py | 465 -------- pytermor/text.py | 801 ------------- pytermor/util/__init__.py | 33 + pytermor/util/auto_float.py | 158 +++ pytermor/util/prefixed_unit.py | 208 ++++ pytermor/util/stdlib_ext.py | 53 + pytermor/util/string_filter.py | 121 ++ pytermor/util/time_delta.py | 298 +++++ pytermor/utilmisc.py | 462 -------- pytermor/utilnum.py | 1094 ----------------- pytermor/utilstr.py | 799 ------------- setup.cfg | 2 +- 25 files changed, 2751 insertions(+), 8041 deletions(-) delete mode 100644 pytermor/cval.py delete mode 100644 pytermor/cval.py.tpl create mode 100644 pytermor/render.py delete mode 100644 pytermor/renderer.py delete mode 100644 pytermor/style.py delete mode 100644 pytermor/text.py create mode 100644 pytermor/util/__init__.py create mode 100644 pytermor/util/auto_float.py create mode 100644 pytermor/util/prefixed_unit.py create mode 100644 pytermor/util/stdlib_ext.py create mode 100644 pytermor/util/string_filter.py create mode 100644 pytermor/util/time_delta.py delete mode 100644 pytermor/utilmisc.py delete mode 100644 pytermor/utilnum.py delete mode 100644 pytermor/utilstr.py diff --git a/.env.dist b/.env.dist index 0b68721..c693307 100644 --- a/.env.dist +++ b/.env.dist @@ -1,4 +1,4 @@ -VERSION=1.4.0 +VERSION=1.4.1 PYPI_USERNAME=__token__ PYPI_PASSWORD= #api token PYPI_PASSWORD_DEV= #api token diff --git a/README.md b/README.md index 041f849..f855c5d 100644 --- a/README.md +++ b/README.md @@ -191,6 +191,9 @@ Even more information can be seen after running `kolombos --legend`. ## Changelog +### v1.4.1 +- Temporarily injected `pytermor` v2.1 + ### v1.4 - REFACTOR: base colors - REFACTOR: extended legend diff --git a/kolombos/version.py b/kolombos/version.py index 96e3ce8..8e3c933 100644 --- a/kolombos/version.py +++ b/kolombos/version.py @@ -1 +1 @@ -__version__ = '1.4.0' +__version__ = '1.4.1' diff --git a/pytermor/__init__.py b/pytermor/__init__.py index 3fd99cc..ef99897 100644 --- a/pytermor/__init__.py +++ b/pytermor/__init__.py @@ -1,114 +1,13 @@ # ----------------------------------------------------------------------------- # pytermor [ANSI formatted terminal output toolset] -# (c) 2022-2023. A. Shavykin <0.delameter@gmail.com> +# (c) 2022. A. Shavykin <0.delameter@gmail.com> # ----------------------------------------------------------------------------- -import os +from .ansi import IntCodes, Seqs, Spans, SequenceSGR, Span, NOOP_SEQ, NOOP_SPAN +from .color import Colors, ColorIndexed16, ColorIndexed256, ColorRGB, NOOP_COLOR +from .render import Styles, Style, Text, SgrRenderer, RendererManager, NOOP_STYLE +from ._version import __version__ -from ._version import __version__ as __version__ -from .common import CDT as CDT -from .common import FT as FT -from .common import RT as RT -from .common import logger as logger -from .common import Align as Align -from .common import ArgCountError as ArgCountError -from .common import ArgTypeError as ArgTypeError -from .common import ConflictError as ConflictError -from .common import LogicError as LogicError -from .common import UserAbort as UserAbort -from .common import UserCancel as UserCancel +import logging +from logging import NullHandler -from .ansi import NOOP_SEQ as NOOP_SEQ -from .ansi import IntCode as IntCode -from .ansi import SeqIndex as SeqIndex -from .ansi import ISequence as ISequence -from .ansi import SequenceSGR as SequenceSGR -from .ansi import enclose as enclose -from .ansi import get_closing_seq as get_closing_seq -from .ansi import make_color_256 as make_color_256 -from .ansi import make_color_rgb as make_color_rgb -from .color import NOOP_COLOR as NOOP_COLOR -from .color import IColor as IColor -from .color import Color16 as Color16 -from .color import Color256 as Color256 -from .color import ColorRGB as ColorRGB -from .color import ApxResult as ApxResult -from .color import approximate as approximate -from .color import find_closest as find_closest -from .color import resolve_color as resolve_color -from .color import hex_to_rgb as hex_to_rgb -from .color import hex_to_hsv as hex_to_hsv -from .color import rgb_to_hex as rgb_to_hex -from .cval import CVAL as cv -from .style import NOOP_STYLE as NOOP_STYLE -from .style import Style as Style -from .style import Styles as Styles -from .style import make_style as make_style -from .style import merge_styles as merge_styles -from .renderer import IRenderer as IRenderer -from .renderer import HtmlRenderer as HtmlRenderer -from .renderer import RendererManager as RendererManager -from .renderer import SgrRenderer as SgrRenderer -from .renderer import TmuxRenderer as TmuxRenderer -from .renderer import OutputMode as OutputMode -from .text import IRenderable as IRenderable -from .text import Fragment as Fragment -from .text import FrozenText as FrozenText -from .text import SimpleTable as SimpleTable -from .text import Text as Text -from .text import TemplateEngine as TemplateEngine -from .text import echo as echo -from .text import echoi as echoi -from .text import render as render -from .text import distribute_padded as distribute_padded -from .utilmisc import confirm as confirm -from .utilmisc import get_char_width as get_char_width -from .utilmisc import get_preferable_wrap_width as get_preferable_wrap_width -from .utilmisc import get_qname as get_qname -from .utilmisc import get_terminal_width as get_terminal_width -from .utilmisc import guess_char_width as guess_char_width -from .utilmisc import measure_char_width as measure_char_width -from .utilmisc import total_size as total_size -from .utilmisc import wait_key as wait_key -from .utilnum import NumHighlighter as NumHighlighter -from .utilnum import StaticBaseFormatter as StaticBaseFormatter -from .utilnum import DynamicBaseFormatter as DynamicBaseFormatter -from .utilnum import CustomBaseUnit as CustomBaseUnit -from .utilnum import format_auto_float as format_auto_float -from .utilnum import format_thousand_sep as format_thousand_sep -from .utilnum import format_si as format_si -from .utilnum import format_si_binary as format_si_binary -from .utilnum import format_time_delta as format_time_delta -from .utilstr import ESCAPE_SEQ_REGEX as ESCAPE_SEQ_REGEX -from .utilstr import SGR_SEQ_REGEX as SGR_SEQ_REGEX -from .utilstr import CSI_SEQ_REGEX as CSI_SEQ_REGEX -from .utilstr import CONTROL_CHARS as CONTROL_CHARS -from .utilstr import WHITESPACE_CHARS as WHITESPACE_CHARS -from .utilstr import PRINTABLE_CHARS as PRINTABLE_CHARS -from .utilstr import NON_ASCII_CHARS as NON_ASCII_CHARS -from .utilstr import IFilter as IFilter -from .utilstr import BytesTracer as BytesTracer -from .utilstr import CsiStringReplacer as CsiStringReplacer -from .utilstr import EscSeqStringReplacer as EscSeqStringReplacer -from .utilstr import NonPrintsOmniVisualizer as NonPrintsOmniVisualizer -from .utilstr import NonPrintsStringVisualizer as NonPrintsStringVisualizer -from .utilstr import NoopFilter as NoopFilter -from .utilstr import OmniDecoder as OmniDecoder -from .utilstr import OmniEncoder as OmniEncoder -from .utilstr import OmniMapper as OmniMapper -from .utilstr import OmniSanitizer as OmniSanitizer -from .utilstr import SgrStringReplacer as SgrStringReplacer -from .utilstr import StringTracer as StringTracer -from .utilstr import StringMapper as StringMapper -from .utilstr import StringReplacer as StringReplacer -from .utilstr import StringUcpTracer as StringUcpTracer -from .utilstr import TracerExtra as TracerExtra -from .utilstr import pad as pad -from .utilstr import padv as padv -from .utilstr import ljust_sgr as ljust_sgr -from .utilstr import rjust_sgr as rjust_sgr -from .utilstr import center_sgr as center_sgr -from .utilstr import wrap_sgr as wrap_sgr -from .utilstr import apply_filters as apply_filters -from .utilstr import dump as dump - -PYTERMOR_DEV = os.environ.get('PYTERMOR_DEV', False) +logging.getLogger(__name__).addHandler(NullHandler()) diff --git a/pytermor/__main__.py b/pytermor/__main__.py index ea0788c..308ad15 100644 --- a/pytermor/__main__.py +++ b/pytermor/__main__.py @@ -1,4 +1,4 @@ # ----------------------------------------------------------------------------- # pytermor [ANSI formatted terminal output toolset] -# (c) 2022-2023. A. Shavykin <0.delameter@gmail.com> +# (c) 2022. A. Shavykin <0.delameter@gmail.com> # ----------------------------------------------------------------------------- diff --git a/pytermor/_version.py b/pytermor/_version.py index 24381c8..94d171e 100644 --- a/pytermor/_version.py +++ b/pytermor/_version.py @@ -1,5 +1,5 @@ # ----------------------------------------------------------------------------- # pytermor [ANSI formatted terminal output toolset] -# (c) 2022-2023. A. Shavykin <0.delameter@gmail.com> +# (c) 2022. A. Shavykin <0.delameter@gmail.com> # ----------------------------------------------------------------------------- -__version__ = '2.35.1-dev1' +__version__ = '2.1.0-dev15' diff --git a/pytermor/ansi.py b/pytermor/ansi.py index 3902864..416e543 100644 --- a/pytermor/ansi.py +++ b/pytermor/ansi.py @@ -1,79 +1,62 @@ # ----------------------------------------------------------------------------- # pytermor [ANSI formatted terminal output toolset] -# (c) 2022-2023. A. Shavykin <0.delameter@gmail.com> +# (c) 2022. A. Shavykin <0.delameter@gmail.com> # ----------------------------------------------------------------------------- """ -Module contains definitions for low-level ANSI escape sequences building. -Can be used for creating a variety of sequences including: +Module contains definitions for low-level ANSI escape sequences handling. - - :abbr:`SGR (Select Graphic Rendition)` sequences (text and background - coloring, other text formatting and effects); - - :abbr:`CSI (Control Sequence Introducer)` sequences (cursor management, - selective screen cleraing); - - :abbr:`OSC (Operating System Command)` sequences (varoius system commands). +The key difference beetween ``Spans`` and ``Sequences`` is that sequence can +*open* text style and also *close*, or terminate it. As for ``Spans`` -- they +always do both; typical use-case of `Span` is to wrap some text in opening SGR +and closing one. -.. important :: - blah-blah-blah low-level @TODO +Each variable in `Seqs` and `Spans` below is a valid argument +for :class:`.Span` and :class:`.SequenceSGR` default constructors; furthermore, +it can be passed in a string form (case-insensitive): + +.. testsetup:: * + + from pytermor.ansi import SequenceSGR, Spans, Span, Seqs, IntCodes, NOOP_SPAN, NOOP_SEQ + +>>> Span('BG_GREEN') +Span[SGR[42], SGR[49]] + +>>> Span(Seqs.BG_GREEN, Seqs.UNDERLINED) +Span[SGR[42;4], SGR[49;24]] """ from __future__ import annotations -from abc import abstractmethod, ABCMeta +from abc import ABCMeta, abstractmethod from copy import copy -import enum -import typing as t +from typing import List, Any, Dict, Tuple, Sized -from .common import ConflictError +from .common import Registry -class ISequence(t.Sized, metaclass=ABCMeta): +class Sequence(Sized, metaclass=ABCMeta): """ Abstract ancestor of all escape sequences. """ + def __init__(self, *params: int): + self._params: List[int] = [max(0, int(p)) for p in params] - _ESC_CHARACTER: str = "\x1b" - _SEPARATOR: str = ";" - _INTRODUCER: str - _TERMINATOR: str - - def __init__(self, *params: int | str): - """ - :param \*params: Sequence internal parameters, existnce and - valid amount depends on sequence type. - """ - self._params: t.List[int | str] = [] - - for param in params: - if isinstance(param, IntCode): - self._params.append( - param.value - ) # to avoid casting it later in assemble() - continue - self._params.append(param) - + @abstractmethod def assemble(self) -> str: """ Build up actual byte sequence and return as an ASCII-encoded string. """ - return ( - self._ESC_CHARACTER - + self._INTRODUCER - + self._SEPARATOR.join([str(param) for param in self.params]) - + self._TERMINATOR - ) + raise NotImplementedError @property - def params(self) -> t.List[int | str]: - """ - Return internal params as array. - """ + def params(self) -> List[int]: + """ Return internal params as array. """ return self._params @classmethod @abstractmethod - def _short_class_name(cls): - raise NotImplementedError + def _short_class_name(cls): raise NotImplementedError def __str__(self) -> str: return self.assemble() @@ -81,187 +64,146 @@ def __str__(self) -> str: def __len__(self) -> int: return 0 - def __eq__(self, other: ISequence): + def __eq__(self, other: Sequence): if type(self) != type(other): return False return self._params == other._params - def __repr__(self) -> str: - params = ",".join([str(p) for p in self._params]) - return f"<{self._short_class_name()}[{params}]>" + def __repr__(self): + params = ";".join([str(p) for p in self._params]) + if len(self._params) == 0: + params = '~' + return f'{self._short_class_name()}[{params}]' -class ISequenceFe(ISequence, metaclass=ABCMeta): +class SequenceCSI(Sequence, metaclass=ABCMeta): """ - Wide range of sequence types that includes `CSI `, - `OSC ` and more. - - All subtypes of this sequence start with ``ESC`` plus ASCII byte - from ``0x40`` to ``0x5F`` (``@``, ``[``, ``\\``, ``]``, ``_``, ``^`` and - capital letters ``A``-``Z``). - """ - - -class SequenceST(ISequenceFe): + Abstract class representing CSI-type ANSI escape sequence. All subtypes + of this sequence start with :kbd:`\\e[`. """ - String Terminator sequence (ST). Terminates strings in other control - sequences. Encoded as ``ESC \\`` (``0x1B`` ``0x5C``). - """ - - _INTRODUCER = "\\" + _CONTROL_CHARACTER = '\x1b' + _INTRODUCER = '[' + _SEPARATOR = ';' - def assemble(self) -> str: - return self._ESC_CHARACTER + self._INTRODUCER + def __init__(self, *params: int): + super(SequenceCSI, self).__init__(*params) @classmethod - def _short_class_name(cls) -> str: - return "ST" - - -class SequenceOSC(ISequenceFe): - """ - :abbr:`OSC (Operating System Command)`-type sequence. Starts a control - string for the operating system to use. Encoded as ``ESC ]``, plus params - separated by ``;``, and terminated with `SequenceST`. - """ - - _INTRODUCER = "]" - _TERMINATOR = SequenceST().assemble() + def regexp(cls) -> str: + return f'\\x1b\\[[0-9;]*{cls._terminator()}' @classmethod - def _short_class_name(cls): - return "OSC" - - -class SequenceCSI(ISequenceFe): - """ - Class representing :abbr:`CSI (Control Sequence Introducer)`-type ANSI - escape sequence. All subtypes of this sequence start with ``ESC [``. - - Sequences of this type are used to control text formatting, - change cursor position, erase screen and more. + @abstractmethod + def _terminator(cls) -> str: raise NotImplementedError - >>> make_erase_in_line().assemble() - '\x1b[0K' +class SequenceSGR(SequenceCSI, metaclass=ABCMeta): """ + Class representing SGR-type escape sequence with varying amount of parameters. - _INTRODUCER = "[" - - def __init__(self, terminator: str, short_name: str, *params: int): - """ - - :param terminator: - :param short_name: - :param params: - """ - self._terminator = terminator - self._short_name = short_name - super().__init__(*params) + `SequenceSGR` with zero params was specifically implemented to + translate into empty string and not into :kbd:`\\e[m`, which would have + made sense, but also would be very entangling, as this sequence is + equivalent of :kbd:`\\e[0m` -- hard reset sequence. The empty-string-sequence + is predefined as `NOOP_SEQ`. - def regexp(self) -> str: - return f"\\x1b\\[[0-9;]*{self._terminator}" + It's possible to add of one SGR sequence to another: - def assemble(self) -> str: - return ( - self._ESC_CHARACTER - + self._INTRODUCER - + self._SEPARATOR.join([str(param) for param in self.params]) - + self._terminator - ) - - def _short_class_name(self): - result = "CSI" - if self._short_name: - result += ":" + self._short_name - return result - - -class SequenceSGR(SequenceCSI): - """ - Class representing :abbr:`SGR (Select Graphic Rendition)`-type escape sequence - with varying amount of parameters. SGR sequences allow to change the color - of text or/and terminal background (in 3 different color spaces) as well - as set decorate text with italic style, underlining, overlining, cross-lining, - making it bold or blinking etc. - - When cast to *str*, as all other sequences, invokes `assemble()` method - and transforms into encoded control sequence string. It is possible to add - of one SGR sequence to another, resulting in a new one with merged params - (see examples). - - .. note :: - `SequenceSGR` with zero params was specifically implemented to - translate into empty string and not into ``ESC [m``, which would have - made sense, but also would be entangling, as this sequence is the equivalent - of ``ESC [0m`` -- hard reset sequence. The empty-string-sequence is - predefined at module level as `NOOP_SEQ`. - - .. note :: - The module doesn't distinguish "single-instruction" sequences from several - ones merged together, e.g. ``Style(fg='red', bold=True)`` produces only one - opening SequenceSGR instance: - - >>> SequenceSGR(IntCode.BOLD, IntCode.RED).assemble() - '\x1b[1;31m' - - ...although generally speaking it is two of them (``ESC [1m`` and - ``ESC [31m``). However, the module can automatically match terminating - sequences for any form of input SGRs and translate it to specified format. - - >>> SequenceSGR(IntCode.HI_CYAN, 'underlined', 1) - >>> SequenceSGR(31) + SequenceSGR(1) == SequenceSGR(31, 1) True - :param args: .. :: + """ + _TERMINATOR = 'm' - Sequence params. Resulting param order is the same as an - argument order. Each argument can be specified as: + def __init__(self, *args: str|int|SequenceSGR): + """ + Create new `SequenceSGR` with specified ``args`` as params. - - *str* -- any of `IntCode` names, case-insensitive - - *int* -- `IntCode` instance or plain integer - - `SequenceSGR` instance (params will be extracted) - """ + Resulting sequence param order is same as an argument order. - _TERMINATOR = "m" + Each sequence param can be specified as: + - string key (name of any constant defined in `IntCodes`, case-insensitive) + - integer param value (``IntCodes`` values) + - existing ``SequenceSGR`` instance (params will be extracted). - def __init__(self, *args: str | int | SequenceSGR): - result: t.List[int] = [] + >>> SequenceSGR('yellow', 'bold') + SGR[33;1] + >>> SequenceSGR(91, 7) + SGR[91;7] + >>> SequenceSGR(IntCodes.HI_CYAN, IntCodes.UNDERLINED) + SGR[96;4] + """ + result: List[int] = [] for arg in args: if isinstance(arg, str): - result.append(IntCode.resolve(arg).value) + resolved_param = IntCodes.resolve(arg) + if not isinstance(resolved_param, int): + raise ValueError(f'Attribute is not valid SGR param: {resolved_param}') + result.append(resolved_param) elif isinstance(arg, int): result.append(arg) elif isinstance(arg, SequenceSGR): result.extend(arg.params) else: - raise TypeError(f"Invalid argument type: {arg!r})") + raise TypeError(f'Invalid argument type: {arg!r})') - result = [max(0, p) for p in result] - super().__init__(self._TERMINATOR, "SGR", *result) + super().__init__(*result) - def assemble(self) -> str: - if len(self._params) == 0: # NOOP - return "" + @classmethod + def init_color_indexed(cls, idx: int, bg: bool = False) -> SequenceSGR: + """ + Wrapper for creation of `SequenceSGR` that sets foreground + (or background) to one of 256-color pallete value. - return ( - self._ESC_CHARACTER - + self._INTRODUCER - + self._SEPARATOR.join([str(param) for param in self._params]) - + self._TERMINATOR - ) + :param idx: Index of the color in the pallete, 0 -- 255. + :param bg: Set to *True* to change the background color + (default is foreground). + :return: `SequenceSGR` with required params. + """ - @property - def params(self) -> t.List[int]: + cls._validate_extended_color(idx) + key_code = IntCodes.BG_COLOR_EXTENDED if bg else IntCodes.COLOR_EXTENDED + return SequenceSGR(key_code, IntCodes.EXTENDED_MODE_256, idx) + + @classmethod + def init_color_rgb(cls, r: int, g: int, b: int, bg: bool = False) -> SequenceSGR: """ - :return: Sequence params as integers or `IntCode` instances. + Wrapper for creation of `SequenceSGR` operating in True Color mode (16M). + Valid values for *r*, *g* and *b* are in range [0; 255]. This range + linearly translates into [``0x00``; ``0xFF``] for each channel. The result + value is composed as ``#RRGGBB``. For example, sequence with color of + ``#FF3300`` can be created with:: + + SequenceSGR.init_color_rgb(255, 51, 0) + + :param r: Red channel value, 0 -- 255. + :param g: Blue channel value, 0 -- 255. + :param b: Green channel value, 0 -- 255. + :param bg: Set to *True* to change the background color + (default is foreground). + :return: `SequenceSGR` with required params. """ - return super().params + + [cls._validate_extended_color(color) for color in [r, g, b]] + key_code = IntCodes.BG_COLOR_EXTENDED if bg else IntCodes.COLOR_EXTENDED + return SequenceSGR(key_code, IntCodes.EXTENDED_MODE_RGB, r, g, b) + + def assemble(self) -> str: + if len(self._params) == 0: # NOOP + return '' + + params = self._params + if params == [0]: # \x1b[0m <=> \x1b[m, saving 1 byte + params = [] + + return (self._CONTROL_CHARACTER + + self._INTRODUCER + + self._SEPARATOR.join([str(param) for param in params]) + + self._TERMINATOR) def __hash__(self) -> int: - return int.from_bytes(self.assemble().encode(), byteorder="big") + return int.from_bytes(self.assemble().encode(), byteorder='big') def __add__(self, other: SequenceSGR) -> SequenceSGR: self._ensure_sequence(other) @@ -278,57 +220,157 @@ def __eq__(self, other: SequenceSGR): return False return self._params == other._params + @property + def is_color_extended(self) -> bool: + return len(self.params) >= 3 and \ + (self.params[0] == IntCodes.COLOR_EXTENDED or + self.params[0] == IntCodes.BG_COLOR_EXTENDED) + @staticmethod - def _ensure_sequence(subject: t.Any): + def _ensure_sequence(subject: Any): if not isinstance(subject, SequenceSGR): - raise TypeError(f"Expected SequenceSGR, got {type(subject)}") + raise TypeError(f'Expected SequenceSGR, got {type(subject)}') @staticmethod - def validate_extended_color(value: int): + def _validate_extended_color(value: int): if value < 0 or value > 255: raise ValueError( - f"Invalid color value: expected range [0-255], got: {value}" - ) + f'Invalid color value: expected range [0-255], got: {value}') + + @classmethod + def _terminator(cls) -> str: + return cls._TERMINATOR @classmethod def _short_class_name(cls) -> str: - return "SGR" - - -# class UnderlinedCurlySequenceSGR(SequenceSGR): -# """ -# Registered as a separate class, because this is the one and only SGR in the -# package, which is identified by "4:3" string (in contrast with all the other -# sequences entirely made of digits and semicolon separators). -# """ -# -# def __init__(self): -# """ """ -# super().__init__() -# self._params = [f"{IntCode.UNDERLINED}:3"] -# -# @property -# def params(self) -> t.List[str]: -# """ """ -# return self._params - -class _NoOpSequenceSGR(SequenceSGR): - def __init__(self): - super().__init__() - - def __bool__(self) -> bool: - return False - - def __eq__(self, other: SequenceSGR) -> bool: - if not isinstance(other, SequenceSGR): + return 'SGR' + + +# noinspection PyMethodMayBeStatic +class Span: + """ + Class consisting of two `SequenceSGR` instances -- the first one, "opener", + tells the terminal that's it should format subsequent characters as specified, + and the second one, which reverses the effects of the first one. + """ + def __init__(self, *opening_params: str|int|SequenceSGR): + """ + Create a `Span` with specified control sequence(s) as an opening sequence + and **automatically compose** second (closing) sequence that will terminate + attributes defined in the first one while keeping the others (*soft* reset). + + Resulting sequence param order is same as an argument order. + + Each argument can be specified as: + - string key (name of any constant defined in `IntCodes`, case-insensitive) + - integer param value (``IntCodes`` values) + - existing `SequenceSGR` instance (params will be extracted). + + >>> Span('red', 'bold') + Span[SGR[31;1], SGR[39;22]] + >>> Span(IntCodes.GREEN) + Span[SGR[32], SGR[39]] + >>> Span(93, 4) + Span[SGR[93;4], SGR[39;24]] + >>> Span(Seqs.BG_BLACK + Seqs.RED) + Span[SGR[40;31], SGR[49;39]] + + :param opening_params: string keys, integer codes or existing ``SequenceSGR`` + instances to build ``Span`` from. + """ + self._opening_seq = SequenceSGR(*opening_params) + if len(opening_params) == 0: + self._closing_seq = SequenceSGR() + return + + self._closing_seq = _SgrPairityRegistry.get_closing_seq(self._opening_seq) + + @classmethod + def init_explicit(cls, opening_seq: SequenceSGR = None, + closing_seq: SequenceSGR = None, + hard_reset_after: bool = False) -> Span: + """ + Create new `Span` with explicitly specified opening and closing sequences. + + .. note :: + `closing_seq` gets overwritten with `Seqs.RESET` if ``hard_reset_after`` is *True*. + + :param opening_seq: Starter sequence, in general determening how `Span` will actually look like. + :param closing_seq: Finisher SGR sequence. + :param hard_reset_after: Terminate *all* formatting after this span. + """ + instance = Span() + instance._opening_seq = cls._opt_arg(opening_seq) + instance._closing_seq = cls._opt_arg(closing_seq) + + if hard_reset_after: + instance._closing_seq = Seqs.RESET + + return instance + + def wrap(self, text: Any = None) -> str: + """ + Wrap given ``text`` string with ``SGRs`` defined on initialization -- `opening_seq` + on the left, `closing_seq` on the right. ``str(text)`` will + be invoked for all argument types with the exception of *None*, + which will be replaced with an empty string. + + :param text: String to wrap. + :return: ``text`` enclosed in instance's ``SGRs``, if any. + """ + result = self._opening_seq.assemble() + + if text is not None: + result += str(text) + + result += self._closing_seq.assemble() + return result + + @property + def opening_str(self) -> str: + """ Return opening SGR sequence assembled. """ + return self._opening_seq.assemble() + + @property + def opening_seq(self) -> 'SequenceSGR': + """ Return opening SGR sequence instance. """ + return self._opening_seq + + @property + def closing_str(self) -> str: + """ Return closing SGR sequence assembled. """ + return self._closing_seq.assemble() + + @property + def closing_seq(self) -> 'SequenceSGR': + """ Return closing SGR sequence instance. """ + return self._closing_seq + + @classmethod + def _opt_arg(self, arg: SequenceSGR | None) -> SequenceSGR: + if not arg: + return NOOP_SEQ + return arg + + def __call__(self, text: Any = None) -> str: + """ + Can be used instead of `wrap()` method. + + >>> Spans.RED('text') == Spans.RED.wrap('text') + True + """ + return self.wrap(text) + + def __eq__(self, other: Span) -> bool: + if not isinstance(other, Span): return False - return self._params == other._params + return self._opening_seq == other._opening_seq and self._closing_seq == other._closing_seq - def __repr__(self) -> str: - return f"<{self._short_class_name()}[NOP]>" + def __repr__(self): + return self.__class__.__name__ + '[{!r}, {!r}]'.format(self._opening_seq, self._closing_seq) -NOOP_SEQ = _NoOpSequenceSGR() +NOOP_SEQ = SequenceSGR() """ Special sequence in case you *have to* provide one or another SGR, but do not want any control sequences to be actually included in the output. @@ -339,48 +381,44 @@ def __repr__(self) -> str: '' >>> NOOP_SEQ.params [] +""" +NOOP_SPAN = Span() """ +Special `Span` in cases where you *have to* select one or +another `Span`, but do not want any control sequence to be actually included. +- ``NOOP_SPAN(string)`` or ``NOOP_SPAN.wrap(string)`` returns ``string`` without any modifications; +- ``NOOP_SPAN.opening_str`` and ``NOOP_SPAN.closing_str`` are empty strings; +- ``NOOP_SPAN.opening_seq`` and ``NOOP_SPAN.closing_seq`` both returns `NOOP_SEQ`. -class IntCode(enum.IntEnum): - """ - Complete or almost complete list of reliably working SGR param integer codes. - Fully interchangeable with plain *int*. Suitable for `SequenceSGR` - default constructor. - - .. note :: - `IntCode` predefined constants are omitted from documentation to avoid - useless repeats and save space, as most of the time "next level" class - `SeqIndex` is more appropriate, and on top of that, the constant - names are literally the same for `SeqIndex` and `IntCode`. - """ +>>> NOOP_SPAN('text') +'text' +>>> NOOP_SPAN.opening_str +'' +>>> NOOP_SPAN.opening_seq +SGR[~] +""" - @classmethod - def resolve(cls, name: str) -> IntCode: - """ - :param name: - """ - name_norm = name.upper() - try: - instance = cls[name_norm] - except KeyError as e: - e.args = (f"Int code '{name_norm}' (<- '{name}') does not exist",) - raise e - return instance +class IntCodes(Registry[int]): + """ + Complete or almost complete list of reliably working SGR param integer codes. - def __repr__(self) -> str: - return f"<{self.value}|{self.name}>" + Suitable for :class:`.Span` and :class:`.SequenceSGR` default constructors. - # -- SGR: default attributes and colors ----------------------------------- + .. attention:: + Registry constants are omitted from API doc pages to improve readability + and avoid duplication. Summary list of all presets can be found in + `guide.presets` section of the guide. + """ + # -- Default attributes and colors -------------------------------------------- RESET = 0 # hard reset code BOLD = 1 DIM = 2 ITALIC = 3 UNDERLINED = 4 - # CURLY_UNDERLINED = '4:3' # TODO BLINK_SLOW = 5 BLINK_FAST = 6 INVERSED = 7 @@ -388,8 +426,8 @@ def __repr__(self) -> str: CROSSLINED = 9 DOUBLE_UNDERLINED = 21 OVERLINED = 53 - BOLD_DIM_OFF = 22 # no sequence to disable BOLD or DIM while keeping the other - ITALIC_OFF = 23 + BOLD_DIM_OFF = 22 # there is no separate sequence for disabling either + ITALIC_OFF = 23 # of BOLD or DIM while keeping the other UNDERLINED_OFF = 24 BLINK_OFF = 25 INVERSED_OFF = 27 @@ -407,7 +445,7 @@ def __repr__(self) -> str: MAGENTA = 35 CYAN = 36 WHITE = 37 - COLOR_EXTENDED = 38 + COLOR_EXTENDED = 38 # use init_color_indexed() and init_color_rgb() instead BG_BLACK = 40 BG_RED = 41 @@ -417,10 +455,7 @@ def __repr__(self) -> str: BG_MAGENTA = 45 BG_CYAN = 46 BG_WHITE = 47 - BG_COLOR_EXTENDED = 48 - - # UNDERLINE_COLOR_EXTENDED = 58 # @TODO - # UNDERLINE_COLOR_OFF = 59 + BG_COLOR_EXTENDED = 48 # use color_indexed() and color_rgb() instead GRAY = 90 HI_RED = 91 @@ -447,449 +482,252 @@ def __repr__(self) -> str: # 51: framed # 52: encircled # 54: neither framed nor encircled + # 58-59: underline color # 60-65: ideogram attributes # 73-75: superscript and subscript - # -- SGR: extended modifiers ---------------------------------------------- - - EXTENDED_MODE_256 = 5 - EXTENDED_MODE_RGB = 2 + # -- Default colors lists ----------------------------------------------------- - # -- Other sequence classes ----------------------------------------------- + LIST_COLORS = list(range(30, 39)) + LIST_BG_COLORS = list(range(40, 49)) + LIST_HI_COLORS = list(range(90, 98)) + LIST_BG_HI_COLORS = list(range(100, 108)) - HYPERLINK = 8 + LIST_ALL_COLORS = LIST_COLORS + LIST_BG_COLORS + \ + LIST_HI_COLORS + LIST_BG_HI_COLORS + # -- EXTENDED modifiers ------------------------------------------------------- -class SeqIndex: - """ - Registry of static sequence presets. - """ + EXTENDED_MODE_256 = 5 + EXTENDED_MODE_RGB = 2 - # -- SGR ------------------------------------------------------------------ - RESET = SequenceSGR(IntCode.RESET) - """ - Hard reset sequence. +class Seqs(Registry[SequenceSGR]): """ + Registry of sequence presets. - BOLD = SequenceSGR(IntCode.BOLD) - """ Bold or increased intensity. """ - - DIM = SequenceSGR(IntCode.DIM) - """ Faint, decreased intensity. """ - - ITALIC = SequenceSGR(IntCode.ITALIC) - """ Italic *(not widely supported)*. """ - - UNDERLINED = SequenceSGR(IntCode.UNDERLINED) - """ Underline. """ - - BLINK_SLOW = SequenceSGR(IntCode.BLINK_SLOW) - """ Set blinking to < 150 cpm. """ - - BLINK_FAST = SequenceSGR(IntCode.BLINK_FAST) - """ Set blinking to 150+ cpm *(not widely supported)*. """ - - INVERSED = SequenceSGR(IntCode.INVERSED) - """ Swap foreground and background colors. """ - - HIDDEN = SequenceSGR(IntCode.HIDDEN) - """ Conceal characters *(not widely supported)*. """ - - CROSSLINED = SequenceSGR(IntCode.CROSSLINED) - """ Strikethrough. """ - - DOUBLE_UNDERLINED = SequenceSGR(IntCode.DOUBLE_UNDERLINED) - """ Double-underline. *On several terminals disables* `BOLD` *instead*. """ - - OVERLINED = SequenceSGR(IntCode.OVERLINED) - """ Overline *(not widely supported)*. """ + .. attention:: + Registry constants are omitted from API doc pages to improve readability + and avoid duplication. Summary list of all presets can be found in + `guide.presets` section of the guide. + """ - BOLD_DIM_OFF = SequenceSGR(IntCode.BOLD_DIM_OFF) + RESET = SequenceSGR(IntCodes.RESET) """ - Disable ``BOLD`` and ``DIM`` attributes.\n - *Special aspects... It's impossible to reliably disable them on a separate basis.* + Hard reset sequence. """ - ITALIC_OFF = SequenceSGR(IntCode.ITALIC_OFF) - """ Disable italic. """ - - UNDERLINED_OFF = SequenceSGR(IntCode.UNDERLINED_OFF) - """ Disable underlining. """ - - BLINK_OFF = SequenceSGR(IntCode.BLINK_OFF) - """ Disable blinking. """ - - INVERSED_OFF = SequenceSGR(IntCode.INVERSED_OFF) - """ Disable inversing. """ - - HIDDEN_OFF = SequenceSGR(IntCode.HIDDEN_OFF) - """ Disable conecaling. """ - - CROSSLINED_OFF = SequenceSGR(IntCode.CROSSLINED_OFF) - """ Disable strikethrough. """ - - OVERLINED_OFF = SequenceSGR(IntCode.OVERLINED_OFF) - """ Disable overlining. """ + # attributes + BOLD = SequenceSGR(IntCodes.BOLD) + DIM = SequenceSGR(IntCodes.DIM) + ITALIC = SequenceSGR(IntCodes.ITALIC) + UNDERLINED = SequenceSGR(IntCodes.UNDERLINED) + BLINK_SLOW = SequenceSGR(IntCodes.BLINK_SLOW) + BLINK_FAST = SequenceSGR(IntCodes.BLINK_FAST) + BLINK_DEFAULT = BLINK_SLOW + INVERSED = SequenceSGR(IntCodes.INVERSED) + HIDDEN = SequenceSGR(IntCodes.HIDDEN) + CROSSLINED = SequenceSGR(IntCodes.CROSSLINED) + DOUBLE_UNDERLINED = SequenceSGR(IntCodes.DOUBLE_UNDERLINED) + OVERLINED = SequenceSGR(IntCodes.OVERLINED) + + BOLD_DIM_OFF = SequenceSGR(IntCodes.BOLD_DIM_OFF) # there is no separate sequence for + ITALIC_OFF = SequenceSGR(IntCodes.ITALIC_OFF) # disabling either of BOLD or DIM + UNDERLINED_OFF = SequenceSGR(IntCodes.UNDERLINED_OFF) # while keeping the other + BLINK_OFF = SequenceSGR(IntCodes.BLINK_OFF) + INVERSED_OFF = SequenceSGR(IntCodes.INVERSED_OFF) + HIDDEN_OFF = SequenceSGR(IntCodes.HIDDEN_OFF) + CROSSLINED_OFF = SequenceSGR(IntCodes.CROSSLINED_OFF) + OVERLINED_OFF = SequenceSGR(IntCodes.OVERLINED_OFF) # text colors - - BLACK = SequenceSGR(IntCode.BLACK) - """ Set text color to 0x000000. """ - - RED = SequenceSGR(IntCode.RED) - """ Set text color to 0x800000. """ - - GREEN = SequenceSGR(IntCode.GREEN) - """ Set text color to 0x008000. """ - - YELLOW = SequenceSGR(IntCode.YELLOW) - """ Set text color to 0x808000. """ - - BLUE = SequenceSGR(IntCode.BLUE) - """ Set text color to 0x000080. """ - - MAGENTA = SequenceSGR(IntCode.MAGENTA) - """ Set text color to 0x800080. """ - - CYAN = SequenceSGR(IntCode.CYAN) - """ Set text color to 0x008080. """ - - WHITE = SequenceSGR(IntCode.WHITE) - """ Set text color to 0xc0c0c0. """ - - COLOR_OFF = SequenceSGR(IntCode.COLOR_OFF) - """ Reset foreground color. """ + BLACK = SequenceSGR(IntCodes.BLACK) + RED = SequenceSGR(IntCodes.RED) + GREEN = SequenceSGR(IntCodes.GREEN) + YELLOW = SequenceSGR(IntCodes.YELLOW) + BLUE = SequenceSGR(IntCodes.BLUE) + MAGENTA = SequenceSGR(IntCodes.MAGENTA) + CYAN = SequenceSGR(IntCodes.CYAN) + WHITE = SequenceSGR(IntCodes.WHITE) + # code.COLOR_EXTENDED is handled by color_indexed() + COLOR_OFF = SequenceSGR(IntCodes.COLOR_OFF) # background colors - - BG_BLACK = SequenceSGR(IntCode.BG_BLACK) - """ Set background color to 0x000000. """ - - BG_RED = SequenceSGR(IntCode.BG_RED) - """ Set background color to 0x800000. """ - - BG_GREEN = SequenceSGR(IntCode.BG_GREEN) - """ Set background color to 0x008000. """ - - BG_YELLOW = SequenceSGR(IntCode.BG_YELLOW) - """ Set background color to 0x808000. """ - - BG_BLUE = SequenceSGR(IntCode.BG_BLUE) - """ Set background color to 0x000080. """ - - BG_MAGENTA = SequenceSGR(IntCode.BG_MAGENTA) - """ Set background color to 0x800080. """ - - BG_CYAN = SequenceSGR(IntCode.BG_CYAN) - """ Set background color to 0x008080. """ - - BG_WHITE = SequenceSGR(IntCode.BG_WHITE) - """ Set background color to 0xc0c0c0. """ - - BG_COLOR_OFF = SequenceSGR(IntCode.BG_COLOR_OFF) - """ Reset background color. """ + BG_BLACK = SequenceSGR(IntCodes.BG_BLACK) + BG_RED = SequenceSGR(IntCodes.BG_RED) + BG_GREEN = SequenceSGR(IntCodes.BG_GREEN) + BG_YELLOW = SequenceSGR(IntCodes.BG_YELLOW) + BG_BLUE = SequenceSGR(IntCodes.BG_BLUE) + BG_MAGENTA = SequenceSGR(IntCodes.BG_MAGENTA) + BG_CYAN = SequenceSGR(IntCodes.BG_CYAN) + BG_WHITE = SequenceSGR(IntCodes.BG_WHITE) + # code.BG_COLOR_EXTENDED is handled by color_indexed() + BG_COLOR_OFF = SequenceSGR(IntCodes.BG_COLOR_OFF) # high intensity text colors - - GRAY = SequenceSGR(IntCode.GRAY) - """ Set text color to 0x808080. """ - HI_RED = SequenceSGR(IntCode.HI_RED) - """ Set text color to 0xff0000. """ - HI_GREEN = SequenceSGR(IntCode.HI_GREEN) - """ Set text color to 0x00ff00. """ - HI_YELLOW = SequenceSGR(IntCode.HI_YELLOW) - """ Set text color to 0xffff00. """ - HI_BLUE = SequenceSGR(IntCode.HI_BLUE) - """ Set text color to 0x0000ff. """ - HI_MAGENTA = SequenceSGR(IntCode.HI_MAGENTA) - """ Set text color to 0xff00ff. """ - HI_CYAN = SequenceSGR(IntCode.HI_CYAN) - """ Set text color to 0x00ffff. """ - HI_WHITE = SequenceSGR(IntCode.HI_WHITE) - """ Set text color to 0xffffff. """ + GRAY = SequenceSGR(IntCodes.GRAY) + HI_RED = SequenceSGR(IntCodes.HI_RED) + HI_GREEN = SequenceSGR(IntCodes.HI_GREEN) + HI_YELLOW = SequenceSGR(IntCodes.HI_YELLOW) + HI_BLUE = SequenceSGR(IntCodes.HI_BLUE) + HI_MAGENTA = SequenceSGR(IntCodes.HI_MAGENTA) + HI_CYAN = SequenceSGR(IntCodes.HI_CYAN) + HI_WHITE = SequenceSGR(IntCodes.HI_WHITE) # high intensity background colors - - BG_GRAY = SequenceSGR(IntCode.BG_GRAY) - """ Set background color to 0x808080. """ - BG_HI_RED = SequenceSGR(IntCode.BG_HI_RED) - """ Set background color to 0xff0000. """ - BG_HI_GREEN = SequenceSGR(IntCode.BG_HI_GREEN) - """ Set background color to 0x00ff00. """ - BG_HI_YELLOW = SequenceSGR(IntCode.BG_HI_YELLOW) - """ Set background color to 0xffff00. """ - BG_HI_BLUE = SequenceSGR(IntCode.BG_HI_BLUE) - """ Set background color to 0x0000ff. """ - BG_HI_MAGENTA = SequenceSGR(IntCode.BG_HI_MAGENTA) - """ Set background color to 0xff00ff. """ - BG_HI_CYAN = SequenceSGR(IntCode.BG_HI_CYAN) - """ Set background color to 0x00ffff. """ - BG_HI_WHITE = SequenceSGR(IntCode.BG_HI_WHITE) - """ Set background color to 0xffffff. """ - - # -- OSC ------------------------------------------------------------------ - - HYPERLINK = SequenceOSC(IntCode.HYPERLINK) - """ - Create a hyperlink in the text *(supported by limited amount of terminals)*. - Note that for a working hyperlink you'll need two sequences, not just one. - - .. seealso :: - `make_hyperlink_part()` and `assemble_hyperlink()`. - """ - - -COLORS = list(range(30, 39)) -BG_COLORS = list(range(40, 49)) -HI_COLORS = list(range(90, 98)) -BG_HI_COLORS = list(range(100, 108)) -ALL_COLORS = COLORS + BG_COLORS + HI_COLORS + BG_HI_COLORS + BG_GRAY = SequenceSGR(IntCodes.BG_GRAY) + BG_HI_RED = SequenceSGR(IntCodes.BG_HI_RED) + BG_HI_GREEN = SequenceSGR(IntCodes.BG_HI_GREEN) + BG_HI_YELLOW = SequenceSGR(IntCodes.BG_HI_YELLOW) + BG_HI_BLUE = SequenceSGR(IntCodes.BG_HI_BLUE) + BG_HI_MAGENTA = SequenceSGR(IntCodes.BG_HI_MAGENTA) + BG_HI_CYAN = SequenceSGR(IntCodes.BG_HI_CYAN) + BG_HI_WHITE = SequenceSGR(IntCodes.BG_HI_WHITE) class _SgrPairityRegistry: """ - Internal class providing methods for mapping SGRs to a - complement (closing) SGRs, also referred to as "resetters". + Internal class responsible for correct SGRs termination. """ - - _code_to_resetter_map: t.Dict[int | t.Tuple[int, ...], SequenceSGR] = dict() - _complex_code_def: t.Dict[int | t.Tuple[int, ...], int] = dict() + _code_to_breaker_map: Dict[int|Tuple[int, ...], SequenceSGR] = dict() + _complex_code_def: Dict[int|Tuple[int, ...], int] = dict() _complex_code_max_len: int = 0 - def __init__(self): - _regulars = [ - (IntCode.BOLD, IntCode.BOLD_DIM_OFF), - (IntCode.DIM, IntCode.BOLD_DIM_OFF), - (IntCode.ITALIC, IntCode.ITALIC_OFF), - (IntCode.UNDERLINED, IntCode.UNDERLINED_OFF), - (IntCode.DOUBLE_UNDERLINED, IntCode.UNDERLINED_OFF), - (IntCode.BLINK_SLOW, IntCode.BLINK_OFF), - (IntCode.BLINK_FAST, IntCode.BLINK_OFF), - (IntCode.INVERSED, IntCode.INVERSED_OFF), - (IntCode.HIDDEN, IntCode.HIDDEN_OFF), - (IntCode.CROSSLINED, IntCode.CROSSLINED_OFF), - (IntCode.OVERLINED, IntCode.OVERLINED_OFF), - ] + @classmethod + def __new__(cls, *args, **kwargs): + + _regulars = [(IntCodes.BOLD, IntCodes.BOLD_DIM_OFF), + (IntCodes.DIM, IntCodes.BOLD_DIM_OFF), + (IntCodes.ITALIC, IntCodes.ITALIC_OFF), + (IntCodes.UNDERLINED, IntCodes.UNDERLINED_OFF), + (IntCodes.DOUBLE_UNDERLINED, IntCodes.UNDERLINED_OFF), + (IntCodes.BLINK_SLOW, IntCodes.BLINK_OFF), + (IntCodes.BLINK_FAST, IntCodes.BLINK_OFF), + (IntCodes.INVERSED, IntCodes.INVERSED_OFF), + (IntCodes.HIDDEN, IntCodes.HIDDEN_OFF), + (IntCodes.CROSSLINED, IntCodes.CROSSLINED_OFF), + (IntCodes.OVERLINED, IntCodes.OVERLINED_OFF), ] for c in _regulars: - self._bind_regular(*c) + cls.bind_regular(*c) - for c in [*COLORS, *HI_COLORS]: - self._bind_regular(c, IntCode.COLOR_OFF) + for c in [*IntCodes.LIST_COLORS, *IntCodes.LIST_HI_COLORS]: + cls.bind_regular(c, IntCodes.COLOR_OFF) - for c in [*BG_COLORS, *BG_HI_COLORS]: - self._bind_regular(c, IntCode.BG_COLOR_OFF) + for c in [*IntCodes.LIST_BG_COLORS, *IntCodes.LIST_BG_HI_COLORS]: + cls.bind_regular(c, IntCodes.BG_COLOR_OFF) - self._bind_complex((IntCode.COLOR_EXTENDED, 5), 1, IntCode.COLOR_OFF) - self._bind_complex((IntCode.COLOR_EXTENDED, 2), 3, IntCode.COLOR_OFF) - self._bind_complex((IntCode.BG_COLOR_EXTENDED, 5), 1, IntCode.BG_COLOR_OFF) - self._bind_complex((IntCode.BG_COLOR_EXTENDED, 2), 3, IntCode.BG_COLOR_OFF) + cls.bind_complex((IntCodes.COLOR_EXTENDED, 5), 1, IntCodes.COLOR_OFF) + cls.bind_complex((IntCodes.COLOR_EXTENDED, 2), 3, IntCodes.COLOR_OFF) + cls.bind_complex((IntCodes.BG_COLOR_EXTENDED, 5), 1, IntCodes.BG_COLOR_OFF) + cls.bind_complex((IntCodes.BG_COLOR_EXTENDED, 2), 3, IntCodes.BG_COLOR_OFF) - def _bind_regular(self, starter_code: int | t.Tuple[int, ...], resetter_code: int): - if starter_code in self._code_to_resetter_map: - raise ConflictError(f"SGR {starter_code} already has a registered resetter") + @classmethod + def bind_regular(cls, starter_code: int|Tuple[int, ...], breaker_code: int): + if starter_code in cls._code_to_breaker_map: + raise RuntimeError(f'Conflict: SGR code {starter_code} already ' + f'has a registered breaker') - self._code_to_resetter_map[starter_code] = SequenceSGR(resetter_code) + cls._code_to_breaker_map[starter_code] = SequenceSGR(breaker_code) - def _bind_complex( - self, starter_codes: t.Tuple[int, ...], param_len: int, resetter_code: int - ): - self._bind_regular(starter_codes, resetter_code) + @classmethod + def bind_complex(cls, starter_codes: Tuple[int, ...], param_len: int, + breaker_code: int): + cls.bind_regular(starter_codes, breaker_code) - if starter_codes in self._complex_code_def: - raise ConflictError(f"SGR {starter_codes} already has a registered resetter") + if starter_codes in cls._complex_code_def: + raise RuntimeError(f'Conflict: SGR complex {starter_codes} already ' + f'has a registered breaker') - self._complex_code_def[starter_codes] = param_len - self._complex_code_max_len = max( - self._complex_code_max_len, len(starter_codes) + param_len - ) + cls._complex_code_def[starter_codes] = param_len + cls._complex_code_max_len = max(cls._complex_code_max_len, + len(starter_codes) + param_len) - def get_closing_seq(self, opening_seq: SequenceSGR) -> SequenceSGR: - closing_seq_params: t.List[int] = [] + @classmethod + def get_closing_seq(cls, opening_seq: SequenceSGR) -> SequenceSGR: + closing_seq_params: List[int] = [] opening_params = copy(opening_seq.params) while len(opening_params): - key_params: int | t.Tuple[int, ...] | None = None + key_params: int|Tuple[int, ...]|None = None - for complex_len in range( - 1, min(len(opening_params), self._complex_code_max_len + 1) - ): + for complex_len in range(1, min(len(opening_params), + cls._complex_code_max_len + 1)): opening_complex_suggestion = tuple(opening_params[:complex_len]) - if opening_complex_suggestion in self._complex_code_def: + if opening_complex_suggestion in cls._complex_code_def: key_params = opening_complex_suggestion complex_total_len = ( - complex_len + self._complex_code_def[opening_complex_suggestion] - ) + complex_len + cls._complex_code_def[opening_complex_suggestion]) opening_params = opening_params[complex_total_len:] break if key_params is None: key_params = opening_params.pop(0) - if key_params not in self._code_to_resetter_map: + if key_params not in cls._code_to_breaker_map: continue - closing_seq_params.extend(self._code_to_resetter_map[key_params].params) + closing_seq_params.extend(cls._code_to_breaker_map[key_params].params) return SequenceSGR(*closing_seq_params) - -_sgr_pairity_registry = _SgrPairityRegistry() - - -def get_closing_seq(opening_seq: SequenceSGR) -> SequenceSGR: - """ - - :param opening_seq: - :return: - """ - return _sgr_pairity_registry.get_closing_seq(opening_seq) - - -def enclose(opening_seq: SequenceSGR, string: str) -> str: - """ - - :param opening_seq: - :param string: - :return: - """ - return f"{opening_seq}{string}{get_closing_seq(opening_seq)}" - - -def make_set_cursor_x_abs(x: int = 1) -> SequenceCSI: - """ - Create :abbr:`CHA (Cursor Horizontal Absolute)` sequence that sets - cursor horizontal position, or column, to ``x``. - - :param x: New cursor horizontal position. - :example: ``ESC [1G`` - """ - if x <= 0: - raise ValueError(f"Invalid x value: {x}, expected x > 0") - return SequenceCSI("G", "CHA", x) - - -def make_erase_in_line(mode: int = 0) -> SequenceCSI: - """ - Create :abbr:`EL (Erase in Line)` sequence that erases a part of the line - or the entire line. Cursor position does not change. - - :param mode: .. :: - - Sequence operating mode. - - - If set to 0, clear from cursor to the end of the line. - - If set to 1, clear from cursor to beginning of the line. - - If set to 2, clear the entire line. - - :example: ``ESC [0K`` - """ - if not (0 <= mode <= 2): - raise ValueError(f"Invalid mode: {mode}, expected [0;2]") - return SequenceCSI("K", "EL", mode) - - -def make_query_cursor_position() -> SequenceCSI: - """ - Create :abbr:`QCP (Query Cursor Position)` sequence that requests an output - device to respond with a structure containing current cursor coordinates - (`RCP `). - - .. warning :: - - Sending this sequence to the terminal may **block** infinitely. Consider - using a thread or set a timeout for the main thread using a signal. - - :example: ``ESC [6n`` - """ - - return SequenceCSI("n", "QCP", 6) - - -def decompose_request_cursor_position(string: str) -> t.Tuple[int, int]|None: - """ - Parse :abbr:`RCP (Report Cursor Position)` sequence that generally comes from - a terminal as a response to `QCP ` sequence and - contains a cursor's current row and column. - - .. note :: - - As the library in general provides sequence assembling methods, but not - the disassembling ones, there is no dedicated class for RCP sequences yet. - - >>> decompose_request_cursor_position('\x1b[18;2R') - (18, 2) - - :param string: Terminal response with a sequence. - :return: Current row and column if the expected sequence exists - in ``string``, *None* otherwise. - """ - if not all(c in string for c in "\x1b[;R"): - return None # input does not contain a valid RCP sequence - - start_idx = string.rfind("\x1b[") - seq = string[start_idx + 2: string.rfind("R") - start_idx] - y, x = seq.split(";", 2) - - try: - return int(y), int(x) - except ValueError: - return None # unexpected results - - -def make_color_256(code: int, bg: bool = False) -> SequenceSGR: - """ - Wrapper for creation of `SequenceSGR` that sets foreground - (or background) to one of 256-color palette value. - - :param code: Index of the color in the palette, 0 -- 255. - :param bg: Set to *True* to change the background color - (default is foreground). - :example: ``ESC [38;5;141m`` - """ - - SequenceSGR.validate_extended_color(code) - key_code = IntCode.BG_COLOR_EXTENDED if bg else IntCode.COLOR_EXTENDED - return SequenceSGR(key_code, IntCode.EXTENDED_MODE_256, code) - - -def make_color_rgb(r: int, g: int, b: int, bg: bool = False) -> SequenceSGR: - """ - Wrapper for creation of `SequenceSGR` operating in True Color mode (16M). - Valid values for ``r``, ``g`` and ``b`` are in range of [0; 255]. This range - linearly translates into [0x00; 0xFF] for each channel. The result - value is composed as "0xRRGGBB". For example, sequence with color of - 0xFF3300 can be created with:: - - make_color_rgb(255, 51, 0) - - :param r: Red channel value, 0 -- 255. - :param g: Blue channel value, 0 -- 255. - :param b: Green channel value, 0 -- 255. - :param bg: Set to *True* to change the background color (default is foreground). - :example: ``ESC [38;2;255;51;0m`` - """ - - [SequenceSGR.validate_extended_color(color) for color in [r, g, b]] - key_code = IntCode.BG_COLOR_EXTENDED if bg else IntCode.COLOR_EXTENDED - return SequenceSGR(key_code, IntCode.EXTENDED_MODE_RGB, r, g, b) - - -def make_hyperlink_part(url: str = None) -> SequenceOSC: - """ - - :param url: - :example: ``ESC ]8;;http://localhost ESC \\`` - """ - return SequenceOSC(IntCode.HYPERLINK, "", (url or "")) - - -def assemble_hyperlink(url: str, label: str = None) -> str: - """ - - :param url: - :param label: - :example: ``ESC ]8;;http://localhost ESC \\Text ESC ]8;; ESC \\`` - """ - return f"{make_hyperlink_part(url)}{label or url}{make_hyperlink_part()}" +_SgrPairityRegistry() + + +class Spans(Registry[Span]): + """ + Registry of span presets. + + .. attention:: + Registry constants are omitted from API doc pages to improve readability + and avoid duplication. Summary list of all presets can be found in + `guide.presets` section of the guide. + """ + + BOLD = Span(IntCodes.BOLD) + DIM = Span(IntCodes.DIM) + ITALIC = Span(IntCodes.ITALIC) + UNDERLINED = Span(IntCodes.UNDERLINED) + BLINK_SLOW = Span(IntCodes.BLINK_SLOW) + BLINK_FAST = Span(IntCodes.BLINK_FAST) + INVERSED = Span(IntCodes.INVERSED) + HIDDEN = Span(IntCodes.HIDDEN) + CROSSLINED = Span(IntCodes.CROSSLINED) + DOUBLE_UNDERLINED = Span(IntCodes.DOUBLE_UNDERLINED) + OVERLINED = Span(IntCodes.OVERLINED) + + BLACK = Span(IntCodes.BLACK) + RED = Span(IntCodes.RED) + GREEN = Span(IntCodes.GREEN) + YELLOW = Span(IntCodes.YELLOW) + BLUE = Span(IntCodes.BLUE) + MAGENTA = Span(IntCodes.MAGENTA) + CYAN = Span(IntCodes.CYAN) + WHITE = Span(IntCodes.WHITE) + + GRAY = Span(IntCodes.GRAY) + HI_RED = Span(IntCodes.HI_RED) + HI_GREEN = Span(IntCodes.HI_GREEN) + HI_YELLOW = Span(IntCodes.HI_YELLOW) + HI_BLUE = Span(IntCodes.HI_BLUE) + HI_MAGENTA = Span(IntCodes.HI_MAGENTA) + HI_CYAN = Span(IntCodes.HI_CYAN) + HI_WHITE = Span(IntCodes.HI_WHITE) + + BG_BLACK = Span(IntCodes.BG_BLACK) + BG_RED = Span(IntCodes.BG_RED) + BG_GREEN = Span(IntCodes.BG_GREEN) + BG_YELLOW = Span(IntCodes.BG_YELLOW) + BG_BLUE = Span(IntCodes.BG_BLUE) + BG_MAGENTA = Span(IntCodes.BG_MAGENTA) + BG_CYAN = Span(IntCodes.BG_CYAN) + BG_WHITE = Span(IntCodes.BG_WHITE) + + BG_GRAY = Span(IntCodes.BG_GRAY) + BG_HI_RED = Span(IntCodes.BG_HI_RED) + BG_HI_GREEN = Span(IntCodes.BG_HI_GREEN) + BG_HI_YELLOW = Span(IntCodes.BG_HI_YELLOW) + BG_HI_BLUE = Span(IntCodes.BG_HI_BLUE) + BG_HI_MAGENTA = Span(IntCodes.BG_HI_MAGENTA) + BG_HI_CYAN = Span(IntCodes.BG_HI_CYAN) + BG_HI_WHITE = Span(IntCodes.BG_HI_WHITE) diff --git a/pytermor/color.py b/pytermor/color.py index 2777888..1f919b8 100644 --- a/pytermor/color.py +++ b/pytermor/color.py @@ -1,917 +1,642 @@ # ----------------------------------------------------------------------------- # pytermor [ANSI formatted terminal output toolset] -# (c) 2022-2023. A. Shavykin <0.delameter@gmail.com> +# (c) 2022. A. Shavykin <0.delameter@gmail.com> # ----------------------------------------------------------------------------- """ .. testsetup:: * - from pytermor.color import * - + from pytermor.color import _ColorIndexed, Color, ColorIndexed16, ColorIndexed256, ColorRGB """ from __future__ import annotations -import dataclasses -import math -import re -import typing as t -from abc import abstractmethod, ABC - -from .ansi import ( - SequenceSGR, - NOOP_SEQ, - HI_COLORS, - BG_HI_COLORS, - make_color_256, - make_color_rgb, -) -from .common import LogicError, CDT - -CT = t.TypeVar("CT", bound="IColor") -""" -Any non-abstract `IColor` type. - -:meta public: - """ - - -class _ColorRegistry(t.Generic[CT], t.Sized): - _TOKEN_SEPARATOR = "-" - _QUERY_SPLIT_REGEX = re.compile(r"[\W_]+|(?<=[a-z])(?=[A-Z0-9])") - - def __init__(self): - self._map: t.Dict[t.Tuple[str], CT] = {} - - def register(self, color: CT, name: str): - primary_tokens = tuple(self._QUERY_SPLIT_REGEX.split(name)) - self._register_pair(color, primary_tokens) - - if not isinstance(color, ColorRGB): - return - for variation in color.variations.values(): - variation_tokens: t.Tuple[str, ...] = ( - *primary_tokens, - *(self._QUERY_SPLIT_REGEX.split(variation.name)), - ) - self._register_pair(variation, variation_tokens) - - def _register_pair(self, color: CT, tokens: t.Tuple[str, ...]): - if tokens not in self._map.keys(): - self._map[tokens] = color - return - - existing_color = self._map.get(tokens) - if color.hex_value == existing_color.hex_value: - return # skipping the duplicate with the same name and value - raise ColorNameConflictError(tokens, existing_color, color) - - def resolve(self, name: str) -> CT: - query_tokens = (*(qt.lower() for qt in self._QUERY_SPLIT_REGEX.split(name)),) - if color := self._map.get(query_tokens, None): - return color - raise LookupError(f"Color '{name}' does not exist") - - def __len__(self) -> int: - return len(self._map) - - -class _ColorIndex(t.Generic[CT], t.Sized): - def __init__(self): - self._map: t.Dict[int, _ColorChannels[CT]] = {} - - def add(self, color: CT, code: int = None): - if code is None: - code = len(self._map) - if code not in self._map.keys(): - self._map[code] = _ColorChannels(color) - return - - existing_color = self._map.get(code).color - if color.hex_value == existing_color.hex_value: - return # skipping the duplicate with the same code and value - raise ColorCodeConflictError(code, existing_color, color) - - def get(self, code: int) -> CT: - if channels := self._map.get(code, None): - return channels.color - raise KeyError(f"Color #{code} does not exist") - - def __len__(self) -> int: - return len(self._map) - - @property - def values(self) -> t.Iterable[_ColorChannels[CT]]: - return self._map.values() - +import logging +from abc import abstractmethod, ABCMeta +from typing import Dict, Tuple, TypeVar, List -class _ColorChannels(t.Generic[CT]): - def __init__(self, color: CT): - self.color: CT = color - self.r, self.g, self.b = self.color.to_rgb() +from .ansi import SequenceSGR, NOOP_SEQ, IntCodes +from .common import LogicError, Registry -@dataclasses.dataclass(frozen=True) -class ApxResult(t.Generic[CT]): - """ - Approximation result. - """ - - color: CT - """ Found `IColor` instance. """ - distance: int - """ Squared sRGB distance from this instance to the approximation target. """ - - @property - def distance_real(self) -> float: - """ - Actual distance from instance to target: - - :math:`distance_{real} = \\sqrt{distance}` - """ - return math.sqrt(self.distance) - - -class IColor(ABC): +class Color(metaclass=ABCMeta): """ Abstract superclass for other ``Colors``. - - :meta private: """ - # class vars # - _registry: _ColorRegistry - _index: _ColorIndex - _approx_cache: t.Dict[int, CT] - - @classmethod - def __new__(cls, *args, **kwargs): - # @TODO find a way to provide a correct constructor signature - # for Color256 etc. instead of this one (for sphinx) - # fmt: off - if not hasattr(cls, "_registry"): cls._registry = _ColorRegistry[cls]() - if not hasattr(cls, "_index"): cls._index = _ColorIndex[cls]() - if not hasattr(cls, "_approx_cache"): cls._approx_cache = dict() - return super().__new__(cls) - # fmt: on - - def __init__(self, hex_value: int, name: str = None): - if hex_value < 0 or hex_value > 0xFFFFFF: - raise ValueError(f"Out of bounds hex value {hex_value:06X}, should be: 0x0 <= hex_value <= 0xFFFFFF") - self._hex_value: int = hex_value - self._name: str | None = name - - def _post_init( - self: CT, code: int | None, register: bool, index: bool, aliases: t.List[str] - ): - if register: - self._register_names(aliases) - if index: - self._index.add(self, code) - - def _register_names(self: CT, aliases: t.List[str] = None): - if not self.name: - return - self._registry.register(self, self.name) - - if not aliases: - return - for alias in aliases: - self._registry.register(self, alias) - - def _make_variations(self: CT, variation_map: t.Dict[int, str] = None): - if not variation_map: - return - - # @TODO rewrite this part later. don't like that entity relationship attributes - # are being set in some indistinct method, not in the constructor. - for vari_hex_value, vari_name in variation_map.items(): - variation = type(self)( - hex_value=vari_hex_value, name=vari_name, register=False, index=True - ) # registration will be made by registry itself - variation._base = self - self._variations[vari_name] = variation - - def __eq__(self, other) -> bool: - if not isinstance(other, self.__class__): - return False - return self._hex_value == other._hex_value - - def format_value(self, prefix: str = "0x") -> str: - """ - Format color value as "0xFFFFFF". + def __init__(self, hex_value: int = None): + self._hex_value: int | None = hex_value - :param prefix: Can be customized. + @staticmethod + def hex_value_to_hsv_channels(hex_value: int) -> Tuple[int, float, float]: """ - return f"{prefix:s}{self._hex_value:06X}" - - @property - def hex_value(self) -> int: - """Color value, e.g. 0x3AEB0C.""" - return self._hex_value - - @property - def name(self) -> str | None: - """Color name, e.g. "navy-blue".""" - return self._name - - def __repr__(self) -> str: - return f"<{self.__class__.__name__}[{self.repr_attrs()}]>" - - @abstractmethod - def repr_attrs(self, verbose: bool = True) -> str: - raise NotImplementedError - - def to_hsv(self) -> t.Tuple[float, float, float]: + Transforms ``hex_value`` in ``0xffffff`` format into tuple of three + numbers corresponding to *hue*, *saturation* and *value* channel values + respectively. *Hue* is within [0, 359] range, *saturation* and *value* are + within [0; 1] range. """ - Wrapper around `hex_to_hsv()` for concrete instance. - - :see: hex_to_hsv() for the details + if not isinstance(hex_value, int): + raise TypeError(f"Argument type should be 'int', got: {type(hex_value)}") + + # https://en.wikipedia.org/wiki/HSL_and_HSV#From_RGB + r, g, b = Color.hex_value_to_rgb_channels(hex_value) + rn, gn, bn = r/255, g/255, b/255 + + vmax = max(rn, gn, bn) + vmin = min(rn, gn, bn) + c = vmax - vmin + v = vmax + + if c == 0: + h = 0 + elif v == rn: + h = 60 * (0 + (gn - bn)/c) + elif v == gn: + h = 60 * (2 + (bn - rn)/c) + elif v == bn: + h = 60 * (4 + (rn - gn)/c) + else: + raise LogicError('Impossible if-branch, algorithm is implemented ' + 'incorrectly') + + if v == 0: + s = 0 + else: + s = c/v + + if h < 0: + h += 360 + + return h, s, v + + @staticmethod + def rgb_channels_to_hex_value(r: int, g: int, b: int) -> int: """ - return hex_to_hsv(self._hex_value) + .. todo :: - def to_rgb(self) -> t.Tuple[int, int, int]: + :param r: + :param g: + :param b: + :return: """ - Wrapper around `to_rgb()` for concrete instance. + return (r << 16) + (g << 8) + b - :see: to_rgb() for the details + @staticmethod + def hex_value_to_rgb_channels(hex_value: int) -> Tuple[int, int, int]: """ - return hex_to_rgb(self._hex_value) + Transforms ``hex_value`` in ``0xffffff`` format into tuple of three + integers corresponding to *red*, *blue* and *green* channel value + respectively. Values are within [0; 255] range. - @abstractmethod - def to_sgr(self, bg: bool, upper_bound: t.Type[IColor] = None) -> SequenceSGR: + >>> Color.hex_value_to_rgb_channels(0x80ff80) + (128, 255, 128) + >>> Color.hex_value_to_rgb_channels(0x000001) + (0, 0, 1) """ - Make an `SGR sequence` out of `IColor`. Used by `SgrRenderer`. + if not isinstance(hex_value, int): + raise TypeError(f"Argument type should be 'int', got: {type(hex_value)}") - :param bg: Set to *True* if required SGR should change the background color, or - *False* for the foreground (=text) color. - :param upper_bound: Required result `IColor` type upper boundary, i.e., the - maximum acceptable color class, which will be the basis for - SGR being made. See `Color256.to_sgr()` for the details. - """ - raise NotImplementedError + return ((hex_value & 0xff0000) >> 16, + (hex_value & 0xff00) >> 8, + (hex_value & 0xff)) @abstractmethod - def to_tmux(self, bg: bool) -> str: - """ - Make a tmux markup directive, which will change the output color to - this color's value (after tmux processes and prints it). Used by `TmuxRenderer`. - - :param bg: Set to *True* if required tmux directive should change the background - color, or *False* for the foreground (=text) color. - """ + def to_sgr(self, bg: bool = False) -> SequenceSGR: raise NotImplementedError - @classmethod - def resolve(cls, name: str) -> CT: - """ - Case-insensitive search through registry contents. + @property + def hex_value(self) -> int | None: + return self._hex_value - :see: `resolve_color()` for the details - :param name: `IColor` name to search for. - """ - if not hasattr(cls, "_registry"): - raise LogicError( - "Registry is empty. Did you call an abstract class' method?" - ) - return cls._registry.resolve(name) + def format_value(self, prefix: str|None = '0x', noop_label: str = '~') -> str: + if self._hex_value is None: + return noop_label + return f'{prefix or "":s}{self._hex_value:06x}' - @classmethod - def find_closest(cls, hex_value: int) -> CT: - """ - Search and return nearest to ``hex_value`` color instance. - :see: `color.find_closest()` for the details - :param hex_value: Target RGB value. - """ - if not hasattr(cls, "_index"): - raise LogicError("Index is empty. Did you call an abstract class' method?") +TypeColor = TypeVar('TypeColor', 'ColorIndexed16', 'ColorIndexed256', 'ColorRGB') +""" Any non-abstract `Color` type. """ - if hex_value in cls._approx_cache.keys(): - return cls._approx_cache.get(hex_value) - closest = cls._find_neighbours(hex_value)[0].color - cls._approx_cache[hex_value] = closest - return closest +class _ColorIndexed(Color, metaclass=ABCMeta): + _approximator: Approximator = None - @classmethod - def approximate(cls, hex_value: int, max_results: int = 1) -> t.List[ApxResult[CT]]: - """ - Search for the colors nearest to ``hex_value`` and return the first ``max_results``. + def __init__(self, hex_value: int = None): + super().__init__(hex_value) - :see: `color.approximate()` for the details - :param hex_value: Target RGB value. - :param max_results: Result limit. - """ - if not hasattr(cls, "_index"): - raise LogicError("Index is empty. Did you call an abstract class' method?") - return cls._find_neighbours(hex_value)[:max_results] + if not self.__class__._approximator: + self.__class__._approximator = Approximator() + self.__class__._approximator.add_to_map(self) @classmethod - def _find_neighbours(cls: t.Type[CT], hex_value: int) -> t.List[ApxResult[CT]]: + def find_closest(cls, hex_value: int) -> _ColorIndexed: """ - Iterate the registered colors table and compute the squared euclidean distance - from argument to each color of the palette. Sort the results and return them. + Wrapper for `Approximator.find_closest()`. - **sRGB euclidean distance** - https://en.wikipedia.org/wiki/Color_difference#sRGB - https://stackoverflow.com/a/35114586/5834973 + :param hex_value: Integer color value in ``0xffffff`` format. + :return: Nearest found `_ColorIndexed` instance. - :param hex_value: Target RGB value. + >>> _ColorIndexed.find_closest(0xd9dbdb) + _ColorIndexed[code=253, 0xdadada] """ - input_r, input_g, input_b = hex_to_rgb(hex_value) - result: t.List[ApxResult[CT]] = list() - - for channels in cls._index.values: - distance_sq: int = ( - pow(channels.r - input_r, 2) - + pow(channels.g - input_g, 2) - + pow(channels.b - input_b, 2) - ) - result.append(ApxResult(channels.color, distance_sq)) - return sorted(result, key=lambda r: r.distance) - - -class Color16(IColor): - """ - Variant of a `IColor` operating within the most basic color set - -- **Xterm-16**. Represents basic color-setting SGRs with primary codes - 30-37, 40-47, 90-97 and 100-107 (see `guide.presets.color16`). - - .. note :: - - Arguments ``register``, ``index`` and ``aliases`` - are *kwonly*-type args. - - :param hex_value: Color RGB value, e.g. 0x800000. - :param code_fg: Int code for a foreground color setup, e.g. 30. - :param code_bg: Int code for a background color setup. e.g. 40. - :param name: Name of the color, e.g. "red". - :param register: If *True*, add color to registry for resolving by name. - :param index: If *True*, add color to approximation index. - :param aliases: Alternative color names (used in `resolve_color()`). - """ + return cls._approximator.find_closest(hex_value) - def __init__( - self, - hex_value: int, - code_fg: int, - code_bg: int, - name: str = None, - *, - register: bool = False, - index: bool = False, - aliases: t.List[str] = None, - ): - super().__init__(hex_value, name) - self._code_fg: int = code_fg - self._code_bg: int = code_bg - self._post_init(self._code_fg, register, index, aliases) - @property - def code_fg(self) -> int: - """Int code for a foreground color setup, e.g. 30.""" - return self._code_fg - - @property - def code_bg(self) -> int: - """Int code for a background color setup. e.g. 40.""" - return self._code_bg - - @classmethod - def get_by_code(cls, code: int) -> Color16: - """ - Get a `Color16` instance with specified code. Only *foreground* (=text) colors - are indexed, therefore it is impossible to look up for a `Color16` with - given background color. - - :param code: Foreground integer code to look up for (see - `guide.presets.color16`). - :raises KeyError: If no color with specified code is found. - """ - return cls._index.get(code) - - def __eq__(self, other) -> bool: - if not isinstance(other, self.__class__): - return False - return ( - self._hex_value == other._hex_value - and self._code_bg == other._code_bg - and self._code_fg == other._code_fg - ) - - def repr_attrs(self, verbose: bool = True) -> str: - # question mark after color value indicates that we cannot be 100% sure - # about the exact value of xterm-16 colors, as they are configurable and - # depend on terminal theme and settings. that's not the case for xterm-256, - # though -- it's almost guaranteed to have the same color nearly everywhere. - # the exceptions are rare and include color mapping at low level, e.g., - # ``tmux`` with specifically configured terminal capability overrides. - # that's not something that you'd expect from a regular user, anyway. - code = f"#{self._code_fg}" - value = f"{self.format_value('')}?" - - params = [self._name] - if verbose: - params = [code, value] + params - return ",".join(str(s) for s in filter(None, params)) - - def to_sgr(self, bg: bool, upper_bound: t.Type[IColor] = None) -> SequenceSGR: +class ColorIndexed16(_ColorIndexed): + def __init__(self, hex_value: int = None, code_fg: int = None, code_bg: int = None): + self._code_fg = code_fg + self._code_bg = code_bg + super().__init__(hex_value) + + def to_sgr(self, bg: bool = False) -> SequenceSGR: if bg: return SequenceSGR(self._code_bg) return SequenceSGR(self._code_fg) - def to_tmux(self, bg: bool) -> str: - if self._name is None: - raise LogicError("Translation to tmux format failed: color name required") - code = self._code_bg if bg else self._code_fg - is_hi = code in HI_COLORS or code in BG_HI_COLORS - tmux_name = ("bright" if is_hi else "") + self._name.lower().replace("hi-", "") - return tmux_name - - -class Color256(IColor): - """ - Variant of a `IColor` operating within relatively modern **Xterm-256** - indexed color table. Represents SGR complex codes ``38;5;*`` and ``48;5;*`` - (see `guide.presets.color256`). - - .. note :: - - Arguments ``register``, ``index``, ``aliases`` and ``color16_equiv`` - are *kwonly*-type args. - - :param hex_value: Color RGB value, e.g. 0x5f0000. - :param code: Int code for a color setup, e.g. 52. - :param name: Name of the color, e.g. "dark-red". - :param register: If *True*, add color to registry for resolving by name. - :param index: If *True*, add color to approximation index. - :param aliases: Alternative color names (used in `resolve_color()`). - :param color16_equiv: - `Color16` counterpart (applies only to codes 0-15). - """ - - def __init__( - self, - hex_value: int, - code: int, - name: str = None, - *, - register: bool = False, - index: bool = False, - aliases: t.List[str] = None, - color16_equiv: Color16 = None, - ): - super().__init__(hex_value, name) - self._code: int | None = code - self._color16_equiv: Color16 | None = None - if color16_equiv: - self._color16_equiv = Color16.get_by_code(color16_equiv.code_fg) - self._post_init(self._code, register, index, aliases) - - def to_sgr(self, bg: bool, upper_bound: t.Type[IColor] = None) -> SequenceSGR: - """ - Make an `SGR sequence` out of `IColor`. Used by `SgrRenderer`. - - Each `IColor` type represents one SGR type in the context of colors. For - example, if ``upper_bound`` is set to `Color16`, the resulting SGR will always - be one of 16-color index table, even if the original color was of different - type -- it will be approximated just before the SGR assembling. - - The reason for this is the necessity to provide a similar look for all users - with different terminal settings/ capabilities. When the library sees that - user's output device supports 256 colors only, it cannot assemble True Color - SGRs, because they will be ignored (if we are lucky), or displayed in a - glitchy way, or mess up the output completely. The good news is that the - process is automatic and in most cases the library will manage the - transformations by itself. If it's not the case, the developer can correct the - behaviour by overriding the renderers' output mode. See `SgrRenderer` and - `OutputMode` docs. - - :param bg: Set to *True* if required SGR should change the background color, or - *False* for the foreground (=text) color. - :param upper_bound: Required result `IColor` type upper boundary, i.e., the - maximum acceptable color class, which will be the basis for - SGR being made. - """ - if upper_bound is ColorRGB: - return make_color_rgb(*self.to_rgb(), bg) - - if upper_bound is Color256 or upper_bound is None: - return make_color_256(self._code, bg) - - if self._color16_equiv: - return self._color16_equiv.to_sgr(bg, upper_bound) - - return Color16.find_closest(self.hex_value).to_sgr(bg, upper_bound) - - def to_tmux(self, bg: bool) -> str: - return f"colour{self._code}" - - @property - def code(self) -> int: - """Int code for a color setup, e.g. 52.""" - return self._code - - @classmethod - def get_by_code(cls, code: int) -> Color256: - """ - Get a `Color256` instance with specified code (=position in the index). - - :param code: Color code to look up for (see `guide.presets.color256`). - :raises KeyError: If no color with specified code is found. - """ - return cls._index.get(code) - def __eq__(self, other) -> bool: if not isinstance(other, self.__class__): return False - return self._hex_value == other._hex_value and self._code == other._code - - def repr_attrs(self, verbose: bool = True) -> str: - code = f"X{self._code}" - value = self.format_value("") - - params = [code+f"[{value}]"] - if verbose: - params = [code, value, self._name] - return ",".join(str(s) for s in filter(None, params)) + return (self._hex_value == other._hex_value + and self._code_bg == other._code_bg + and self._code_fg == other._code_fg) + + def __repr__(self): + return f'{self.__class__.__name__}[' \ + f'fg={self._code_fg!r}, ' \ + f'bg={self._code_bg!r}, ' \ + f'{self.format_value()}]' + +class ColorIndexed256(_ColorIndexed): + """ .. todo :: get color by int code """ + _code_map: Dict[int, ColorIndexed256] = dict() + + def __init__(self, hex_value: int = None, code: int = None): + self._code = code + super().__init__(hex_value) -class ColorRGB(IColor): - """ - Variant of a `IColor` operating within RGB color space. Presets include - `es7s named colors `, a unique collection of colors - compiled from several known sources after careful selection. However, - it's not limited to aforementioned color list and can be easily extended. + if not self._code_map.get(self._code): + self._code_map[self._code] = self + else: + logging.warning(f'Indexed color duplicate by code {self._code} ' + f'detected: {self}. It was NOT added to the index.') - .. note :: + def to_sgr(self, bg: bool = False) -> SequenceSGR: + if self._hex_value is None: + return NOOP_SEQ + return SequenceSGR.init_color_indexed(self._code, bg=bg) - Arguments ``register``, ``index``, ``aliases`` and ``variation_map`` - are *kwonly*-type args. + def __eq__(self, other) -> bool: + if not isinstance(other, self.__class__): + return False + return (self._hex_value == other._hex_value + and self._code == other._code) + def __repr__(self): + return f'{self.__class__.__name__}[' \ + f'code={self._code}, ' \ + f'{self.format_value()}]' - :param hex_value: Color RGB value, e.g. 0x73a9c2. - :param name: Name of the color, e.g. "moonstone-blue". - :param register: If *True*, add color to registry for resolving by name. - :param index: If *True*, add color to approximation index. - :param aliases: Alternative color names (used in `resolve_color()`). - :param variation_map: Mapping {*int*: *str*}, where keys are hex values, - and values are variation names. - """ - def __init__( - self, - hex_value: int, - name: str = None, - *, - register: bool = False, - index: bool = False, - aliases: t.List[str] = None, - variation_map: t.Dict[int, str] = None, - ): - super().__init__(hex_value, name) - self._base: CT | None = None - self._variations: t.Dict[str, CT] = {} - self._make_variations(variation_map) - self._post_init(None, register, index, aliases) - - def to_sgr(self, bg: bool, upper_bound: t.Type[IColor] = None) -> SequenceSGR: - if upper_bound is ColorRGB or upper_bound is None: - return make_color_rgb(*self.to_rgb(), bg) - - return Color256.find_closest(self._hex_value).to_sgr(bg, upper_bound) - - def to_tmux(self, bg: bool) -> str: # rgb hex format should be lower cased! - return self.format_value("#").lower() +class ColorRGB(Color): + def to_sgr(self, bg: bool = False) -> SequenceSGR: + if self._hex_value is None: + return NOOP_SEQ + return SequenceSGR.init_color_rgb( + *self.hex_value_to_rgb_channels(self._hex_value), bg=bg) def __eq__(self, other) -> bool: if not isinstance(other, self.__class__): return False return self._hex_value == other._hex_value - def repr_attrs(self, verbose: bool = True) -> str: - value = self.format_value("") - - params = [value] - if verbose: - params += [self.name] - return ",".join(str(s) for s in filter(None, params)) - - @property - def base(self) -> CT | None: - """Parent color for color variations. Empty for regular colors.""" - return self._base - - @property - def variations(self) -> t.Dict[str, CT]: - """ - List of color variations. *Variation* of a color is a similar color with - almost the same name, but with differing suffix. The main idea of variations - is to provide a basis for fuzzy searching, which will return several results - for one query; i.e., when the query matches a color with variations, the whole - color family can be considered a match, which should increase searching speed. - """ - return self._variations - - -class _NoopColor(IColor): - def __init__(self): - super().__init__(0) + def __repr__(self): + return f'{self.__class__.__name__}[{self.format_value()}]' - def __bool__(self) -> bool: - return False - def to_sgr(self, bg: bool, upper_bound: t.Type[IColor] = None) -> SequenceSGR: - return NOOP_SEQ - - def to_tmux(self, bg: bool) -> str: - return "" - - @property - def hex_value(self) -> int: - raise LogicError("No color for NO-OP instance") - - def format_value(self, prefix: str = "0x") -> str: - return (prefix if "=" in prefix else "") + "NOP" - - def repr_attrs(self, verbose: bool = True) -> str: - return self.format_value() - - -NOOP_COLOR = _NoopColor() -""" -Special `IColor` instance always rendering into empty string. -""" - - -def resolve_color(subject: CDT, color_type: t.Type[CT] = None) -> CT: - """ - Case-insensitive search through registry contents. Search is performed for - `IColor` instance named as specified in ``subject`` argument, and of specified - ``color_type``, or for any type if argument is omitted: first it will be performed - in the registry of `Color16` class, then -- in `Color256`, and, if previous two - were unsuccessful, in the largest `ColorRGB` registry. Therefore, the return value - could be any of these types: - - >>> resolve_color('red') - - - If ``color_type`` is `ColorRGB` or if it is omitted, there is one more way - to specify a color: in form of a hexadecimal value "#RRGGBB" (or in short form, as - "#RGB"), as well as just use an *int* in [0x0; 0xFFFFFF] range. In this case no - actual searching is performed, and a new nameless instance of `ColorRGB` is - created and returned. - - >>> resolve_color("#333") - - >>> resolve_color(0xfafef0) - - - Color names are stored in registries as tokens, which allows to use any form of - input and get the correct result regardless. The only requirement is to split the - words in any matter, so that tokenizer could distinguish the words from each other: - - >>> resolve_color('deep-sky-blue-7') - - >>> resolve_color('DEEP_SKY_BLUE_7') - - >>> resolve_color('DeepSkyBlue7') - - - >>> resolve_color('deepskyblue7') - Traceback (most recent call last): - LookupError: Color 'deepskyblue7' was not found in any of registries - - :param str|int subject: - `IColor` name or hex value to search for. See `CDT`. - :param color_type: Target color type (`Color16`, `Color256` or `ColorRGB`). - :raises LookupError: If nothing was found in either of registries. - :return: `IColor` instance with specified name or value. +class Approximator: """ - def subject_as_hex(): - nonlocal subject - if isinstance(subject, int): - return subject - elif re.fullmatch(r"#[\da-f]{3}([\da-f]{3})?", subject, flags=re.IGNORECASE): - subject = subject[1:] - if len(subject) == 3: - # 3-digit hex notation, basically #RGB -> #RRGGBB - # https://www.quackit.com/css/color/values/css_hex_color_notation_3_digits.cfm - subject = "".join(2*c for c in subject) - return int(subject, 16) - return None - - if (hex_value := subject_as_hex()) is not None: - if color_type is None or color_type == ColorRGB: - return ColorRGB(hex_value) - - color_types = [color_type] if color_type else [Color16, Color256, ColorRGB] - for color_cls in color_types: - try: - return color_cls.resolve(str(subject)) - except LookupError: - continue - raise LookupError(f"Color '{subject}' was not found in any of registries") - - -def find_closest(hex_value: int, color_type: t.Type[CT] = None) -> CT: + Internal class containing a dictionary of registred `colors <_ColorIndexed>` indexed + by hex code along with cached nearest color search results to avoid unnecessary + instance copies and search repeats. """ - Search and return nearest to ``hex_value`` instance of specified ``color_type``. - If `color_type` is omitted, search for the closest `Color256` element. - - Method is useful for finding applicable color alternatives if user's - terminal is incapable of operating in more advanced mode. Usually it is - done by the library automatically and transparently for both the developer - and the end-user. - - .. note :: - - This method caches the results, i.e., the same search query will from then - onward result in the same return value without the necessity of iterating - through the color index. If that's not applicable, use similar method - `approximate()`, which is unaware of caching mechanism altogether. - - :param hex_value: Target color RGB value. - :param color_type: Target color type (`Color16`, `Color256` or `ColorRGB`). - :return: Nearest to ``hex_value`` color instance of specified type. - """ - return (color_type or Color256).find_closest(hex_value) - - -def approximate( - hex_value: int, color_type: t.Type[CT] = None, max_results: int = 1 -) -> t.List[ApxResult[CT]]: - """ - Search for nearest to ``hex_value`` colors of specified ``color_type`` and - return the first ``max_results`` of them. If `color_type` is omitted, search - for the closest `Color256` elements. This method is similar to the - `find_closest()`, although they differ in some aspects: - - - `approximate()` can return more than one result; - - `approximate()` returns not just a `IColor` instance(s), but also a - number equal to squared distance to the target color for each of them; - - `find_closest()` caches the results, while `approximate()` ignores - the cache completely. - - :param hex_value: Target color RGB value. - :param color_type: Target color type (`Color16`, `Color256` or `ColorRGB`). - :param max_results: Return no more than ``max_results`` items. - :return: Pairs of closest `IColor` instance(s) found with their distances - to the target color, sorted by distance descending, i.e., element - at index 0 is the closest color found, paired with its distance - to the target; element with index 1 is second-closest color - (if any) and corresponding distance value, etc. - """ - return (color_type or Color256).approximate(hex_value, max_results) - - -def hex_to_rgb(hex_value: int) -> t.Tuple[int, int, int]: - """ - Transforms ``hex_value`` in *int* format into a tuple of three - integers corresponding to **red**, **blue** and **green** channel value - respectively. Values are within [0; 255] range. - - >>> hex_to_rgb(0x80ff80) - (128, 255, 128) - - :param hex_value: RGB value. - :returns: R, G, B channel values correspondingly. - """ - if not isinstance(hex_value, int): - raise TypeError(f"Argument type should be 'int', got: {type(hex_value)}") - - return ((hex_value & 0xFF0000) >> 16, (hex_value & 0xFF00) >> 8, (hex_value & 0xFF)) - - -def rgb_to_hex(r: int, g: int, b: int) -> int: - """ - Transforms RGB value in a three-integers form ([0; 255], [0; 255], [0; 255]) - to an one-integer form. - - >>> hex(rgb_to_hex(0, 128, 0)) - '0x8000' - - :param r: value of red channel. - :param g: value of green channel. - :param b: value of blue channel. - :return: RGB value. - """ - return (r << 16) + (g << 8) + b + def __init__(self): + """ + Called in `Color`-type class constructors. Each `Color` type should have + class variable with instance of `Approximator` and create it by itself if it's + not present. + """ + self._lookup_table: Dict[int, _ColorIndexed] = dict() + self._approximation_cache: Dict[int, _ColorIndexed] = dict() -def hsv_to_rgb(h: float, s: float, v: float) -> t.Tuple[int, int, int]: - """ - Transforms HSV value in three-floats form (where 0 <= h < 360, 0 <= s <= 1, - and 0 <= v <= 1) into RGB three-integer form ([0; 255], [0; 255], [0; 255]). + def add_to_map(self, color: _ColorIndexed): + """ + Called from `_ColorIndexed` constructors. Add a new element in color + lookup table if it wasn't there, and then drop cached search results + as they are most probably useless after registering a new color (i.e. + now there will be better result for at least one cached value). - >>> hsv_to_rgb(270, 2/3, 0.75) - (128, 64, 192) + :param color: `Color` instance being created. + """ + if color.hex_value is None: + return - :param h: hue channel value. - :param s: saturation channel value. - :param v: value channel value. - :return: R, G, B channel values correspondingly. - """ - h = 0.0 if h == 360.0 else h / 60.0 - fract = h - math.floor(h) - - p = v * (1.0 - s) - q = v * (1.0 - s * fract) - t = v * (1.0 - s * (1.0 - fract)) - - if 0.0 <= h < 1.0: - r, g, b = v, t, p - elif 1.0 <= h < 2.0: - r, g, b = q, v, p - elif 2.0 <= h < 3.0: - r, g, b = p, v, t - elif 3.0 <= h < 4.0: - r, g, b = p, q, v - elif 4.0 <= h < 5.0: - r, g, b = t, p, v - elif 5.0 <= h < 6.0: - r, g, b = v, p, q - else: - r, g, b = 0, 0, 0 - - r, g, b = (math.ceil(255 * c) for c in (r, g, b)) - return r, g, b - - -def rgb_to_hsv(r: int, g: int, b: int) -> t.Tuple[float, float, float]: - """ - Transforms RGB value in a three-integers form ([0; 255], [0; 255], [0; 255]) to an - HSV in three-floats form such as (0 <= h < 360, 0 <= s <= 1, and 0 <= v <= 1). + if color.hex_value not in self._lookup_table.keys(): + self._approximation_cache.clear() + self._lookup_table[color.hex_value] = color - >>> rgb_to_hsv(0, 0, 255) - (240.0, 1.0, 1.0) + def find_closest(self, hex_value: int) -> _ColorIndexed: + """ + Search for nearest to ``hex_value`` registered color. Is used by + `SgrRenderer` to find supported color alternatives in case user's terminal is + incapable of operating in better mode. + + :param hex_value: Color value in RGB format. + :return: Nearest to ``hex_value`` registered ``_ColorIndexed``. + If no colors of required type were created (table and cache + are empty), ``NOOP_COLOR`` is returned. + """ + if hex_value in self._approximation_cache.keys(): + return self._approximation_cache.get(hex_value) - :param r: value of red channel. - :param g: value of green channel. - :param b: value of blue channel. - :returns: H, S, V channel values correspondingly. - """ - # fmt: off - # https://en.wikipedia.org/wiki/HSL_and_HSV#From_RGB + if len(self._approximation_cache) == 0: # there was on-addition cache reset + self._approximation_cache = self._lookup_table.copy() - rn, gn, bn = r / 255, g / 255, b / 255 - vmax = max(rn, gn, bn) - vmin = min(rn, gn, bn) - c = vmax - vmin - v = vmax + if len(self._approximation_cache) == 0: + # rare case when `find_closest` classmethod is called from `Color` type + # without registered instances, but it's still possible (for example, + # developer can interrupt preset creation or just comment it out) + logging.warning('Approximation cache is empty') + return NOOP_COLOR_INDEXED - h = 0 - if c == 0: pass - elif v == rn: h = 60 * (0 + (gn - bn) / c) - elif v == gn: h = 60 * (2 + (bn - rn) / c) - elif v == bn: h = 60 * (4 + (rn - gn) / c) + closest = self.approximate(hex_value)[0] + self._approximation_cache[hex_value] = closest + return closest - if v == 0: s = 0 - else: s = c / v + def approximate(self, hex_value: int, max_results: int = 1) -> List[_ColorIndexed]: + """ + Core color approximation method. Iterate the registred colors table, or + *lookup table*, and compute the euclidean distance from argument to each + color of the palette. Sort the results and return the first + ```` of them. + + .. note:: + It's not guaranteed that this method will **always** succeed in + searching (the result list can be empty). Consider using `find_closest` + instead, if you really want to be sure that at least some color will + be returned. Another option is to use special "color" named `NOOP_COLOR`. + + .. todo :: rewrite using HSV distance? + + :param hex_value: Color RGB value. + :param max_results: Maximum amount of values to return. + :return: Closest `_ColorIndexed` instances found, sorted by color + distance descending (i.e. 0th element is always the + closest to the input value). + """ + input_r, input_g, input_b = Color.hex_value_to_rgb_channels(hex_value) + result: List[Tuple[_ColorIndexed, float]] = list() - if h < 0: h += 360 + for cached_hex, cached_color in self._lookup_table.items(): + # sRGB euclidean distance + # https://en.wikipedia.org/wiki/Color_difference#sRGB + # https://stackoverflow.com/a/35114586/5834973 + map_r, map_g, map_b = Color.hex_value_to_rgb_channels(cached_hex) + distance_sq = (pow(map_r - input_r, 2) + + pow(map_g - input_g, 2) + + pow(map_b - input_b, 2)) - return h, s, v - # fmt: on + result.append((cached_color, distance_sq)) + if len(result) == 0: + # normally it's impossible to get here; this exception almost + # certainly means that there is a bug somewhere in this class. + raise LogicError(f'There are ' # pragma: no cover + f'no registred _ColorIndexed instances') -def hex_to_hsv(hex_value: int) -> t.Tuple[float, float, float]: - """ - Transforms ``hex_value`` in *int* form into a tuple of three numbers - corresponding to **hue**, **saturation** and **value** channel values respectively. - Hue is within [0, 359] range, both saturation and value are within [0; 1] range. + sorted_result = sorted(result, key=lambda r: r[1]) + return [c for c, _ in sorted_result[:max_results]] - >>> hex_to_hsv(0x999999) - (0, 0.0, 0.6) + def __repr__(self): + return f'{self.__class__.__name__}[' \ + f'lookup {len(self._lookup_table)}, ' \ + f'cached {len(self._approximation_cache)}]' - :param hex_value: RGB value. - :returns: H, S, V channel values correspondingly. - """ - return rgb_to_hsv(*hex_to_rgb(hex_value)) +NOOP_COLOR_INDEXED = ColorIndexed16() +""" +Special instance of `ColorIndexed16` class always rendering into empty string. +""" -def hsv_to_hex(h: float, s: float, v: float) -> int: - """ - Transforms HSV value in three-floats form (where 0 <= h < 360, 0 <= s <= 1, - and 0 <= v <= 1) into an one-integer form. +NOOP_COLOR = ColorRGB() +""" +Special instance of `ColorRGB` class always rendering into empty string. +""" - >>> hex(hsv_to_hex(90, 0.5, 0.5)) - '0x608040' - :param h: hue channel value. - :param s: saturation channel value. - :param v: value channel value. - :return: RGB value. +class Colors(Registry[TypeColor]): """ - return rgb_to_hex(*hsv_to_rgb(h, s, v)) - - -class ColorNameConflictError(Exception): - def __init__(self, tokens: t.Tuple[str], existing_color: CT, new_color: CT): - msg = f"Color '{new_color.name}' -> {tokens} already exists" - super().__init__(msg, [existing_color, new_color]) - - -class ColorCodeConflictError(Exception): - def __init__(self, code: int, existing_color: CT, new_color: CT): - msg = f"Color #{code} already exists" - super().__init__(msg, existing_color, new_color) + Registry of colors presets (`ColorIndexed16`, `ColorIndexed256`, `ColorRGB`). + + .. attention:: + Registry constants are omitted from API doc pages to improve readability + and avoid duplication. Summary list of all presets can be found in + `guide.presets` section of the guide. + """ + + # ---------------------------------- GENERATED --------------------------------- + + BLACK = ColorIndexed16(0x000000, IntCodes.BLACK, IntCodes.BG_BLACK) + RED = ColorIndexed16(0x800000, IntCodes.RED, IntCodes.BG_RED) + GREEN = ColorIndexed16(0x008000, IntCodes.GREEN, IntCodes.BG_GREEN) + YELLOW = ColorIndexed16(0x808000, IntCodes.YELLOW, IntCodes.BG_YELLOW) + BLUE = ColorIndexed16(0x000080, IntCodes.BLUE, IntCodes.BG_BLUE) + MAGENTA = ColorIndexed16(0x800080, IntCodes.MAGENTA, IntCodes.BG_MAGENTA) + CYAN = ColorIndexed16(0x008080, IntCodes.CYAN, IntCodes.BG_CYAN) + WHITE = ColorIndexed16(0xc0c0c0, IntCodes.WHITE, IntCodes.BG_WHITE) + GREY = ColorIndexed16(0x808080, IntCodes.GRAY, IntCodes.BG_GRAY) + HI_RED = ColorIndexed16(0xff0000, IntCodes.HI_RED, IntCodes.BG_HI_RED) + HI_GREEN = ColorIndexed16(0x00ff00, IntCodes.HI_GREEN, IntCodes.BG_HI_GREEN) + HI_YELLOW = ColorIndexed16(0xffff00, IntCodes.HI_YELLOW, IntCodes.BG_HI_YELLOW) + HI_BLUE = ColorIndexed16(0x0000ff, IntCodes.HI_BLUE, IntCodes.BG_HI_BLUE) + HI_MAGENTA = ColorIndexed16(0xff00ff, IntCodes.HI_MAGENTA, IntCodes.BG_HI_MAGENTA) + HI_CYAN = ColorIndexed16(0x00ffff, IntCodes.HI_CYAN, IntCodes.BG_HI_CYAN) + HI_WHITE = ColorIndexed16(0xffffff, IntCodes.HI_WHITE, IntCodes.BG_HI_WHITE) + + GREY_0 = ColorIndexed256(0x000000, 16) + NAVY_BLUE = ColorIndexed256(0x00005f, 17) + DARK_BLUE = ColorIndexed256(0x000087, 18) + BLUE_3 = ColorIndexed256(0x0000af, 19) + BLUE_2 = ColorIndexed256(0x0000d7, 20) # Blue3 + BLUE_1 = ColorIndexed256(0x0000ff, 21) + DARK_GREEN = ColorIndexed256(0x005f00, 22) + DEEP_SKY_BLUE_7 = ColorIndexed256(0x005f5f, 23) # DeepSkyBlue4 + DEEP_SKY_BLUE_6 = ColorIndexed256(0x005f87, 24) # DeepSkyBlue4 + DEEP_SKY_BLUE_5 = ColorIndexed256(0x005faf, 25) # DeepSkyBlue4 + DODGER_BLUE_3 = ColorIndexed256(0x005fd7, 26) + DODGER_BLUE_2 = ColorIndexed256(0x005fff, 27) + GREEN_5 = ColorIndexed256(0x008700, 28) # Green4 + SPRING_GREEN_4 = ColorIndexed256(0x00875f, 29) + TURQUOISE_4 = ColorIndexed256(0x008787, 30) + DEEP_SKY_BLUE_4 = ColorIndexed256(0x0087af, 31) # DeepSkyBlue3 + DEEP_SKY_BLUE_3 = ColorIndexed256(0x0087d7, 32) + DODGER_BLUE_1 = ColorIndexed256(0x0087ff, 33) + GREEN_4 = ColorIndexed256(0x00af00, 34) # Green3 + SPRING_GREEN_5 = ColorIndexed256(0x00af5f, 35) # SpringGreen3 + DARK_CYAN = ColorIndexed256(0x00af87, 36) + LIGHT_SEA_GREEN = ColorIndexed256(0x00afaf, 37) + DEEP_SKY_BLUE_2 = ColorIndexed256(0x00afd7, 38) + DEEP_SKY_BLUE_1 = ColorIndexed256(0x00afff, 39) + GREEN_3 = ColorIndexed256(0x00d700, 40) + SPRING_GREEN_3 = ColorIndexed256(0x00d75f, 41) + SPRING_GREEN_6 = ColorIndexed256(0x00d787, 42) # SpringGreen2 + CYAN_3 = ColorIndexed256(0x00d7af, 43) + DARK_TURQUOISE = ColorIndexed256(0x00d7d7, 44) + TURQUOISE_2 = ColorIndexed256(0x00d7ff, 45) + GREEN_2 = ColorIndexed256(0x00ff00, 46) # Green1 + SPRING_GREEN_2 = ColorIndexed256(0x00ff5f, 47) + SPRING_GREEN_1 = ColorIndexed256(0x00ff87, 48) + MEDIUM_SPRING_GREEN = ColorIndexed256(0x00ffaf, 49) + CYAN_2 = ColorIndexed256(0x00ffd7, 50) + CYAN_1 = ColorIndexed256(0x00ffff, 51) + DARK_RED_2 = ColorIndexed256(0x5f0000, 52) # DarkRed + DEEP_PINK_8 = ColorIndexed256(0x5f005f, 53) # DeepPink4 + PURPLE_5 = ColorIndexed256(0x5f0087, 54) # Purple4 + PURPLE_4 = ColorIndexed256(0x5f00af, 55) + PURPLE_3 = ColorIndexed256(0x5f00d7, 56) + BLUE_VIOLET = ColorIndexed256(0x5f00ff, 57) + ORANGE_4 = ColorIndexed256(0x5f5f00, 58) + GREY_37 = ColorIndexed256(0x5f5f5f, 59) + MEDIUM_PURPLE_7 = ColorIndexed256(0x5f5f87, 60) # MediumPurple4 + SLATE_BLUE_3 = ColorIndexed256(0x5f5faf, 61) + SLATE_BLUE_2 = ColorIndexed256(0x5f5fd7, 62) # SlateBlue3 + ROYAL_BLUE_1 = ColorIndexed256(0x5f5fff, 63) + CHARTREUSE_6 = ColorIndexed256(0x5f8700, 64) # Chartreuse4 + DARK_SEA_GREEN_9 = ColorIndexed256(0x5f875f, 65) # DarkSeaGreen4 + PALE_TURQUOISE_4 = ColorIndexed256(0x5f8787, 66) + STEEL_BLUE = ColorIndexed256(0x5f87af, 67) + STEEL_BLUE_3 = ColorIndexed256(0x5f87d7, 68) + CORNFLOWER_BLUE = ColorIndexed256(0x5f87ff, 69) + CHARTREUSE_5 = ColorIndexed256(0x5faf00, 70) # Chartreuse3 + DARK_SEA_GREEN_8 = ColorIndexed256(0x5faf5f, 71) # DarkSeaGreen4 + CADET_BLUE_2 = ColorIndexed256(0x5faf87, 72) # CadetBlue + CADET_BLUE = ColorIndexed256(0x5fafaf, 73) + SKY_BLUE_3 = ColorIndexed256(0x5fafd7, 74) + STEEL_BLUE_2 = ColorIndexed256(0x5fafff, 75) # SteelBlue1 + CHARTREUSE_4 = ColorIndexed256(0x5fd700, 76) # Chartreuse3 + PALE_GREEN_4 = ColorIndexed256(0x5fd75f, 77) # PaleGreen3 + SEA_GREEN_3 = ColorIndexed256(0x5fd787, 78) + AQUAMARINE_3 = ColorIndexed256(0x5fd7af, 79) + MEDIUM_TURQUOISE = ColorIndexed256(0x5fd7d7, 80) + STEEL_BLUE_1 = ColorIndexed256(0x5fd7ff, 81) + CHARTREUSE_2 = ColorIndexed256(0x5fff00, 82) + SEA_GREEN_4 = ColorIndexed256(0x5fff5f, 83) # SeaGreen2 + SEA_GREEN_2 = ColorIndexed256(0x5fff87, 84) # SeaGreen1 + SEA_GREEN_1 = ColorIndexed256(0x5fffaf, 85) + AQUAMARINE_2 = ColorIndexed256(0x5fffd7, 86) # Aquamarine1 + DARK_SLATE_GRAY_2 = ColorIndexed256(0x5fffff, 87) + DARK_RED = ColorIndexed256(0x870000, 88) + DEEP_PINK_7 = ColorIndexed256(0x87005f, 89) # DeepPink4 + DARK_MAGENTA_2 = ColorIndexed256(0x870087, 90) # DarkMagenta + DARK_MAGENTA = ColorIndexed256(0x8700af, 91) + DARK_VIOLET_2 = ColorIndexed256(0x8700d7, 92) # DarkViolet + PURPLE_2 = ColorIndexed256(0x8700ff, 93) # Purple + ORANGE_3 = ColorIndexed256(0x875f00, 94) # Orange4 + LIGHT_PINK_3 = ColorIndexed256(0x875f5f, 95) # LightPink4 + PLUM_4 = ColorIndexed256(0x875f87, 96) + MEDIUM_PURPLE_6 = ColorIndexed256(0x875faf, 97) # MediumPurple3 + MEDIUM_PURPLE_5 = ColorIndexed256(0x875fd7, 98) # MediumPurple3 + SLATE_BLUE_1 = ColorIndexed256(0x875fff, 99) + YELLOW_6 = ColorIndexed256(0x878700, 100) # Yellow4 + WHEAT_4 = ColorIndexed256(0x87875f, 101) + GREY_53 = ColorIndexed256(0x878787, 102) + LIGHT_SLATE_GREY = ColorIndexed256(0x8787af, 103) + MEDIUM_PURPLE_4 = ColorIndexed256(0x8787d7, 104) # MediumPurple + LIGHT_SLATE_BLUE = ColorIndexed256(0x8787ff, 105) + YELLOW_4 = ColorIndexed256(0x87af00, 106) + DARK_OLIVE_GREEN_6 = ColorIndexed256(0x87af5f, 107) # DarkOliveGreen3 + DARK_SEA_GREEN_7 = ColorIndexed256(0x87af87, 108) # DarkSeaGreen + LIGHT_SKY_BLUE_3 = ColorIndexed256(0x87afaf, 109) + LIGHT_SKY_BLUE_2 = ColorIndexed256(0x87afd7, 110) # LightSkyBlue3 + SKY_BLUE_2 = ColorIndexed256(0x87afff, 111) + CHARTREUSE_3 = ColorIndexed256(0x87d700, 112) # Chartreuse2 + DARK_OLIVE_GREEN_4 = ColorIndexed256(0x87d75f, 113) # DarkOliveGreen3 + PALE_GREEN_3 = ColorIndexed256(0x87d787, 114) + DARK_SEA_GREEN_5 = ColorIndexed256(0x87d7af, 115) # DarkSeaGreen3 + DARK_SLATE_GRAY_3 = ColorIndexed256(0x87d7d7, 116) + SKY_BLUE_1 = ColorIndexed256(0x87d7ff, 117) + CHARTREUSE_1 = ColorIndexed256(0x87ff00, 118) + LIGHT_GREEN_2 = ColorIndexed256(0x87ff5f, 119) # LightGreen + LIGHT_GREEN = ColorIndexed256(0x87ff87, 120) + PALE_GREEN_1 = ColorIndexed256(0x87ffaf, 121) + AQUAMARINE_1 = ColorIndexed256(0x87ffd7, 122) + DARK_SLATE_GRAY_1 = ColorIndexed256(0x87ffff, 123) + RED_4 = ColorIndexed256(0xaf0000, 124) # Red3 + DEEP_PINK_6 = ColorIndexed256(0xaf005f, 125) # DeepPink4 + MEDIUM_VIOLET_RED = ColorIndexed256(0xaf0087, 126) + MAGENTA_6 = ColorIndexed256(0xaf00af, 127) # Magenta3 + DARK_VIOLET = ColorIndexed256(0xaf00d7, 128) + PURPLE = ColorIndexed256(0xaf00ff, 129) + DARK_ORANGE_3 = ColorIndexed256(0xaf5f00, 130) + INDIAN_RED_4 = ColorIndexed256(0xaf5f5f, 131) # IndianRed + HOT_PINK_5 = ColorIndexed256(0xaf5f87, 132) # HotPink3 + MEDIUM_ORCHID_4 = ColorIndexed256(0xaf5faf, 133) # MediumOrchid3 + MEDIUM_ORCHID_3 = ColorIndexed256(0xaf5fd7, 134) # MediumOrchid + MEDIUM_PURPLE_2 = ColorIndexed256(0xaf5fff, 135) + DARK_GOLDENROD = ColorIndexed256(0xaf8700, 136) + LIGHT_SALMON_3 = ColorIndexed256(0xaf875f, 137) + ROSY_BROWN = ColorIndexed256(0xaf8787, 138) + GREY_63 = ColorIndexed256(0xaf87af, 139) + MEDIUM_PURPLE_3 = ColorIndexed256(0xaf87d7, 140) # MediumPurple2 + MEDIUM_PURPLE_1 = ColorIndexed256(0xaf87ff, 141) + GOLD_3 = ColorIndexed256(0xafaf00, 142) + DARK_KHAKI = ColorIndexed256(0xafaf5f, 143) + NAVAJO_WHITE_3 = ColorIndexed256(0xafaf87, 144) + GREY_69 = ColorIndexed256(0xafafaf, 145) + LIGHT_STEEL_BLUE_3 = ColorIndexed256(0xafafd7, 146) + LIGHT_STEEL_BLUE_2 = ColorIndexed256(0xafafff, 147) # LightSteelBlue + YELLOW_5 = ColorIndexed256(0xafd700, 148) # Yellow3 + DARK_OLIVE_GREEN_5 = ColorIndexed256(0xafd75f, 149) # DarkOliveGreen3 + DARK_SEA_GREEN_6 = ColorIndexed256(0xafd787, 150) # DarkSeaGreen3 + DARK_SEA_GREEN_4 = ColorIndexed256(0xafd7af, 151) # DarkSeaGreen2 + LIGHT_CYAN_3 = ColorIndexed256(0xafd7d7, 152) + LIGHT_SKY_BLUE_1 = ColorIndexed256(0xafd7ff, 153) + GREEN_YELLOW = ColorIndexed256(0xafff00, 154) + DARK_OLIVE_GREEN_3 = ColorIndexed256(0xafff5f, 155) # DarkOliveGreen2 + PALE_GREEN_2 = ColorIndexed256(0xafff87, 156) # PaleGreen1 + DARK_SEA_GREEN_3 = ColorIndexed256(0xafffaf, 157) # DarkSeaGreen2 + DARK_SEA_GREEN_1 = ColorIndexed256(0xafffd7, 158) + PALE_TURQUOISE_1 = ColorIndexed256(0xafffff, 159) + RED_3 = ColorIndexed256(0xd70000, 160) + DEEP_PINK_5 = ColorIndexed256(0xd7005f, 161) # DeepPink3 + DEEP_PINK_3 = ColorIndexed256(0xd70087, 162) + MAGENTA_3 = ColorIndexed256(0xd700af, 163) + MAGENTA_5 = ColorIndexed256(0xd700d7, 164) # Magenta3 + MAGENTA_4 = ColorIndexed256(0xd700ff, 165) # Magenta2 + DARK_ORANGE_2 = ColorIndexed256(0xd75f00, 166) # DarkOrange3 + INDIAN_RED_3 = ColorIndexed256(0xd75f5f, 167) # IndianRed + HOT_PINK_4 = ColorIndexed256(0xd75f87, 168) # HotPink3 + HOT_PINK_3 = ColorIndexed256(0xd75faf, 169) # HotPink2 + ORCHID_3 = ColorIndexed256(0xd75fd7, 170) # Orchid + MEDIUM_ORCHID_2 = ColorIndexed256(0xd75fff, 171) # MediumOrchid1 + ORANGE_2 = ColorIndexed256(0xd78700, 172) # Orange3 + LIGHT_SALMON_2 = ColorIndexed256(0xd7875f, 173) # LightSalmon3 + LIGHT_PINK_2 = ColorIndexed256(0xd78787, 174) # LightPink3 + PINK_3 = ColorIndexed256(0xd787af, 175) + PLUM_3 = ColorIndexed256(0xd787d7, 176) + VIOLET = ColorIndexed256(0xd787ff, 177) + GOLD_2 = ColorIndexed256(0xd7af00, 178) # Gold3 + LIGHT_GOLDENROD_5 = ColorIndexed256(0xd7af5f, 179) # LightGoldenrod3 + TAN = ColorIndexed256(0xd7af87, 180) + MISTY_ROSE_3 = ColorIndexed256(0xd7afaf, 181) + THISTLE_3 = ColorIndexed256(0xd7afd7, 182) + PLUM_2 = ColorIndexed256(0xd7afff, 183) + YELLOW_3 = ColorIndexed256(0xd7d700, 184) + KHAKI_3 = ColorIndexed256(0xd7d75f, 185) + LIGHT_GOLDENROD_3 = ColorIndexed256(0xd7d787, 186) # LightGoldenrod2 + LIGHT_YELLOW_3 = ColorIndexed256(0xd7d7af, 187) + GREY_84 = ColorIndexed256(0xd7d7d7, 188) + LIGHT_STEEL_BLUE_1 = ColorIndexed256(0xd7d7ff, 189) + YELLOW_2 = ColorIndexed256(0xd7ff00, 190) + DARK_OLIVE_GREEN_2 = ColorIndexed256(0xd7ff5f, 191) # DarkOliveGreen1 + DARK_OLIVE_GREEN_1 = ColorIndexed256(0xd7ff87, 192) + DARK_SEA_GREEN_2 = ColorIndexed256(0xd7ffaf, 193) # DarkSeaGreen1 + HONEYDEW_2 = ColorIndexed256(0xd7ffd7, 194) + LIGHT_CYAN_1 = ColorIndexed256(0xd7ffff, 195) + RED_1 = ColorIndexed256(0xff0000, 196) + DEEP_PINK_4 = ColorIndexed256(0xff005f, 197) # DeepPink2 + DEEP_PINK_2 = ColorIndexed256(0xff0087, 198) # DeepPink1 + DEEP_PINK_1 = ColorIndexed256(0xff00af, 199) + MAGENTA_2 = ColorIndexed256(0xff00d7, 200) + MAGENTA_1 = ColorIndexed256(0xff00ff, 201) + ORANGE_RED_1 = ColorIndexed256(0xff5f00, 202) + INDIAN_RED_1 = ColorIndexed256(0xff5f5f, 203) + INDIAN_RED_2 = ColorIndexed256(0xff5f87, 204) # IndianRed1 + HOT_PINK_2 = ColorIndexed256(0xff5faf, 205) # HotPink + HOT_PINK = ColorIndexed256(0xff5fd7, 206) + MEDIUM_ORCHID_1 = ColorIndexed256(0xff5fff, 207) + DARK_ORANGE = ColorIndexed256(0xff8700, 208) + SALMON_1 = ColorIndexed256(0xff875f, 209) + LIGHT_CORAL = ColorIndexed256(0xff8787, 210) + PALE_VIOLET_RED_1 = ColorIndexed256(0xff87af, 211) + ORCHID_2 = ColorIndexed256(0xff87d7, 212) + ORCHID_1 = ColorIndexed256(0xff87ff, 213) + ORANGE_1 = ColorIndexed256(0xffaf00, 214) + SANDY_BROWN = ColorIndexed256(0xffaf5f, 215) + LIGHT_SALMON_1 = ColorIndexed256(0xffaf87, 216) + LIGHT_PINK_1 = ColorIndexed256(0xffafaf, 217) + PINK_1 = ColorIndexed256(0xffafd7, 218) + PLUM_1 = ColorIndexed256(0xffafff, 219) + GOLD_1 = ColorIndexed256(0xffd700, 220) + LIGHT_GOLDENROD_4 = ColorIndexed256(0xffd75f, 221) # LightGoldenrod2 + LIGHT_GOLDENROD_2 = ColorIndexed256(0xffd787, 222) + NAVAJO_WHITE_1 = ColorIndexed256(0xffd7af, 223) + MISTY_ROSE_1 = ColorIndexed256(0xffd7d7, 224) + THISTLE_1 = ColorIndexed256(0xffd7ff, 225) + YELLOW_1 = ColorIndexed256(0xffff00, 226) + LIGHT_GOLDENROD_1 = ColorIndexed256(0xffff5f, 227) + KHAKI_1 = ColorIndexed256(0xffff87, 228) + WHEAT_1 = ColorIndexed256(0xffffaf, 229) + CORNSILK_1 = ColorIndexed256(0xffffd7, 230) + GREY_100 = ColorIndexed256(0xffffff, 231) + GREY_3 = ColorIndexed256(0x080808, 232) + GREY_7 = ColorIndexed256(0x121212, 233) + GREY_11 = ColorIndexed256(0x1c1c1c, 234) + GREY_15 = ColorIndexed256(0x262626, 235) + GREY_19 = ColorIndexed256(0x303030, 236) + GREY_23 = ColorIndexed256(0x3a3a3a, 237) + GREY_27 = ColorIndexed256(0x444444, 238) + GREY_30 = ColorIndexed256(0x4e4e4e, 239) + GREY_35 = ColorIndexed256(0x585858, 240) + GREY_39 = ColorIndexed256(0x626262, 241) + GREY_42 = ColorIndexed256(0x6c6c6c, 242) + GREY_46 = ColorIndexed256(0x767676, 243) + GREY_50 = ColorIndexed256(0x808080, 244) + GREY_54 = ColorIndexed256(0x8a8a8a, 245) + GREY_58 = ColorIndexed256(0x949494, 246) + GREY_62 = ColorIndexed256(0x9e9e9e, 247) + GREY_66 = ColorIndexed256(0xa8a8a8, 248) + GREY_70 = ColorIndexed256(0xb2b2b2, 249) + GREY_74 = ColorIndexed256(0xbcbcbc, 250) + GREY_78 = ColorIndexed256(0xc6c6c6, 251) + GREY_82 = ColorIndexed256(0xd0d0d0, 252) + GREY_85 = ColorIndexed256(0xdadada, 253) + GREY_89 = ColorIndexed256(0xe4e4e4, 254) + GREY_93 = ColorIndexed256(0xeeeeee, 255) + + TRUE_BLACK = ColorRGB(0x000000) + TRUE_WHITE = ColorRGB(0xffffff) + RGB_GREY_1 = ColorRGB(0x020202) + RGB_GREY_2 = ColorRGB(0x050505) + RGB_GREY_3 = ColorRGB(0x070707) + RGB_GREY_4 = ColorRGB(0x0a0a0a) + RGB_GREY_5 = ColorRGB(0x0c0c0c) + RGB_GREY_6 = ColorRGB(0x0f0f0f) + RGB_GREY_7 = ColorRGB(0x111111) + RGB_GREY_8 = ColorRGB(0x141414) + RGB_GREY_9 = ColorRGB(0x171717) + RGB_GREY_10 = ColorRGB(0x191919) + RGB_GREY_15 = ColorRGB(0x262626) + RGB_GREY_20 = ColorRGB(0x333333) + RGB_GREY_25 = ColorRGB(0x404040) + RGB_GREY_30 = ColorRGB(0x4c4c4c) + RGB_GREY_35 = ColorRGB(0x595959) + RGB_GREY_40 = ColorRGB(0x666666) + RGB_GREY_45 = ColorRGB(0x737373) + RGB_GREY_50 = ColorRGB(0x808080) + RGB_GREY_55 = ColorRGB(0x8c8c8c) + RGB_GREY_60 = ColorRGB(0x999999) + RGB_GREY_65 = ColorRGB(0xa6a6a6) + RGB_GREY_70 = ColorRGB(0xb3b3b3) + RGB_GREY_75 = ColorRGB(0xc0c0c0) + RGB_GREY_80 = ColorRGB(0xcccccc) + RGB_GREY_85 = ColorRGB(0xd9d9d9) + RGB_GREY_90 = ColorRGB(0xe6e6e6) + RGB_GREY_91 = ColorRGB(0xe8e8e8) + RGB_GREY_92 = ColorRGB(0xebebeb) + RGB_GREY_93 = ColorRGB(0xeeeeee) + RGB_GREY_94 = ColorRGB(0xf1f1f1) + RGB_GREY_95 = ColorRGB(0xf3f3f3) + RGB_GREY_96 = ColorRGB(0xf5f5f5) + RGB_GREY_97 = ColorRGB(0xf8f8f8) + RGB_GREY_98 = ColorRGB(0xfafafa) + RGB_GREY_99 = ColorRGB(0xfdfdfd) diff --git a/pytermor/common.py b/pytermor/common.py index 2a71779..8bfe6a2 100644 --- a/pytermor/common.py +++ b/pytermor/common.py @@ -1,175 +1,73 @@ # ----------------------------------------------------------------------------- # pytermor [ANSI formatted terminal output toolset] -# (c) 2022-2023. A. Shavykin <0.delameter@gmail.com> +# (c) 2022. A. Shavykin <0.delameter@gmail.com> # ----------------------------------------------------------------------------- from __future__ import annotations -import enum -import inspect -import time -import typing as t -import logging -from functools import update_wrapper +import os +import sys +from typing import TypeVar, Generic, AnyStr -logger = logging.getLogger(__package__) -logger.addHandler(logging.NullHandler()) +T = TypeVar('T') +""" Any """ -### catching library logs "from the outside": -# logger = logging.getLogger('pytermor') -# handler = logging.StreamHandler() -# fmt = '[%(levelname)5.5s][%(name)s.%(module)s] %(message)s' -# handler.setFormatter(logging.Formatter(fmt)) -# logger.addHandler(handler) -# logger.setLevel(logging.WARNING) -######## - -CDT = t.TypeVar("CDT", int, str) -""" -:abbr:`CDT (Color descriptor type)` represents a RGB color value. Primary handler -is `resolve_color()`. Valid values include: - - - *str* with a color name in any form distinguishable by the color resolver; - the color lists can be found at: `guide.ansi-presets` and `guide.es7s-colors`; - - *str* starting with a "#" and consisting of 6 more hexadecimal characters, case - insensitive (RGB regular form), e.g.: "#0B0CCA"; - - *str* starting with a "#" and consisting of 3 more hexadecimal characters, case - insensitive (RGB short form), e.g.: "#666"; - - *int* in a [0; 0xFFFFFF] range. -""" - -FT = t.TypeVar("FT", int, str, "IColor", "Style", None) -""" -:abbr:`FT (Format type)` is a style descriptor. Used as a shortcut precursor for actual -styles. Primary handler is `make_style()`. -""" - -RT = t.TypeVar("RT", str, "IRenderable") -""" -:abbr:`RT (Renderable type)` includes regular *str*\\ s as well as `IRenderable` -implementations. -""" - -F = t.TypeVar("F", bound=t.Callable[..., t.Any]) - - -def measure(msg: str = "Done"): - def wrapper(origin: F) -> F: - def new_func(*args, **kwargs): - before_s = time.time_ns() / 1e9 - result = origin(*args, **kwargs) - after_s = time.time_ns() / 1e9 - - from . import PYTERMOR_DEV - - if PYTERMOR_DEV and not kwargs.get("no_log", False): - from . import format_si, dump, logger - - logger.debug(msg + f" in {format_si((after_s - before_s), 's')}") - logger.log(level=5, msg=dump(result, "Dump")) - - return result - - return update_wrapper(t.cast(F, new_func), origin) - - return wrapper - - -class ExtendedEnum(enum.Enum): +class Registry(Generic[T]): + """ + Registry of elements of specified type. + """ @classmethod - def list(cls): - return list(map(lambda c: c.value, cls)) + def resolve(cls, name: str) -> T: + """ + Case-insensitive search through registry contents. - @classmethod - def dict(cls): - return dict(map(lambda c: (c, c.value), cls)) + :param name: name of the value to look up for. + :return: value or KeyError if nothing found. + """ + name_norm = name.upper() + if (value := getattr(cls, name_norm, None)) is not None: + return value + raise KeyError(f'No item named "{name_norm}" (<- "{name}") is found ' + f'in {cls.__name__} registry') -class Align(str, ExtendedEnum): +def get_terminal_width() -> int: """ - Align type. + get_terminal_width + :return: terminal_width """ + try: + import shutil as _shutil + return _shutil.get_terminal_size().columns - 2 + except ImportError: + return 80 - LEFT = "<" - """ """ - RIGHT = ">" - """ """ - CENTER = "^" - """ """ - @classmethod - def resolve(cls, input: str | Align | None, fallback: Align = LEFT): - if input is None: - return fallback - if isinstance(input, cls): - return input - for k, v in cls.dict().items(): - if v == input: - return k - try: - return cls[input.upper()] - except KeyError: - logger.warning(f"Invalid align name: {input}") - return fallback +def wait_key() -> AnyStr|None: + """ + Wait for a key press on the console and return it. + """ + if os.name == 'nt': + import msvcrt + return msvcrt.getch() + import termios + fd = sys.stdin.fileno() -class UserCancel(Exception): - pass + oldterm = termios.tcgetattr(fd) + newattr = termios.tcgetattr(fd) + newattr[3] = newattr[3] & ~termios.ICANON & ~termios.ECHO + termios.tcsetattr(fd, termios.TCSANOW, newattr) - -class UserAbort(Exception): - pass + result = None + try: + result = sys.stdin.read(1) + except IOError: + pass + finally: + termios.tcsetattr(fd, termios.TCSAFLUSH, oldterm) + return result class LogicError(Exception): pass - - -class ConflictError(Exception): - pass - - -class ArgTypeError(Exception): - """ """ - - def __init__(self, actual_type: t.Type, arg_name: str = None, fn: t.Callable = None): - arg_name_str = f'"{arg_name}"' if arg_name else "argument" - # @todo suggestion - # f = inspect.currentframe() - # fp = f.f_back - # fn = getattr(fp.f_locals['self'].__class__, fp.f_code.co_name) - # argspec = inspect.getfullargspec(fn) - if fn is None: - try: - stacks = inspect.stack() - method_name = stacks[0].function - outer_frame = stacks[1].frame - fn = outer_frame.f_locals.get(method_name) - except Exception: - pass - - if fn is not None: - signature = inspect.signature(fn) - param_desc = signature.parameters.get(arg_name, None) - expected_type = '?' - if param_desc: - expected_type = param_desc.annotation - actual_type = actual_type.__qualname__ - msg = ( - f"Expected {arg_name_str} type: <{expected_type}>, got: <{actual_type}>" - ) - else: - msg = f"Unexpected {arg_name_str} type: <{actual_type}>" - - super().__init__(msg) - - -class ArgCountError(Exception): - """ """ - - def __init__(self, actual: int, *expected: int) -> None: - expected_str = ", ".join(str(e) for e in expected) - msg = ( - f"Invalid arguments amount, expected one of: ({expected_str}), got: {actual}" - ) - super().__init__(msg) diff --git a/pytermor/cval.py b/pytermor/cval.py deleted file mode 100644 index 92ecdd0..0000000 --- a/pytermor/cval.py +++ /dev/null @@ -1,2002 +0,0 @@ -# ----------------------------------------------------------------------------- -# pytermor [ANSI formatted terminal output toolset] -# (c) 2022. A. Shavykin <0.delameter@gmail.com> -# ----------------------------------------------------------------------------- -# AUTOGENERATED MODULE -# 2023-01-07T00:08:42.481249 -""" -Color preset list. -""" -from .color import Color16, Color256, ColorRGB -from .ansi import IntCode - - -class CVAL: - """ - - """ - # fmt: off - BLACK = Color16(0x000000, IntCode.BLACK, IntCode.BG_BLACK, "black", register=True, index=True) - RED = Color16(0x800000, IntCode.RED, IntCode.BG_RED, "red", register=True, index=True) - GREEN = Color16(0x008000, IntCode.GREEN, IntCode.BG_GREEN, "green", register=True, index=True) - YELLOW = Color16(0x808000, IntCode.YELLOW, IntCode.BG_YELLOW, "yellow", register=True, index=True) - BLUE = Color16(0x000080, IntCode.BLUE, IntCode.BG_BLUE, "blue", register=True, index=True) - MAGENTA = Color16(0x800080, IntCode.MAGENTA, IntCode.BG_MAGENTA, "magenta", register=True, index=True) - CYAN = Color16(0x008080, IntCode.CYAN, IntCode.BG_CYAN, "cyan", register=True, index=True) - WHITE = Color16(0xc0c0c0, IntCode.WHITE, IntCode.BG_WHITE, "white", register=True, index=True) - GRAY = Color16(0x808080, IntCode.GRAY, IntCode.BG_GRAY, "gray", register=True, index=True) - HI_RED = Color16(0xff0000, IntCode.HI_RED, IntCode.BG_HI_RED, "hi-red", register=True, index=True, aliases=['bright-red']) - HI_GREEN = Color16(0x00ff00, IntCode.HI_GREEN, IntCode.BG_HI_GREEN, "hi-green", register=True, index=True, aliases=['bright-green']) - HI_YELLOW = Color16(0xffff00, IntCode.HI_YELLOW, IntCode.BG_HI_YELLOW, "hi-yellow", register=True, index=True, aliases=['bright-yellow']) - HI_BLUE = Color16(0x0000ff, IntCode.HI_BLUE, IntCode.BG_HI_BLUE, "hi-blue", register=True, index=True, aliases=['bright-blue']) - HI_MAGENTA = Color16(0xff00ff, IntCode.HI_MAGENTA, IntCode.BG_HI_MAGENTA, "hi-magenta", register=True, index=True, aliases=['bright-magenta']) - HI_CYAN = Color16(0x00ffff, IntCode.HI_CYAN, IntCode.BG_HI_CYAN, "hi-cyan", register=True, index=True, aliases=['bright-cyan']) - HI_WHITE = Color16(0xffffff, IntCode.HI_WHITE, IntCode.BG_HI_WHITE, "hi-white", register=True, index=True, aliases=['bright-white']) - - __256A_16_BLACK = Color256(0x000000, 0, "black", register=True, index=True, aliases=['color0', 'colour0'], color16_equiv=BLACK) - __256A_16_RED = Color256(0x800000, 1, "maroon", register=True, index=True, aliases=['color1', 'colour1'], color16_equiv=RED) - __256A_16_GREEN = Color256(0x008000, 2, "green", register=True, index=True, aliases=['color2', 'colour2'], color16_equiv=GREEN) - __256A_16_YELLOW = Color256(0x808000, 3, "olive", register=True, index=True, aliases=['color3', 'colour3'], color16_equiv=YELLOW) - __256A_16_BLUE = Color256(0x000080, 4, "navy", register=True, index=True, aliases=['color4', 'colour4'], color16_equiv=BLUE) - __256A_16_MAGENTA = Color256(0x800080, 5, "purple-5", register=True, index=True, aliases=['color5', 'colour5'], color16_equiv=MAGENTA) - __256A_16_CYAN = Color256(0x008080, 6, "teal", register=True, index=True, aliases=['color6', 'colour6'], color16_equiv=CYAN) - __256A_16_WHITE = Color256(0xc0c0c0, 7, "silver", register=True, index=True, aliases=['color7', 'colour7'], color16_equiv=WHITE) - __256A_16_GRAY = Color256(0x808080, 8, "gray", register=True, index=True, aliases=['color8', 'colour8'], color16_equiv=GRAY) - __256A_16_HI_RED = Color256(0xff0000, 9, "red", register=True, index=True, aliases=['color9', 'colour9'], color16_equiv=HI_RED) - __256A_16_HI_GREEN = Color256(0x00ff00, 10, "lime", register=True, index=True, aliases=['color10', 'colour10'], color16_equiv=HI_GREEN) - __256A_16_HI_YELLOW = Color256(0xffff00, 11, "yellow", register=True, index=True, aliases=['color11', 'colour11'], color16_equiv=HI_YELLOW) - __256A_16_HI_BLUE = Color256(0x0000ff, 12, "blue", register=True, index=True, aliases=['color12', 'colour12'], color16_equiv=HI_BLUE) - __256A_16_HI_MAGENTA = Color256(0xff00ff, 13, "fuchsia", register=True, index=True, aliases=['color13', 'colour13'], color16_equiv=HI_MAGENTA) - __256A_16_HI_CYAN = Color256(0x00ffff, 14, "aqua", register=True, index=True, aliases=['color14', 'colour14'], color16_equiv=HI_CYAN) - __256A_16_HI_WHITE = Color256(0xffffff, 15, "white", register=True, index=True, aliases=['color15', 'colour15'], color16_equiv=HI_WHITE) - AQUAMARINE_1 = Color256(0x87ffd7, 122, "aquamarine-1", register=True, index=True, aliases=['color122', 'colour122']) - AQUAMARINE_2 = Color256(0x5fffd7, 86, "aquamarine-2", register=True, index=True, aliases=['color86', 'colour86']) - AQUAMARINE_3 = Color256(0x5fd7af, 79, "aquamarine-3", register=True, index=True, aliases=['color79', 'colour79']) - BLUE_1 = Color256(0x0000ff, 21, "blue-1", register=True, index=True, aliases=['color21', 'colour21']) - BLUE_2 = Color256(0x0000d7, 20, "blue-2", register=True, index=True, aliases=['color20', 'colour20']) - BLUE_3 = Color256(0x0000af, 19, "blue-3", register=True, index=True, aliases=['color19', 'colour19']) - BLUE_VIOLET = Color256(0x5f00ff, 57, "blue-violet", register=True, index=True, aliases=['color57', 'colour57']) - CADET_BLUE = Color256(0x5fafaf, 73, "cadet-blue", register=True, index=True, aliases=['color73', 'colour73']) - CADET_BLUE_2 = Color256(0x5faf87, 72, "cadet-blue-2", register=True, index=True, aliases=['color72', 'colour72']) - CHARTREUSE_1 = Color256(0x87ff00, 118, "chartreuse-1", register=True, index=True, aliases=['color118', 'colour118']) - CHARTREUSE_2 = Color256(0x5fff00, 82, "chartreuse-2", register=True, index=True, aliases=['color82', 'colour82']) - CHARTREUSE_3 = Color256(0x87d700, 112, "chartreuse-3", register=True, index=True, aliases=['color112', 'colour112']) - CHARTREUSE_4 = Color256(0x5fd700, 76, "chartreuse-4", register=True, index=True, aliases=['color76', 'colour76']) - CHARTREUSE_5 = Color256(0x5faf00, 70, "chartreuse-5", register=True, index=True, aliases=['color70', 'colour70']) - CHARTREUSE_6 = Color256(0x5f8700, 64, "chartreuse-6", register=True, index=True, aliases=['color64', 'colour64']) - CORNFLOWER_BLUE = Color256(0x5f87ff, 69, "cornflower-blue", register=True, index=True, aliases=['color69', 'colour69']) - CORNSILK_1 = Color256(0xffffd7, 230, "cornsilk-1", register=True, index=True, aliases=['color230', 'colour230']) - CYAN_1 = Color256(0x00ffff, 51, "cyan-1", register=True, index=True, aliases=['color51', 'colour51']) - CYAN_2 = Color256(0x00ffd7, 50, "cyan-2", register=True, index=True, aliases=['color50', 'colour50']) - CYAN_3 = Color256(0x00d7af, 43, "cyan-3", register=True, index=True, aliases=['color43', 'colour43']) - DARK_BLUE = Color256(0x000087, 18, "dark-blue", register=True, index=True, aliases=['color18', 'colour18']) - DARK_CYAN = Color256(0x00af87, 36, "dark-cyan", register=True, index=True, aliases=['color36', 'colour36']) - DARK_GOLDENROD = Color256(0xaf8700, 136, "dark-goldenrod", register=True, index=True, aliases=['color136', 'colour136']) - DARK_GREEN = Color256(0x005f00, 22, "dark-green", register=True, index=True, aliases=['color22', 'colour22']) - DARK_KHAKI = Color256(0xafaf5f, 143, "dark-khaki", register=True, index=True, aliases=['color143', 'colour143']) - DARK_MAGENTA = Color256(0x8700af, 91, "dark-magenta", register=True, index=True, aliases=['color91', 'colour91']) - DARK_MAGENTA_2 = Color256(0x870087, 90, "dark-magenta-2", register=True, index=True, aliases=['color90', 'colour90']) - DARK_OLIVE_GREEN_1 = Color256(0xd7ff87, 192, "dark-olive-green-1", register=True, index=True, aliases=['color192', 'colour192']) - DARK_OLIVE_GREEN_2 = Color256(0xd7ff5f, 191, "dark-olive-green-2", register=True, index=True, aliases=['color191', 'colour191']) - DARK_OLIVE_GREEN_3 = Color256(0xafff5f, 155, "dark-olive-green-3", register=True, index=True, aliases=['color155', 'colour155']) - DARK_OLIVE_GREEN_4 = Color256(0x87d75f, 113, "dark-olive-green-4", register=True, index=True, aliases=['color113', 'colour113']) - DARK_OLIVE_GREEN_5 = Color256(0xafd75f, 149, "dark-olive-green-5", register=True, index=True, aliases=['color149', 'colour149']) - DARK_OLIVE_GREEN_6 = Color256(0x87af5f, 107, "dark-olive-green-6", register=True, index=True, aliases=['color107', 'colour107']) - DARK_ORANGE = Color256(0xff8700, 208, "dark-orange", register=True, index=True, aliases=['color208', 'colour208']) - DARK_ORANGE_2 = Color256(0xd75f00, 166, "dark-orange-2", register=True, index=True, aliases=['color166', 'colour166']) - DARK_ORANGE_3 = Color256(0xaf5f00, 130, "dark-orange-3", register=True, index=True, aliases=['color130', 'colour130']) - DARK_RED = Color256(0x870000, 88, "dark-red", register=True, index=True, aliases=['color88', 'colour88']) - DARK_RED_2 = Color256(0x5f0000, 52, "dark-red-2", register=True, index=True, aliases=['color52', 'colour52']) - DARK_SEA_GREEN_1 = Color256(0xafffd7, 158, "dark-sea-green-1", register=True, index=True, aliases=['color158', 'colour158']) - DARK_SEA_GREEN_2 = Color256(0xd7ffaf, 193, "dark-sea-green-2", register=True, index=True, aliases=['color193', 'colour193']) - DARK_SEA_GREEN_3 = Color256(0xafffaf, 157, "dark-sea-green-3", register=True, index=True, aliases=['color157', 'colour157']) - DARK_SEA_GREEN_4 = Color256(0xafd7af, 151, "dark-sea-green-4", register=True, index=True, aliases=['color151', 'colour151']) - DARK_SEA_GREEN_5 = Color256(0x87d7af, 115, "dark-sea-green-5", register=True, index=True, aliases=['color115', 'colour115']) - DARK_SEA_GREEN_6 = Color256(0xafd787, 150, "dark-sea-green-6", register=True, index=True, aliases=['color150', 'colour150']) - DARK_SEA_GREEN_7 = Color256(0x87af87, 108, "dark-sea-green-7", register=True, index=True, aliases=['color108', 'colour108']) - DARK_SEA_GREEN_8 = Color256(0x5faf5f, 71, "dark-sea-green-8", register=True, index=True, aliases=['color71', 'colour71']) - DARK_SEA_GREEN_9 = Color256(0x5f875f, 65, "dark-sea-green-9", register=True, index=True, aliases=['color65', 'colour65']) - DARK_SLATE_GRAY_1 = Color256(0x87ffff, 123, "dark-slate-gray-1", register=True, index=True, aliases=['color123', 'colour123']) - DARK_SLATE_GRAY_2 = Color256(0x5fffff, 87, "dark-slate-gray-2", register=True, index=True, aliases=['color87', 'colour87']) - DARK_SLATE_GRAY_3 = Color256(0x87d7d7, 116, "dark-slate-gray-3", register=True, index=True, aliases=['color116', 'colour116']) - DARK_TURQUOISE = Color256(0x00d7d7, 44, "dark-turquoise", register=True, index=True, aliases=['color44', 'colour44']) - DARK_VIOLET = Color256(0xaf00d7, 128, "dark-violet", register=True, index=True, aliases=['color128', 'colour128']) - DARK_VIOLET_2 = Color256(0x8700d7, 92, "dark-violet-2", register=True, index=True, aliases=['color92', 'colour92']) - DEEP_PINK_1 = Color256(0xff00af, 199, "deep-pink-1", register=True, index=True, aliases=['color199', 'colour199']) - DEEP_PINK_2 = Color256(0xff0087, 198, "deep-pink-2", register=True, index=True, aliases=['color198', 'colour198']) - DEEP_PINK_3 = Color256(0xd70087, 162, "deep-pink-3", register=True, index=True, aliases=['color162', 'colour162']) - DEEP_PINK_4 = Color256(0xff005f, 197, "deep-pink-4", register=True, index=True, aliases=['color197', 'colour197']) - DEEP_PINK_5 = Color256(0xd7005f, 161, "deep-pink-5", register=True, index=True, aliases=['color161', 'colour161']) - DEEP_PINK_6 = Color256(0xaf005f, 125, "deep-pink-6", register=True, index=True, aliases=['color125', 'colour125']) - DEEP_PINK_7 = Color256(0x87005f, 89, "deep-pink-7", register=True, index=True, aliases=['color89', 'colour89']) - DEEP_PINK_8 = Color256(0x5f005f, 53, "deep-pink-8", register=True, index=True, aliases=['color53', 'colour53']) - DEEP_SKY_BLUE_1 = Color256(0x00afff, 39, "deep-sky-blue-1", register=True, index=True, aliases=['color39', 'colour39']) - DEEP_SKY_BLUE_2 = Color256(0x00afd7, 38, "deep-sky-blue-2", register=True, index=True, aliases=['color38', 'colour38']) - DEEP_SKY_BLUE_3 = Color256(0x0087d7, 32, "deep-sky-blue-3", register=True, index=True, aliases=['color32', 'colour32']) - DEEP_SKY_BLUE_4 = Color256(0x0087af, 31, "deep-sky-blue-4", register=True, index=True, aliases=['color31', 'colour31']) - DEEP_SKY_BLUE_5 = Color256(0x005faf, 25, "deep-sky-blue-5", register=True, index=True, aliases=['color25', 'colour25']) - DEEP_SKY_BLUE_6 = Color256(0x005f87, 24, "deep-sky-blue-6", register=True, index=True, aliases=['color24', 'colour24']) - DEEP_SKY_BLUE_7 = Color256(0x005f5f, 23, "deep-sky-blue-7", register=True, index=True, aliases=['color23', 'colour23']) - DODGER_BLUE_1 = Color256(0x0087ff, 33, "dodger-blue-1", register=True, index=True, aliases=['color33', 'colour33']) - DODGER_BLUE_2 = Color256(0x005fff, 27, "dodger-blue-2", register=True, index=True, aliases=['color27', 'colour27']) - DODGER_BLUE_3 = Color256(0x005fd7, 26, "dodger-blue-3", register=True, index=True, aliases=['color26', 'colour26']) - GOLD_1 = Color256(0xffd700, 220, "gold-1", register=True, index=True, aliases=['color220', 'colour220']) - GOLD_2 = Color256(0xd7af00, 178, "gold-2", register=True, index=True, aliases=['color178', 'colour178']) - GOLD_3 = Color256(0xafaf00, 142, "gold-3", register=True, index=True, aliases=['color142', 'colour142']) - GRAY_0 = Color256(0x000000, 16, "gray-0", register=True, index=True, aliases=['color16', 'colour16']) - GRAY_100 = Color256(0xffffff, 231, "gray-100", register=True, index=True, aliases=['color231', 'colour231']) - GRAY_11 = Color256(0x1c1c1c, 234, "gray-11", register=True, index=True, aliases=['color234', 'colour234']) - GRAY_15 = Color256(0x262626, 235, "gray-15", register=True, index=True, aliases=['color235', 'colour235']) - GRAY_19 = Color256(0x303030, 236, "gray-19", register=True, index=True, aliases=['color236', 'colour236']) - GRAY_23 = Color256(0x3a3a3a, 237, "gray-23", register=True, index=True, aliases=['color237', 'colour237']) - GRAY_27 = Color256(0x444444, 238, "gray-27", register=True, index=True, aliases=['color238', 'colour238']) - GRAY_3 = Color256(0x080808, 232, "gray-3", register=True, index=True, aliases=['color232', 'colour232']) - GRAY_30 = Color256(0x4e4e4e, 239, "gray-30", register=True, index=True, aliases=['color239', 'colour239']) - GRAY_35 = Color256(0x585858, 240, "gray-35", register=True, index=True, aliases=['color240', 'colour240']) - GRAY_37 = Color256(0x5f5f5f, 59, "gray-37", register=True, index=True, aliases=['color59', 'colour59']) - GRAY_39 = Color256(0x626262, 241, "gray-39", register=True, index=True, aliases=['color241', 'colour241']) - GRAY_42 = Color256(0x6c6c6c, 242, "gray-42", register=True, index=True, aliases=['color242', 'colour242']) - GRAY_46 = Color256(0x767676, 243, "gray-46", register=True, index=True, aliases=['color243', 'colour243']) - GRAY_50 = Color256(0x808080, 244, "gray-50", register=True, index=True, aliases=['color244', 'colour244']) - GRAY_53 = Color256(0x878787, 102, "gray-53", register=True, index=True, aliases=['color102', 'colour102']) - GRAY_54 = Color256(0x8a8a8a, 245, "gray-54", register=True, index=True, aliases=['color245', 'colour245']) - GRAY_58 = Color256(0x949494, 246, "gray-58", register=True, index=True, aliases=['color246', 'colour246']) - GRAY_62 = Color256(0x9e9e9e, 247, "gray-62", register=True, index=True, aliases=['color247', 'colour247']) - GRAY_63 = Color256(0xaf87af, 139, "gray-63", register=True, index=True, aliases=['color139', 'colour139']) - GRAY_66 = Color256(0xa8a8a8, 248, "gray-66", register=True, index=True, aliases=['color248', 'colour248']) - GRAY_69 = Color256(0xafafaf, 145, "gray-69", register=True, index=True, aliases=['color145', 'colour145']) - GRAY_7 = Color256(0x121212, 233, "gray-7", register=True, index=True, aliases=['color233', 'colour233']) - GRAY_70 = Color256(0xb2b2b2, 249, "gray-70", register=True, index=True, aliases=['color249', 'colour249']) - GRAY_74 = Color256(0xbcbcbc, 250, "gray-74", register=True, index=True, aliases=['color250', 'colour250']) - GRAY_78 = Color256(0xc6c6c6, 251, "gray-78", register=True, index=True, aliases=['color251', 'colour251']) - GRAY_82 = Color256(0xd0d0d0, 252, "gray-82", register=True, index=True, aliases=['color252', 'colour252']) - GRAY_84 = Color256(0xd7d7d7, 188, "gray-84", register=True, index=True, aliases=['color188', 'colour188']) - GRAY_85 = Color256(0xdadada, 253, "gray-85", register=True, index=True, aliases=['color253', 'colour253']) - GRAY_89 = Color256(0xe4e4e4, 254, "gray-89", register=True, index=True, aliases=['color254', 'colour254']) - GRAY_93 = Color256(0xeeeeee, 255, "gray-93", register=True, index=True, aliases=['color255', 'colour255']) - GREEN_2 = Color256(0x00ff00, 46, "green-2", register=True, index=True, aliases=['color46', 'colour46']) - GREEN_3 = Color256(0x00d700, 40, "green-3", register=True, index=True, aliases=['color40', 'colour40']) - GREEN_4 = Color256(0x00af00, 34, "green-4", register=True, index=True, aliases=['color34', 'colour34']) - GREEN_5 = Color256(0x008700, 28, "green-5", register=True, index=True, aliases=['color28', 'colour28']) - GREEN_YELLOW = Color256(0xafff00, 154, "green-yellow", register=True, index=True, aliases=['color154', 'colour154']) - HONEYDEW_2 = Color256(0xd7ffd7, 194, "honeydew-2", register=True, index=True, aliases=['color194', 'colour194']) - HOT_PINK = Color256(0xff5fd7, 206, "hot-pink", register=True, index=True, aliases=['color206', 'colour206']) - HOT_PINK_2 = Color256(0xff5faf, 205, "hot-pink-2", register=True, index=True, aliases=['color205', 'colour205']) - HOT_PINK_3 = Color256(0xd75faf, 169, "hot-pink-3", register=True, index=True, aliases=['color169', 'colour169']) - HOT_PINK_4 = Color256(0xd75f87, 168, "hot-pink-4", register=True, index=True, aliases=['color168', 'colour168']) - HOT_PINK_5 = Color256(0xaf5f87, 132, "hot-pink-5", register=True, index=True, aliases=['color132', 'colour132']) - INDIAN_RED_1 = Color256(0xff5f5f, 203, "indian-red-1", register=True, index=True, aliases=['color203', 'colour203']) - INDIAN_RED_2 = Color256(0xff5f87, 204, "indian-red-2", register=True, index=True, aliases=['color204', 'colour204']) - INDIAN_RED_3 = Color256(0xd75f5f, 167, "indian-red-3", register=True, index=True, aliases=['color167', 'colour167']) - INDIAN_RED_4 = Color256(0xaf5f5f, 131, "indian-red-4", register=True, index=True, aliases=['color131', 'colour131']) - KHAKI_1 = Color256(0xffff87, 228, "khaki-1", register=True, index=True, aliases=['color228', 'colour228']) - KHAKI_3 = Color256(0xd7d75f, 185, "khaki-3", register=True, index=True, aliases=['color185', 'colour185']) - LIGHT_CORAL = Color256(0xff8787, 210, "light-coral", register=True, index=True, aliases=['color210', 'colour210']) - LIGHT_CYAN_1 = Color256(0xd7ffff, 195, "light-cyan-1", register=True, index=True, aliases=['color195', 'colour195']) - LIGHT_CYAN_3 = Color256(0xafd7d7, 152, "light-cyan-3", register=True, index=True, aliases=['color152', 'colour152']) - LIGHT_GOLDENROD_1 = Color256(0xffff5f, 227, "light-goldenrod-1", register=True, index=True, aliases=['color227', 'colour227']) - LIGHT_GOLDENROD_2 = Color256(0xffd787, 222, "light-goldenrod-2", register=True, index=True, aliases=['color222', 'colour222']) - LIGHT_GOLDENROD_3 = Color256(0xd7d787, 186, "light-goldenrod-3", register=True, index=True, aliases=['color186', 'colour186']) - LIGHT_GOLDENROD_4 = Color256(0xffd75f, 221, "light-goldenrod-4", register=True, index=True, aliases=['color221', 'colour221']) - LIGHT_GOLDENROD_5 = Color256(0xd7af5f, 179, "light-goldenrod-5", register=True, index=True, aliases=['color179', 'colour179']) - LIGHT_GREEN = Color256(0x87ff87, 120, "light-green", register=True, index=True, aliases=['color120', 'colour120']) - LIGHT_GREEN_2 = Color256(0x87ff5f, 119, "light-green-2", register=True, index=True, aliases=['color119', 'colour119']) - LIGHT_PINK_1 = Color256(0xffafaf, 217, "light-pink-1", register=True, index=True, aliases=['color217', 'colour217']) - LIGHT_PINK_2 = Color256(0xd78787, 174, "light-pink-2", register=True, index=True, aliases=['color174', 'colour174']) - LIGHT_PINK_3 = Color256(0x875f5f, 95, "light-pink-3", register=True, index=True, aliases=['color95', 'colour95']) - LIGHT_SALMON_1 = Color256(0xffaf87, 216, "light-salmon-1", register=True, index=True, aliases=['color216', 'colour216']) - LIGHT_SALMON_2 = Color256(0xd7875f, 173, "light-salmon-2", register=True, index=True, aliases=['color173', 'colour173']) - LIGHT_SALMON_3 = Color256(0xaf875f, 137, "light-salmon-3", register=True, index=True, aliases=['color137', 'colour137']) - LIGHT_SEA_GREEN = Color256(0x00afaf, 37, "light-sea-green", register=True, index=True, aliases=['color37', 'colour37']) - LIGHT_SKY_BLUE_1 = Color256(0xafd7ff, 153, "light-sky-blue-1", register=True, index=True, aliases=['color153', 'colour153']) - LIGHT_SKY_BLUE_2 = Color256(0x87afd7, 110, "light-sky-blue-2", register=True, index=True, aliases=['color110', 'colour110']) - LIGHT_SKY_BLUE_3 = Color256(0x87afaf, 109, "light-sky-blue-3", register=True, index=True, aliases=['color109', 'colour109']) - LIGHT_SLATE_BLUE = Color256(0x8787ff, 105, "light-slate-blue", register=True, index=True, aliases=['color105', 'colour105']) - LIGHT_SLATE_GRAY = Color256(0x8787af, 103, "light-slate-gray", register=True, index=True, aliases=['color103', 'colour103']) - LIGHT_STEEL_BLUE_1 = Color256(0xd7d7ff, 189, "light-steel-blue-1", register=True, index=True, aliases=['color189', 'colour189']) - LIGHT_STEEL_BLUE_2 = Color256(0xafafff, 147, "light-steel-blue-2", register=True, index=True, aliases=['color147', 'colour147']) - LIGHT_STEEL_BLUE_3 = Color256(0xafafd7, 146, "light-steel-blue-3", register=True, index=True, aliases=['color146', 'colour146']) - LIGHT_YELLOW_3 = Color256(0xd7d7af, 187, "light-yellow-3", register=True, index=True, aliases=['color187', 'colour187']) - MAGENTA_1 = Color256(0xff00ff, 201, "magenta-1", register=True, index=True, aliases=['color201', 'colour201']) - MAGENTA_2 = Color256(0xff00d7, 200, "magenta-2", register=True, index=True, aliases=['color200', 'colour200']) - MAGENTA_3 = Color256(0xd700af, 163, "magenta-3", register=True, index=True, aliases=['color163', 'colour163']) - MAGENTA_4 = Color256(0xd700ff, 165, "magenta-4", register=True, index=True, aliases=['color165', 'colour165']) - MAGENTA_5 = Color256(0xd700d7, 164, "magenta-5", register=True, index=True, aliases=['color164', 'colour164']) - MAGENTA_6 = Color256(0xaf00af, 127, "magenta-6", register=True, index=True, aliases=['color127', 'colour127']) - MEDIUM_ORCHID_1 = Color256(0xff5fff, 207, "medium-orchid-1", register=True, index=True, aliases=['color207', 'colour207']) - MEDIUM_ORCHID_2 = Color256(0xd75fff, 171, "medium-orchid-2", register=True, index=True, aliases=['color171', 'colour171']) - MEDIUM_ORCHID_3 = Color256(0xaf5fd7, 134, "medium-orchid-3", register=True, index=True, aliases=['color134', 'colour134']) - MEDIUM_ORCHID_4 = Color256(0xaf5faf, 133, "medium-orchid-4", register=True, index=True, aliases=['color133', 'colour133']) - MEDIUM_PURPLE_1 = Color256(0xaf87ff, 141, "medium-purple-1", register=True, index=True, aliases=['color141', 'colour141']) - MEDIUM_PURPLE_2 = Color256(0xaf5fff, 135, "medium-purple-2", register=True, index=True, aliases=['color135', 'colour135']) - MEDIUM_PURPLE_3 = Color256(0xaf87d7, 140, "medium-purple-3", register=True, index=True, aliases=['color140', 'colour140']) - MEDIUM_PURPLE_4 = Color256(0x8787d7, 104, "medium-purple-4", register=True, index=True, aliases=['color104', 'colour104']) - MEDIUM_PURPLE_5 = Color256(0x875fd7, 98, "medium-purple-5", register=True, index=True, aliases=['color98', 'colour98']) - MEDIUM_PURPLE_6 = Color256(0x875faf, 97, "medium-purple-6", register=True, index=True, aliases=['color97', 'colour97']) - MEDIUM_PURPLE_7 = Color256(0x5f5f87, 60, "medium-purple-7", register=True, index=True, aliases=['color60', 'colour60']) - MEDIUM_SPRING_GREEN = Color256(0x00ffaf, 49, "medium-spring-green", register=True, index=True, aliases=['color49', 'colour49']) - MEDIUM_TURQUOISE = Color256(0x5fd7d7, 80, "medium-turquoise", register=True, index=True, aliases=['color80', 'colour80']) - MEDIUM_VIOLET_RED = Color256(0xaf0087, 126, "medium-violet-red", register=True, index=True, aliases=['color126', 'colour126']) - MISTY_ROSE_1 = Color256(0xffd7d7, 224, "misty-rose-1", register=True, index=True, aliases=['color224', 'colour224']) - MISTY_ROSE_3 = Color256(0xd7afaf, 181, "misty-rose-3", register=True, index=True, aliases=['color181', 'colour181']) - NAVAJO_WHITE_1 = Color256(0xffd7af, 223, "navajo-white-1", register=True, index=True, aliases=['color223', 'colour223']) - NAVAJO_WHITE_3 = Color256(0xafaf87, 144, "navajo-white-3", register=True, index=True, aliases=['color144', 'colour144']) - NAVY_BLUE = Color256(0x00005f, 17, "navy-blue", register=True, index=True, aliases=['color17', 'colour17']) - ORANGE_1 = Color256(0xffaf00, 214, "orange-1", register=True, index=True, aliases=['color214', 'colour214']) - ORANGE_2 = Color256(0xd78700, 172, "orange-2", register=True, index=True, aliases=['color172', 'colour172']) - ORANGE_3 = Color256(0x875f00, 94, "orange-3", register=True, index=True, aliases=['color94', 'colour94']) - ORANGE_4 = Color256(0x5f5f00, 58, "orange-4", register=True, index=True, aliases=['color58', 'colour58']) - ORANGE_RED_1 = Color256(0xff5f00, 202, "orange-red-1", register=True, index=True, aliases=['color202', 'colour202']) - ORCHID_1 = Color256(0xff87ff, 213, "orchid-1", register=True, index=True, aliases=['color213', 'colour213']) - ORCHID_2 = Color256(0xff87d7, 212, "orchid-2", register=True, index=True, aliases=['color212', 'colour212']) - ORCHID_3 = Color256(0xd75fd7, 170, "orchid-3", register=True, index=True, aliases=['color170', 'colour170']) - PALE_GREEN_1 = Color256(0x87ffaf, 121, "pale-green-1", register=True, index=True, aliases=['color121', 'colour121']) - PALE_GREEN_2 = Color256(0xafff87, 156, "pale-green-2", register=True, index=True, aliases=['color156', 'colour156']) - PALE_GREEN_3 = Color256(0x87d787, 114, "pale-green-3", register=True, index=True, aliases=['color114', 'colour114']) - PALE_GREEN_4 = Color256(0x5fd75f, 77, "pale-green-4", register=True, index=True, aliases=['color77', 'colour77']) - PALE_TURQUOISE_1 = Color256(0xafffff, 159, "pale-turquoise-1", register=True, index=True, aliases=['color159', 'colour159']) - PALE_TURQUOISE_4 = Color256(0x5f8787, 66, "pale-turquoise-4", register=True, index=True, aliases=['color66', 'colour66']) - PALE_VIOLET_RED_1 = Color256(0xff87af, 211, "pale-violet-red-1", register=True, index=True, aliases=['color211', 'colour211']) - PINK_1 = Color256(0xffafd7, 218, "pink-1", register=True, index=True, aliases=['color218', 'colour218']) - PINK_3 = Color256(0xd787af, 175, "pink-3", register=True, index=True, aliases=['color175', 'colour175']) - PLUM_1 = Color256(0xffafff, 219, "plum-1", register=True, index=True, aliases=['color219', 'colour219']) - PLUM_2 = Color256(0xd7afff, 183, "plum-2", register=True, index=True, aliases=['color183', 'colour183']) - PLUM_3 = Color256(0xd787d7, 176, "plum-3", register=True, index=True, aliases=['color176', 'colour176']) - PLUM_4 = Color256(0x875f87, 96, "plum-4", register=True, index=True, aliases=['color96', 'colour96']) - PURPLE = Color256(0xaf00ff, 129, "purple", register=True, index=True, aliases=['color129', 'colour129']) - PURPLE_2 = Color256(0x8700ff, 93, "purple-2", register=True, index=True, aliases=['color93', 'colour93']) - PURPLE_3 = Color256(0x5f00d7, 56, "purple-3", register=True, index=True, aliases=['color56', 'colour56']) - PURPLE_4 = Color256(0x5f00af, 55, "purple-4", register=True, index=True, aliases=['color55', 'colour55']) - PURPLE_6 = Color256(0x5f0087, 54, "purple-6", register=True, index=True, aliases=['color54', 'colour54']) - RED_1 = Color256(0xff0000, 196, "red-1", register=True, index=True, aliases=['color196', 'colour196']) - RED_3 = Color256(0xd70000, 160, "red-3", register=True, index=True, aliases=['color160', 'colour160']) - RED_4 = Color256(0xaf0000, 124, "red-4", register=True, index=True, aliases=['color124', 'colour124']) - ROSY_BROWN = Color256(0xaf8787, 138, "rosy-brown", register=True, index=True, aliases=['color138', 'colour138']) - ROYAL_BLUE_1 = Color256(0x5f5fff, 63, "royal-blue-1", register=True, index=True, aliases=['color63', 'colour63']) - SALMON_1 = Color256(0xff875f, 209, "salmon-1", register=True, index=True, aliases=['color209', 'colour209']) - SANDY_BROWN = Color256(0xffaf5f, 215, "sandy-brown", register=True, index=True, aliases=['color215', 'colour215']) - SEA_GREEN_1 = Color256(0x5fffaf, 85, "sea-green-1", register=True, index=True, aliases=['color85', 'colour85']) - SEA_GREEN_2 = Color256(0x5fff87, 84, "sea-green-2", register=True, index=True, aliases=['color84', 'colour84']) - SEA_GREEN_3 = Color256(0x5fd787, 78, "sea-green-3", register=True, index=True, aliases=['color78', 'colour78']) - SEA_GREEN_4 = Color256(0x5fff5f, 83, "sea-green-4", register=True, index=True, aliases=['color83', 'colour83']) - SKY_BLUE_1 = Color256(0x87d7ff, 117, "sky-blue-1", register=True, index=True, aliases=['color117', 'colour117']) - SKY_BLUE_2 = Color256(0x87afff, 111, "sky-blue-2", register=True, index=True, aliases=['color111', 'colour111']) - SKY_BLUE_3 = Color256(0x5fafd7, 74, "sky-blue-3", register=True, index=True, aliases=['color74', 'colour74']) - SLATE_BLUE_1 = Color256(0x875fff, 99, "slate-blue-1", register=True, index=True, aliases=['color99', 'colour99']) - SLATE_BLUE_2 = Color256(0x5f5fd7, 62, "slate-blue-2", register=True, index=True, aliases=['color62', 'colour62']) - SLATE_BLUE_3 = Color256(0x5f5faf, 61, "slate-blue-3", register=True, index=True, aliases=['color61', 'colour61']) - SPRING_GREEN_1 = Color256(0x00ff87, 48, "spring-green-1", register=True, index=True, aliases=['color48', 'colour48']) - SPRING_GREEN_2 = Color256(0x00ff5f, 47, "spring-green-2", register=True, index=True, aliases=['color47', 'colour47']) - SPRING_GREEN_3 = Color256(0x00d75f, 41, "spring-green-3", register=True, index=True, aliases=['color41', 'colour41']) - SPRING_GREEN_4 = Color256(0x00875f, 29, "spring-green-4", register=True, index=True, aliases=['color29', 'colour29']) - SPRING_GREEN_5 = Color256(0x00af5f, 35, "spring-green-5", register=True, index=True, aliases=['color35', 'colour35']) - SPRING_GREEN_6 = Color256(0x00d787, 42, "spring-green-6", register=True, index=True, aliases=['color42', 'colour42']) - STEEL_BLUE = Color256(0x5f87af, 67, "steel-blue", register=True, index=True, aliases=['color67', 'colour67']) - STEEL_BLUE_1 = Color256(0x5fd7ff, 81, "steel-blue-1", register=True, index=True, aliases=['color81', 'colour81']) - STEEL_BLUE_2 = Color256(0x5fafff, 75, "steel-blue-2", register=True, index=True, aliases=['color75', 'colour75']) - STEEL_BLUE_3 = Color256(0x5f87d7, 68, "steel-blue-3", register=True, index=True, aliases=['color68', 'colour68']) - TAN = Color256(0xd7af87, 180, "tan", register=True, index=True, aliases=['color180', 'colour180']) - THISTLE_1 = Color256(0xffd7ff, 225, "thistle-1", register=True, index=True, aliases=['color225', 'colour225']) - THISTLE_3 = Color256(0xd7afd7, 182, "thistle-3", register=True, index=True, aliases=['color182', 'colour182']) - TURQUOISE_2 = Color256(0x00d7ff, 45, "turquoise-2", register=True, index=True, aliases=['color45', 'colour45']) - TURQUOISE_4 = Color256(0x008787, 30, "turquoise-4", register=True, index=True, aliases=['color30', 'colour30']) - VIOLET = Color256(0xd787ff, 177, "violet", register=True, index=True, aliases=['color177', 'colour177']) - WHEAT_1 = Color256(0xffffaf, 229, "wheat-1", register=True, index=True, aliases=['color229', 'colour229']) - WHEAT_4 = Color256(0x87875f, 101, "wheat-4", register=True, index=True, aliases=['color101', 'colour101']) - YELLOW_1 = Color256(0xffff00, 226, "yellow-1", register=True, index=True, aliases=['color226', 'colour226']) - YELLOW_2 = Color256(0xd7ff00, 190, "yellow-2", register=True, index=True, aliases=['color190', 'colour190']) - YELLOW_3 = Color256(0xd7d700, 184, "yellow-3", register=True, index=True, aliases=['color184', 'colour184']) - YELLOW_4 = Color256(0x87af00, 106, "yellow-4", register=True, index=True, aliases=['color106', 'colour106']) - YELLOW_5 = Color256(0xafd700, 148, "yellow-5", register=True, index=True, aliases=['color148', 'colour148']) - YELLOW_6 = Color256(0x878700, 100, "yellow-6", register=True, index=True, aliases=['color100', 'colour100']) - - ColorRGB(0x0048ba, "absolute-zero", register=True, index=True) - ColorRGB(0x4c2f27, "acajou", register=True, index=True) - ColorRGB(0xb0bf1a, "acid-green", register=True, index=True) - ColorRGB(0x7cb9e8, "aero", register=True, index=True) - ColorRGB(0xc9ffe5, "aero-blue", register=True, index=True) - ColorRGB(0xb284be, "african-violet", register=True, index=True) - ColorRGB(0x5d8aa8, "air-force-blue", register=True, index=True, variation_map={ - 0x00308f: "usaf" }) - ColorRGB(0x72a0c1, "air-superiority-blue", register=True, index=True) - ColorRGB(0xaf002a, "alabama-crimson", register=True, index=True) - ColorRGB(0xf2f0e6, "alabaster", register=True, index=True) - ColorRGB(0xf0f8ff, "alice-blue", register=True, index=True) - ColorRGB(0xe32636, "alizarin-crimson", register=True, index=True) - ColorRGB(0xc46210, "alloy-orange", register=True, index=True) - ColorRGB(0xefdecd, "almond", register=True, index=True) - ColorRGB(0x5a6457, "aloeswood-brown", register=True, index=True) - ColorRGB(0x6a432d, "aloewood", register=True, index=True) - ColorRGB(0xd6d6d6, "aluminum", register=True, index=True) - ColorRGB(0xd2d9db, "aluminum-foil", register=True, index=True) - ColorRGB(0xe52b50, "amaranth", register=True, index=True) - ColorRGB(0x9f2b68, "amaranth-deep-purple", register=True, index=True) - ColorRGB(0xf19cbb, "amaranth-pink", register=True, index=True) - ColorRGB(0xab274f, "amaranth-purple", register=True, index=True) - ColorRGB(0xd3212d, "amaranth-red", register=True, index=True) - ColorRGB(0x3b7a57, "amazon", register=True, index=True) - ColorRGB(0xffbf00, "amber", register=True, index=True, variation_map={ - 0xca6924: "kohaku-iro", - 0xff7e00: "sae-ece" }) - ColorRGB(0x3b3b6d, "american-blue", register=True, index=True) - ColorRGB(0x391802, "american-bronze", register=True, index=True) - ColorRGB(0x804040, "american-brown", register=True, index=True) - ColorRGB(0xd3af37, "american-gold", register=True, index=True) - ColorRGB(0x34b334, "american-green", register=True, index=True) - ColorRGB(0xff8b00, "american-orange", register=True, index=True) - ColorRGB(0xff9899, "american-pink", register=True, index=True) - ColorRGB(0x431c53, "american-purple", register=True, index=True) - ColorRGB(0xb32134, "american-red", register=True, index=True) - ColorRGB(0xff033e, "american-rose", register=True, index=True) - ColorRGB(0xcfcfcf, "american-silver", register=True, index=True) - ColorRGB(0x551b8c, "american-violet", register=True, index=True) - ColorRGB(0xf2b400, "american-yellow", register=True, index=True) - ColorRGB(0x9966cc, "amethyst", register=True, index=True) - ColorRGB(0xf3c13a, "amur-cork-tree", register=True, index=True) - ColorRGB(0xf2f3f4, "anti-flash-white", register=True, index=True) - ColorRGB(0xcd9575, "antique-brass", register=True, index=True) - ColorRGB(0x665d1e, "antique-bronze", register=True, index=True) - ColorRGB(0x915c83, "antique-fuchsia", register=True, index=True) - ColorRGB(0x841b2d, "antique-ruby", register=True, index=True) - ColorRGB(0xfaebd7, "antique-white", register=True, index=True) - ColorRGB(0x66b447, "apple", register=True, index=True) - ColorRGB(0x8db600, "apple-green", register=True, index=True) - ColorRGB(0xfbceb1, "apricot", register=True, index=True) - ColorRGB(0x00ffff, "aqua", register=True, index=True) - ColorRGB(0x86aba5, "aqua-blue", register=True, index=True) - ColorRGB(0x7fffd4, "aquamarine", register=True, index=True) - ColorRGB(0xd0ff14, "arctic-lime", register=True, index=True) - ColorRGB(0xc0c0c0, "argent", register=True, index=True) - ColorRGB(0x4b5320, "army-green", register=True, index=True) - ColorRGB(0x8f9779, "artichoke", register=True, index=True) - ColorRGB(0xe9d66b, "arylide-yellow", register=True, index=True) - ColorRGB(0x7dc242, "asda-green", register=True, index=True, variation_map={ - 0x00dea4: "1985", - 0x80c197: "1994", - 0x66c992: "1999", - 0x32ad61: "2002" }) - ColorRGB(0xc86500, "asda-orange", register=True, index=True, variation_map={ - 0xca7309: "1968" }) - ColorRGB(0xb2beb5, "ash-gray", register=True, index=True) - ColorRGB(0x87a96b, "asparagus", register=True, index=True) - ColorRGB(0x687652, "aspen-green", register=True, index=True) - ColorRGB(0x003a6c, "ateneo-blue", register=True, index=True) - ColorRGB(0xff9966, "atomic-tangerine", register=True, index=True) - ColorRGB(0xa52a2a, "auburn", register=True, index=True) - ColorRGB(0xfdee00, "aureolin", register=True, index=True) - ColorRGB(0x6e7f80, "auro-metal-saurus", register=True, index=True) - ColorRGB(0x568203, "avocado", register=True, index=True) - ColorRGB(0xff2052, "awesome", register=True, index=True) - ColorRGB(0x63775b, "axolotl", register=True, index=True) - ColorRGB(0x007fff, "azure", register=True, index=True) - ColorRGB(0xf0ffff, "azure-mist", register=True, index=True) - ColorRGB(0xdbe9f4, "azureish-white", register=True, index=True) - ColorRGB(0x89cff0, "baby-blue", register=True, index=True) - ColorRGB(0xa1caf1, "baby-blue-eyes", register=True, index=True) - ColorRGB(0xf4c2c2, "baby-pink", register=True, index=True) - ColorRGB(0xfefefa, "baby-powder", register=True, index=True) - ColorRGB(0x857c55, "baiko-brown", register=True, index=True) - ColorRGB(0xff91af, "baker-miller-pink", register=True, index=True) - ColorRGB(0x21abcd, "ball-blue", register=True, index=True) - ColorRGB(0xf2e096, "bamboo-cream", register=True, index=True) - ColorRGB(0xfae7b5, "banana-mania", register=True, index=True) - ColorRGB(0xffe135, "banana-yellow", register=True, index=True) - ColorRGB(0x83a9c1, "banff-blue", register=True, index=True) - ColorRGB(0x006a4e, "bangladesh-green", register=True, index=True) - ColorRGB(0xe94196, "barbie-pink", register=True, index=True, variation_map={ - 0xe85395: "1959-1975", - 0xd3419d: "1975-1990", - 0xf364a2: "1990-1999", - 0xf7238a: "1999-2004", - 0xff3988: "2004-2005", - 0xfc419a: "2005-2009", - 0xe0218a: "pantone" }) - ColorRGB(0x7c0a02, "barn-red", register=True, index=True) - ColorRGB(0x1dacd6, "battery-charged-blue", register=True, index=True) - ColorRGB(0x848482, "battleship-gray", register=True, index=True) - ColorRGB(0x5fc9bf, "bayside", register=True, index=True) - ColorRGB(0x98777b, "bazaar", register=True, index=True) - ColorRGB(0x2e5894, "bdazzled-blue", register=True, index=True) - ColorRGB(0xbcd4e6, "beau-blue", register=True, index=True) - ColorRGB(0x9f8170, "beaver", register=True, index=True) - ColorRGB(0xf28e1c, "beer", register=True, index=True) - ColorRGB(0xfa6e79, "begonia", register=True, index=True) - ColorRGB(0xf5f5dc, "beige", register=True, index=True) - ColorRGB(0x5d3f6a, "bellflower", register=True, index=True) - ColorRGB(0x352925, "betel-nut-dye", register=True, index=True) - ColorRGB(0x9c2542, "big-dip-o-ruby", register=True, index=True) - ColorRGB(0xe88e5a, "big-foot-feet", register=True, index=True) - ColorRGB(0xb14a30, "birch-brown", register=True, index=True) - ColorRGB(0xffe4c4, "bisque", register=True, index=True) - ColorRGB(0x3d2b1f, "bistre", register=True, index=True) - ColorRGB(0x967117, "bistre-brown", register=True, index=True) - ColorRGB(0xcae00d, "bitter-lemon", register=True, index=True) - ColorRGB(0xbfff00, "bitter-lime", register=True, index=True) - ColorRGB(0xfe6f5e, "bittersweet", register=True, index=True) - ColorRGB(0xbf4f51, "bittersweet-shimmer", register=True, index=True) - ColorRGB(0x171412, "black", register=True, index=True) - ColorRGB(0x3d0c02, "black-bean", register=True, index=True) - ColorRGB(0x252321, "black-chestnut-oak", register=True, index=True) - ColorRGB(0x1b1811, "black-chocolate", register=True, index=True) - ColorRGB(0x3b2f2f, "black-coffee", register=True, index=True) - ColorRGB(0x54626f, "black-coral", register=True, index=True) - ColorRGB(0x351e1c, "black-kite", register=True, index=True) - ColorRGB(0x253529, "black-leather-jacket", register=True, index=True) - ColorRGB(0x3b3c36, "black-olive", register=True, index=True) - ColorRGB(0xbfafb2, "black-shadows", register=True, index=True) - ColorRGB(0xffebcd, "blanched-almond", register=True, index=True) - ColorRGB(0xa57164, "blast-off-bronze", register=True, index=True) - ColorRGB(0x318ce7, "bleu-de-france", register=True, index=True) - ColorRGB(0xace5ee, "blizzard-blue", register=True, index=True) - ColorRGB(0xfaf0be, "blond", register=True, index=True) - ColorRGB(0x8a0303, "blood", register=True, index=True, variation_map={ - 0xa41313: "animal", - 0x630f0f: "organ" }) - ColorRGB(0xd1001c, "blood-orange", register=True, index=True) - ColorRGB(0x660000, "blood-red", register=True, index=True, variation_map={ - 0xf35336: "benihi" }) - ColorRGB(0x1f75fe, "blue", register=True, index=True, variation_map={ - 0x0093af: "munsell", - 0x0087bd: "ncs", - 0x0018a8: "pantone", - 0x333399: "pigment", - 0x0247fe: "ryb", - 0x000080: "xterm" }) - ColorRGB(0xa2a2d0, "blue-bell", register=True, index=True) - ColorRGB(0x52593b, "blue-black-crayfish", register=True, index=True) - ColorRGB(0x00b9fb, "blue-bolt", register=True, index=True) - ColorRGB(0x0088dc, "blue-cola", register=True, index=True) - ColorRGB(0x6699cc, "blue-gray", register=True, index=True) - ColorRGB(0x0d98ba, "blue-green", register=True, index=True, variation_map={ - 0x064e40: "color-wheel", - 0x3a6960: "seiheki" }) - ColorRGB(0x5dadec, "blue-jeans", register=True, index=True) - ColorRGB(0x4cb7a5, "blue-lagoon", register=True, index=True) - ColorRGB(0x553592, "blue-magenta-violet", register=True, index=True) - ColorRGB(0x0cbfe9, "blue-raspberry", register=True, index=True) - ColorRGB(0x126180, "blue-sapphire", register=True, index=True) - ColorRGB(0x8a2be2, "blue-violet", register=True, index=True, variation_map={ - 0x4d1a7f: "color-wheel", - 0x7366bd: "crayola", - 0x2b2028: "shikon" }) - ColorRGB(0x5072a7, "blue-yonder", register=True, index=True) - ColorRGB(0x4f86f7, "blueberry", register=True, index=True) - ColorRGB(0x1c1cf0, "bluebonnet", register=True, index=True) - ColorRGB(0xde5d83, "blush", register=True, index=True) - ColorRGB(0x542d24, "boiled-red-bean-brown", register=True, index=True) - ColorRGB(0x79443b, "bole", register=True, index=True) - ColorRGB(0x0095b6, "bondi-blue", register=True, index=True) - ColorRGB(0xe3dac9, "bone", register=True, index=True) - ColorRGB(0xdde26a, "bored-accent-green", register=True, index=True) - ColorRGB(0x0e9ca5, "boy-red", register=True, index=True) - ColorRGB(0x873260, "boysenberry", register=True, index=True) - ColorRGB(0x0070ff, "brandeis-blue", register=True, index=True) - ColorRGB(0x87413f, "brandy", register=True, index=True) - ColorRGB(0xb5a642, "brass", register=True, index=True) - ColorRGB(0xff631c, "brave-orange", register=True, index=True) - ColorRGB(0xe68364, "brewed-mustard-brown", register=True, index=True) - ColorRGB(0xcb4154, "brick-red", register=True, index=True) - ColorRGB(0xebecf0, "bright-gray", register=True, index=True) - ColorRGB(0x66ff00, "bright-green", register=True, index=True) - ColorRGB(0xbf94e4, "bright-lavender", register=True, index=True) - ColorRGB(0xd891ef, "bright-lilac", register=True, index=True) - ColorRGB(0xc32148, "bright-maroon", register=True, index=True) - ColorRGB(0x1974d2, "bright-navy-blue", register=True, index=True) - ColorRGB(0xff007f, "bright-pink", register=True, index=True) - ColorRGB(0x08e8de, "bright-turquoise", register=True, index=True) - ColorRGB(0xd19fe8, "bright-ube", register=True, index=True) - ColorRGB(0xffaa1d, "bright-yellow", register=True, index=True) - ColorRGB(0x3399ff, "brilliant-azure", register=True, index=True) - ColorRGB(0xf4bbff, "brilliant-lavender", register=True, index=True) - ColorRGB(0xff55a3, "brilliant-rose", register=True, index=True) - ColorRGB(0xfb607f, "brink-pink", register=True, index=True) - ColorRGB(0x004225, "british-racing-green", register=True, index=True) - ColorRGB(0xcd7f32, "bronze", register=True, index=True, variation_map={ - 0x88540b: "2", - 0xb08d57: "metallic" }) - ColorRGB(0x737000, "bronze-yellow", register=True, index=True) - ColorRGB(0x3d504b, "brookmere-green", register=True, index=True) - ColorRGB(0x993300, "brown", register=True, index=True, variation_map={ - 0xaf593e: "crayola", - 0x964b00: "traditional" }) - ColorRGB(0x5f1933, "brown-chocolate", register=True, index=True) - ColorRGB(0x4a2c2a, "brown-coffee", register=True, index=True) - ColorRGB(0x6b4423, "brown-nose", register=True, index=True) - ColorRGB(0x4b3c39, "brown-rat-gray", register=True, index=True) - ColorRGB(0xaf6e4d, "brown-sugar", register=True, index=True) - ColorRGB(0xcc9966, "brown-yellow", register=True, index=True) - ColorRGB(0x1b4d3e, "brunswick-green", register=True, index=True) - ColorRGB(0x8c5939, "brushwood-dyed", register=True, index=True) - ColorRGB(0xffc1cc, "bubble-gum", register=True, index=True) - ColorRGB(0xe7feff, "bubbles", register=True, index=True) - ColorRGB(0x7bb661, "bud-green", register=True, index=True) - ColorRGB(0xf0dc82, "buff", register=True, index=True) - ColorRGB(0x480607, "bulgarian-rose", register=True, index=True) - ColorRGB(0x800020, "burgundy", register=True, index=True) - ColorRGB(0xdeb887, "burlywood", register=True, index=True) - ColorRGB(0xa17a74, "burnished-brown", register=True, index=True) - ColorRGB(0xcc5500, "burnt-orange", register=True, index=True) - ColorRGB(0xe97451, "burnt-sienna", register=True, index=True) - ColorRGB(0x8a3324, "burnt-umber", register=True, index=True) - ColorRGB(0x24a0ed, "button-blue", register=True, index=True) - ColorRGB(0xbd33a4, "byzantine", register=True, index=True) - ColorRGB(0x702963, "byzantium", register=True, index=True) - ColorRGB(0x536872, "cadet", register=True, index=True) - ColorRGB(0x5f9ea0, "cadet-blue", register=True, index=True, variation_map={ - 0xa9b2c3: "crayola" }) - ColorRGB(0x91a3b0, "cadet-gray", register=True, index=True) - ColorRGB(0x0a1195, "cadmium-blue", register=True, index=True) - ColorRGB(0x006b3c, "cadmium-green", register=True, index=True) - ColorRGB(0xed872d, "cadmium-orange", register=True, index=True) - ColorRGB(0xb60c26, "cadmium-purple", register=True, index=True) - ColorRGB(0xe30022, "cadmium-red", register=True, index=True) - ColorRGB(0x7f3e98, "cadmium-violet", register=True, index=True) - ColorRGB(0xfff600, "cadmium-yellow", register=True, index=True) - ColorRGB(0xa67b5b, "cafe-au-lait", register=True, index=True) - ColorRGB(0x4b3621, "cafe-noir", register=True, index=True) - ColorRGB(0x1e4d2b, "cal-poly-pomona-green", register=True, index=True) - ColorRGB(0xfcffa4, "calamansi", register=True, index=True) - ColorRGB(0xa3c1ad, "cambridge-blue", register=True, index=True) - ColorRGB(0xc19a6b, "camel", register=True, index=True) - ColorRGB(0xefbbcc, "cameo-pink", register=True, index=True) - ColorRGB(0x78866b, "camouflage-green", register=True, index=True) - ColorRGB(0xffff99, "canary", register=True, index=True) - ColorRGB(0xffef00, "canary-yellow", register=True, index=True) - ColorRGB(0xff0800, "candy-apple-red", register=True, index=True) - ColorRGB(0xe4717a, "candy-pink", register=True, index=True) - ColorRGB(0xffb95a, "cape-jasmine-or-gardenia", register=True, index=True) - ColorRGB(0x00bfff, "capri", register=True, index=True) - ColorRGB(0x592720, "caput-mortuum", register=True, index=True) - ColorRGB(0xffd59a, "caramel", register=True, index=True) - ColorRGB(0xc41e3a, "cardinal", register=True, index=True) - ColorRGB(0x1ac1dd, "caribbean-blue", register=True, index=True) - ColorRGB(0x00cc99, "caribbean-green", register=True, index=True) - ColorRGB(0x960018, "carmine", register=True, index=True, variation_map={ - 0xd70040: "m-p" }) - ColorRGB(0xeb4c42, "carmine-pink", register=True, index=True) - ColorRGB(0xff0038, "carmine-red", register=True, index=True) - ColorRGB(0xffa6c9, "carnation-pink", register=True, index=True) - ColorRGB(0xb31b1b, "carnelian", register=True, index=True) - ColorRGB(0x56a0d3, "carolina-blue", register=True, index=True) - ColorRGB(0xed9121, "carrot-orange", register=True, index=True) - ColorRGB(0x00563f, "castleton-green", register=True, index=True) - ColorRGB(0x062a78, "catalina-blue", register=True, index=True) - ColorRGB(0x703642, "catawba", register=True, index=True) - ColorRGB(0xb64925, "cattail", register=True, index=True) - ColorRGB(0xc95a49, "cedar-chest", register=True, index=True) - ColorRGB(0x92a1cf, "ceil", register=True, index=True) - ColorRGB(0xace1af, "celadon", register=True, index=True, variation_map={ - 0x819c8b: "seiji-iro" }) - ColorRGB(0x007ba7, "celadon-blue", register=True, index=True) - ColorRGB(0x2f847c, "celadon-green", register=True, index=True) - ColorRGB(0xb2ffff, "celeste", register=True, index=True) - ColorRGB(0x4997d0, "celestial-blue", register=True, index=True) - ColorRGB(0x246bce, "celtic-blue", register=True, index=True) - ColorRGB(0xde3163, "cerise", register=True, index=True) - ColorRGB(0xec3b83, "cerise-pink", register=True, index=True) - ColorRGB(0x2a52be, "cerulean-blue", register=True, index=True) - ColorRGB(0x6d9bc3, "cerulean-frost", register=True, index=True) - ColorRGB(0x001440, "cetacean-blue", register=True, index=True) - ColorRGB(0x007aa5, "cg-blue", register=True, index=True) - ColorRGB(0xe03c31, "cg-red", register=True, index=True) - ColorRGB(0xa0785a, "chamoisee", register=True, index=True) - ColorRGB(0xf7e7ce, "champagne", register=True, index=True) - ColorRGB(0xf1ddcf, "champagne-pink", register=True, index=True) - ColorRGB(0x36454f, "charcoal", register=True, index=True) - ColorRGB(0x232b2b, "charleston-green", register=True, index=True) - ColorRGB(0xd0748b, "charm", register=True, index=True) - ColorRGB(0xe68fac, "charm-pink", register=True, index=True) - ColorRGB(0xdfff00, "chartreuse", register=True, index=True) - ColorRGB(0xffa600, "cheese", register=True, index=True) - ColorRGB(0xfcc9b9, "cherry-blossom", register=True, index=True) - ColorRGB(0xac8181, "cherry-blossom-mouse", register=True, index=True) - ColorRGB(0xffb7c5, "cherry-blossom-pink", register=True, index=True) - ColorRGB(0x954535, "chestnut", register=True, index=True) - ColorRGB(0x60281e, "chestnut-leather-brown", register=True, index=True) - ColorRGB(0xffc34d, "chickadee", register=True, index=True) - ColorRGB(0xde6fa1, "china-pink", register=True, index=True) - ColorRGB(0xa8516e, "china-rose", register=True, index=True) - ColorRGB(0x141414, "chinese-black", register=True, index=True) - ColorRGB(0x365194, "chinese-blue", register=True, index=True) - ColorRGB(0xcd8032, "chinese-bronze", register=True, index=True) - ColorRGB(0xab381f, "chinese-brown", register=True, index=True) - ColorRGB(0xcc9900, "chinese-gold", register=True, index=True) - ColorRGB(0xd0db61, "chinese-green", register=True, index=True) - ColorRGB(0xf37042, "chinese-orange", register=True, index=True) - ColorRGB(0xde70a1, "chinese-pink", register=True, index=True) - ColorRGB(0x720b98, "chinese-purple", register=True, index=True) - ColorRGB(0xaa381e, "chinese-red", register=True, index=True, variation_map={ - 0xcd071e: "2" }) - ColorRGB(0xcccccc, "chinese-silver", register=True, index=True) - ColorRGB(0x856088, "chinese-violet", register=True, index=True) - ColorRGB(0xe2e5de, "chinese-white", register=True, index=True) - ColorRGB(0xffb200, "chinese-yellow", register=True, index=True) - ColorRGB(0xb7702d, "chinese-yellow-tea", register=True, index=True) - ColorRGB(0x4aff00, "chlorophyll-green", register=True, index=True) - ColorRGB(0x7b3f00, "chocolate", register=True, index=True) - ColorRGB(0x3f000f, "chocolate-brown", register=True, index=True) - ColorRGB(0x58111a, "chocolate-cosmos", register=True, index=True) - ColorRGB(0x3c1421, "chocolate-kisses", register=True, index=True) - ColorRGB(0xa8a9ad, "chrome-aluminum", register=True, index=True) - ColorRGB(0xffa700, "chrome-yellow", register=True, index=True) - ColorRGB(0x98817b, "cinereous", register=True, index=True) - ColorRGB(0xe34234, "cinnabar", register=True, index=True) - ColorRGB(0xd2691e, "cinnamon", register=True, index=True) - ColorRGB(0xcd607e, "cinnamon-satin", register=True, index=True) - ColorRGB(0xe4d00a, "citrine", register=True, index=True) - ColorRGB(0x933709, "citrine-brown", register=True, index=True) - ColorRGB(0x9fa91f, "citron", register=True, index=True) - ColorRGB(0x7f1734, "claret", register=True, index=True) - ColorRGB(0xfbcce7, "classic-rose", register=True, index=True) - ColorRGB(0x8f583c, "clove-brown", register=True, index=True) - ColorRGB(0xa96232, "clove-dyed", register=True, index=True) - ColorRGB(0x181b26, "coarse-wool", register=True, index=True) - ColorRGB(0x0047ab, "cobalt-blue", register=True, index=True) - ColorRGB(0x965a3e, "coconut", register=True, index=True) - ColorRGB(0xe9edf6, "coconut-white", register=True, index=True) - ColorRGB(0x524b2a, "codium-fragile-seaweed", register=True, index=True) - ColorRGB(0x6f4e37, "coffee", register=True, index=True) - ColorRGB(0x3c3024, "cola", register=True, index=True) - ColorRGB(0xc4d8e2, "columbia-blue", register=True, index=True) - ColorRGB(0xffffcc, "conditioner", register=True, index=True) - ColorRGB(0xf88379, "congo-pink", register=True, index=True) - ColorRGB(0x665343, "contemplation-in-a-tea-garden", register=True, index=True) - ColorRGB(0xeee0b1, "cookies-and-cream", register=True, index=True) - ColorRGB(0x002e63, "cool-black", register=True, index=True) - ColorRGB(0x8c92ac, "cool-gray", register=True, index=True) - ColorRGB(0xb87333, "copper", register=True, index=True, variation_map={ - 0xda8a67: "crayola" }) - ColorRGB(0xad6f69, "copper-penny", register=True, index=True) - ColorRGB(0xcb6d51, "copper-red", register=True, index=True) - ColorRGB(0x996666, "copper-rose", register=True, index=True) - ColorRGB(0xff3800, "coquelicot", register=True, index=True) - ColorRGB(0xff7f50, "coral", register=True, index=True, variation_map={ - 0xf8674f: "sango-iro" }) - ColorRGB(0xff4040, "coral-red", register=True, index=True) - ColorRGB(0xfd7c6e, "coral-reef", register=True, index=True, variation_map={ - 0xf6a494: "valspar-paint" }) - ColorRGB(0x893f45, "cordovan", register=True, index=True) - ColorRGB(0xfbec5d, "corn", register=True, index=True, variation_map={ - 0xfaa945: "tomorokoshi-iro" }) - ColorRGB(0x93ccea, "cornflower", register=True, index=True) - ColorRGB(0x6495ed, "cornflower-blue", register=True, index=True) - ColorRGB(0xfff8dc, "cornsilk", register=True, index=True) - ColorRGB(0x2e2d88, "cosmic-cobalt", register=True, index=True) - ColorRGB(0xfff8e7, "cosmic-latte", register=True, index=True) - ColorRGB(0xffbcd9, "cotton-candy", register=True, index=True) - ColorRGB(0x81613c, "coyote-brown", register=True, index=True) - ColorRGB(0xfffdd0, "cream", register=True, index=True) - ColorRGB(0xdc143c, "crimson", register=True, index=True) - ColorRGB(0xbe0032, "crimson-glory", register=True, index=True) - ColorRGB(0x990000, "crimson-red", register=True, index=True) - ColorRGB(0xa7d8de, "crystal", register=True, index=True) - ColorRGB(0x68a0b0, "crystal-blue", register=True, index=True) - ColorRGB(0xf5f5f5, "cultured", register=True, index=True) - ColorRGB(0x00b7eb, "cyan", register=True, index=True, variation_map={ - 0x008080: "xterm" }) - ColorRGB(0x4e82b4, "cyan-azure", register=True, index=True) - ColorRGB(0x4682bf, "cyan-blue-azure", register=True, index=True) - ColorRGB(0x28589c, "cyan-cobalt-blue", register=True, index=True) - ColorRGB(0x188bc2, "cyan-cornflower-blue", register=True, index=True) - ColorRGB(0x58427c, "cyber-grape", register=True, index=True) - ColorRGB(0xffd300, "cyber-yellow", register=True, index=True) - ColorRGB(0xf56fa1, "cyclamen", register=True, index=True) - ColorRGB(0x752e23, "cypress-bark", register=True, index=True) - ColorRGB(0x6f3028, "cypress-bark-red", register=True, index=True) - ColorRGB(0xffff31, "daffodil", register=True, index=True) - ColorRGB(0xf0e130, "dandelion", register=True, index=True, variation_map={ - 0xfddb6d: "crayola" }) - ColorRGB(0x00008b, "dark-blue", register=True, index=True, variation_map={ - 0x192236: "kon" }) - ColorRGB(0x666699, "dark-blue-gray", register=True, index=True) - ColorRGB(0x1b294b, "dark-blue-lapis-lazuli", register=True, index=True) - ColorRGB(0x804a00, "dark-bronze", register=True, index=True, variation_map={ - 0x514100: "coin" }) - ColorRGB(0x654321, "dark-brown", register=True, index=True) - ColorRGB(0x88654e, "dark-brown-tangelo", register=True, index=True) - ColorRGB(0x5d3954, "dark-byzantium", register=True, index=True) - ColorRGB(0xa40000, "dark-candy-apple-red", register=True, index=True) - ColorRGB(0x08457e, "dark-cerulean", register=True, index=True) - ColorRGB(0x333333, "dark-charcoal", register=True, index=True) - ColorRGB(0x986960, "dark-chestnut", register=True, index=True) - ColorRGB(0x490206, "dark-chocolate", register=True, index=True, variation_map={ - 0x3c1321: "hersheys" }) - ColorRGB(0xcd5b45, "dark-coral", register=True, index=True) - ColorRGB(0x26428b, "dark-cornflower-blue", register=True, index=True) - ColorRGB(0x008b8b, "dark-cyan", register=True, index=True) - ColorRGB(0x536878, "dark-electric-blue", register=True, index=True) - ColorRGB(0xaa6c39, "dark-gold", register=True, index=True) - ColorRGB(0xb8860b, "dark-goldenrod", register=True, index=True) - ColorRGB(0xa9a9a9, "dark-gray", register=True, index=True) - ColorRGB(0x013220, "dark-green", register=True, index=True, variation_map={ - 0x006400: "x11" }) - ColorRGB(0x1f262a, "dark-gunmetal", register=True, index=True) - ColorRGB(0x00147e, "dark-imperial-blue", register=True, index=True, variation_map={ - 0x00416a: "2" }) - ColorRGB(0x614e6e, "dark-indigo", register=True, index=True) - ColorRGB(0x1a2421, "dark-jungle-green", register=True, index=True) - ColorRGB(0xbdb76b, "dark-khaki", register=True, index=True) - ColorRGB(0x483c32, "dark-lava", register=True, index=True) - ColorRGB(0x734f96, "dark-lavender", register=True, index=True) - ColorRGB(0x8bbe1b, "dark-lemon-lime", register=True, index=True) - ColorRGB(0x534b4f, "dark-liver", register=True, index=True, variation_map={ - 0x543d37: "horses" }) - ColorRGB(0x8b008b, "dark-magenta", register=True, index=True) - ColorRGB(0x003366, "dark-midnight-blue", register=True, index=True) - ColorRGB(0x4a5d23, "dark-moss-green", register=True, index=True) - ColorRGB(0x02075d, "dark-navy", register=True, index=True) - ColorRGB(0x556b2f, "dark-olive-green", register=True, index=True) - ColorRGB(0xff8c00, "dark-orange", register=True, index=True) - ColorRGB(0x9932cc, "dark-orchid", register=True, index=True) - ColorRGB(0x779ecb, "dark-pastel-blue", register=True, index=True) - ColorRGB(0x03c03c, "dark-pastel-green", register=True, index=True) - ColorRGB(0x966fd6, "dark-pastel-purple", register=True, index=True) - ColorRGB(0xc23b22, "dark-pastel-red", register=True, index=True) - ColorRGB(0xe75480, "dark-pink", register=True, index=True) - ColorRGB(0x003399, "dark-powder-blue", register=True, index=True) - ColorRGB(0x4f3a3c, "dark-puce", register=True, index=True) - ColorRGB(0x301934, "dark-purple", register=True, index=True) - ColorRGB(0x872657, "dark-raspberry", register=True, index=True) - ColorRGB(0x8b0000, "dark-red", register=True, index=True, variation_map={ - 0x23191e: "kurobeni" }) - ColorRGB(0xe9967a, "dark-salmon", register=True, index=True) - ColorRGB(0x560319, "dark-scarlet", register=True, index=True) - ColorRGB(0x8fbc8f, "dark-sea-green", register=True, index=True) - ColorRGB(0x3c1414, "dark-sienna", register=True, index=True) - ColorRGB(0x71706e, "dark-silver", register=True, index=True) - ColorRGB(0x8cbed6, "dark-sky-blue", register=True, index=True) - ColorRGB(0x483d8b, "dark-slate-blue", register=True, index=True) - ColorRGB(0x2f4f4f, "dark-slate-gray", register=True, index=True) - ColorRGB(0x177245, "dark-spring-green", register=True, index=True) - ColorRGB(0x918151, "dark-tan", register=True, index=True) - ColorRGB(0xffa812, "dark-tangerine", register=True, index=True) - ColorRGB(0xcc4e5c, "dark-terra-cotta", register=True, index=True) - ColorRGB(0x00ced1, "dark-turquoise", register=True, index=True) - ColorRGB(0xd1bea8, "dark-vanilla", register=True, index=True) - ColorRGB(0x9400d3, "dark-violet", register=True, index=True) - ColorRGB(0x9b870c, "dark-yellow", register=True, index=True) - ColorRGB(0x00703c, "dartmouth-green", register=True, index=True) - ColorRGB(0x555555, "davys-gray", register=True, index=True) - ColorRGB(0xfa7b62, "dawn", register=True, index=True) - ColorRGB(0x616359, "dawn-gray", register=True, index=True) - ColorRGB(0xff8936, "daylily", register=True, index=True) - ColorRGB(0xd70a53, "debian-red", register=True, index=True) - ColorRGB(0xd57835, "decaying-leaves", register=True, index=True) - ColorRGB(0x9c8aa4, "deep-amethyst", register=True, index=True) - ColorRGB(0x40826d, "deep-aquamarine", register=True, index=True) - ColorRGB(0xa9203e, "deep-carmine", register=True, index=True) - ColorRGB(0xef3038, "deep-carmine-pink", register=True, index=True) - ColorRGB(0xe9692c, "deep-carrot-orange", register=True, index=True) - ColorRGB(0xda3287, "deep-cerise", register=True, index=True) - ColorRGB(0xfad6a5, "deep-champagne", register=True, index=True) - ColorRGB(0xb94e48, "deep-chestnut", register=True, index=True) - ColorRGB(0x704241, "deep-coffee", register=True, index=True) - ColorRGB(0x9b351b, "deep-dumpling", register=True, index=True) - ColorRGB(0xc154c1, "deep-fuchsia", register=True, index=True) - ColorRGB(0x056608, "deep-green", register=True, index=True) - ColorRGB(0x0e7c61, "deep-green-cyan-turquoise", register=True, index=True) - ColorRGB(0x004b49, "deep-jungle-green", register=True, index=True) - ColorRGB(0x333366, "deep-koamaru", register=True, index=True) - ColorRGB(0xf5c71a, "deep-lemon", register=True, index=True) - ColorRGB(0x9955bb, "deep-lilac", register=True, index=True) - ColorRGB(0xcc00cc, "deep-magenta", register=True, index=True) - ColorRGB(0x820000, "deep-maroon", register=True, index=True) - ColorRGB(0xd473d4, "deep-mauve", register=True, index=True) - ColorRGB(0x355e3b, "deep-moss-green", register=True, index=True) - ColorRGB(0xffcba4, "deep-peach", register=True, index=True) - ColorRGB(0xff1493, "deep-pink", register=True, index=True) - ColorRGB(0xa95c68, "deep-puce", register=True, index=True) - ColorRGB(0x3a243b, "deep-purple", register=True, index=True) - ColorRGB(0x850101, "deep-red", register=True, index=True) - ColorRGB(0x843f5b, "deep-ruby", register=True, index=True) - ColorRGB(0xff9933, "deep-saffron", register=True, index=True) - ColorRGB(0x7b3b3a, "deep-scarlet", register=True, index=True) - ColorRGB(0x4a646c, "deep-space-sparkle", register=True, index=True) - ColorRGB(0x7e5e60, "deep-taupe", register=True, index=True) - ColorRGB(0x66424d, "deep-tuscan-red", register=True, index=True) - ColorRGB(0x330066, "deep-violet", register=True, index=True) - ColorRGB(0xba8759, "deer", register=True, index=True) - ColorRGB(0x6ab2ca, "delicate-girl-blue", register=True, index=True) - ColorRGB(0x1560bd, "denim", register=True, index=True) - ColorRGB(0x2243b6, "denim-blue", register=True, index=True) - ColorRGB(0x669999, "desaturated-cyan", register=True, index=True) - ColorRGB(0xedc9af, "desert-sand", register=True, index=True) - ColorRGB(0xea3c53, "desire", register=True, index=True) - ColorRGB(0xb9f2ff, "diamond", register=True, index=True) - ColorRGB(0x696969, "dim-gray", register=True, index=True) - ColorRGB(0xc53151, "dingy-dungeon", register=True, index=True) - ColorRGB(0x9b7653, "dirt", register=True, index=True) - ColorRGB(0xb5651e, "dirty-brown", register=True, index=True) - ColorRGB(0xe8e4c9, "dirty-white", register=True, index=True) - ColorRGB(0x3f313a, "disappearing-purple", register=True, index=True) - ColorRGB(0x1e90ff, "dodger-blue", register=True, index=True) - ColorRGB(0xfef65b, "dodie-yellow", register=True, index=True) - ColorRGB(0xd71868, "dogwood-rose", register=True, index=True) - ColorRGB(0x85bb65, "dollar-bill", register=True, index=True) - ColorRGB(0x828e84, "dolphin-gray", register=True, index=True) - ColorRGB(0x2496cd, "douban-blue", register=True, index=True) - ColorRGB(0x2e963d, "douban-green", register=True, index=True) - ColorRGB(0xf7c58e, "douban-light-yellow", register=True, index=True) - ColorRGB(0x755d5b, "dove-feather-gray", register=True, index=True) - ColorRGB(0x00009c, "duke-blue", register=True, index=True) - ColorRGB(0x4f4944, "dull-blue", register=True, index=True) - ColorRGB(0xb07939, "durian", register=True, index=True) - ColorRGB(0xe6d0ab, "durian-white", register=True, index=True) - ColorRGB(0xe1bd27, "durian-yellow", register=True, index=True) - ColorRGB(0xe5ccc9, "dust-storm", register=True, index=True) - ColorRGB(0xefdfbb, "dutch-white", register=True, index=True) - ColorRGB(0x913225, "dyestalk-red", register=True, index=True) - ColorRGB(0xe1a95f, "earth-yellow", register=True, index=True) - ColorRGB(0x5d3a1a, "earthtone", register=True, index=True) - ColorRGB(0x555d50, "ebony", register=True, index=True) - ColorRGB(0xc2b280, "ecru", register=True, index=True) - ColorRGB(0x1b1b1b, "eerie-black", register=True, index=True) - ColorRGB(0xffa631, "egg", register=True, index=True) - ColorRGB(0x614051, "eggplant", register=True, index=True) - ColorRGB(0xf0ead6, "eggshell", register=True, index=True) - ColorRGB(0xe2be9f, "eggshell-paper", register=True, index=True) - ColorRGB(0x1034a6, "egyptian-blue", register=True, index=True) - ColorRGB(0x17182b, "elderberry", register=True, index=True) - ColorRGB(0x7df9ff, "electric-blue", register=True, index=True) - ColorRGB(0xb56257, "electric-brown", register=True, index=True) - ColorRGB(0xff003f, "electric-crimson", register=True, index=True) - ColorRGB(0x6f00ff, "electric-indigo", register=True, index=True) - ColorRGB(0xccff00, "electric-lime", register=True, index=True) - ColorRGB(0xff3503, "electric-orange", register=True, index=True) - ColorRGB(0xf62681, "electric-pink", register=True, index=True) - ColorRGB(0xbf00ff, "electric-purple", register=True, index=True) - ColorRGB(0xe60000, "electric-red", register=True, index=True) - ColorRGB(0x3f00ff, "electric-ultramarine", register=True, index=True) - ColorRGB(0x8f00ff, "electric-violet", register=True, index=True) - ColorRGB(0xffff33, "electric-yellow", register=True, index=True) - ColorRGB(0x50c878, "emerald", register=True, index=True) - ColorRGB(0x046307, "emerald-green", register=True, index=True) - ColorRGB(0x6c3082, "eminence", register=True, index=True) - ColorRGB(0xb48395, "english-lavender", register=True, index=True) - ColorRGB(0xab4b52, "english-red", register=True, index=True) - ColorRGB(0xcc474b, "english-vermillion", register=True, index=True) - ColorRGB(0x563c5c, "english-violet", register=True, index=True) - ColorRGB(0x96c8a2, "eton-blue", register=True, index=True) - ColorRGB(0x44d7a8, "eucalyptus", register=True, index=True) - ColorRGB(0x39569c, "facebook-blue", register=True, index=True) - ColorRGB(0xb0927a, "faded-sen-no-rikyus-tea", register=True, index=True) - ColorRGB(0x9b533f, "faded-spicy-red-brown", register=True, index=True) - ColorRGB(0x43242a, "fake-purple", register=True, index=True) - ColorRGB(0x801818, "falu-red", register=True, index=True) - ColorRGB(0xb53389, "fandango", register=True, index=True) - ColorRGB(0xde5285, "fandango-pink", register=True, index=True) - ColorRGB(0xf400a1, "fashion-fuchsia", register=True, index=True) - ColorRGB(0xe5aa70, "fawn", register=True, index=True) - ColorRGB(0x4d5d53, "feldgrau", register=True, index=True) - ColorRGB(0xfdd5b1, "feldspar", register=True, index=True) - ColorRGB(0x4f7942, "fern-green", register=True, index=True) - ColorRGB(0xff2800, "ferrari-red", register=True, index=True) - ColorRGB(0x6c541e, "field-drab", register=True, index=True) - ColorRGB(0xff5470, "fiery-rose", register=True, index=True) - ColorRGB(0x957b38, "finch-brown", register=True, index=True) - ColorRGB(0xce2029, "fire-engine-red", register=True, index=True) - ColorRGB(0xe95c4b, "fire-opal", register=True, index=True) - ColorRGB(0xb22222, "firebrick", register=True, index=True) - ColorRGB(0xe25822, "flame", register=True, index=True) - ColorRGB(0xfc8eac, "flamingo-pink", register=True, index=True) - ColorRGB(0xf7e98e, "flavescent", register=True, index=True) - ColorRGB(0xeedc82, "flax", register=True, index=True) - ColorRGB(0xffe9d1, "flesh", register=True, index=True) - ColorRGB(0x216bd6, "flickr-blue", register=True, index=True) - ColorRGB(0xfb0081, "flickr-pink", register=True, index=True) - ColorRGB(0xa2006d, "flirt", register=True, index=True) - ColorRGB(0x473f2d, "flirtatious-indigo-tea", register=True, index=True) - ColorRGB(0xffb94e, "floral-leaf", register=True, index=True) - ColorRGB(0xfffaf0, "floral-white", register=True, index=True) - ColorRGB(0xf498ad, "flower-girl", register=True, index=True) - ColorRGB(0x15f4ee, "fluorescent-blue", register=True, index=True) - ColorRGB(0xff004f, "folly", register=True, index=True) - ColorRGB(0xc91f37, "foreign-crimson", register=True, index=True) - ColorRGB(0x228b22, "forest-green", register=True, index=True, variation_map={ - 0x5fa777: "crayola", - 0x014421: "traditional" }) - ColorRGB(0x985629, "fox", register=True, index=True) - ColorRGB(0x856d4d, "french-bistre", register=True, index=True) - ColorRGB(0x0072bb, "french-blue", register=True, index=True) - ColorRGB(0xfd3f92, "french-fuchsia", register=True, index=True) - ColorRGB(0x86608e, "french-lilac", register=True, index=True) - ColorRGB(0x9efd38, "french-lime", register=True, index=True) - ColorRGB(0xfd6c9e, "french-pink", register=True, index=True) - ColorRGB(0x811453, "french-plum", register=True, index=True) - ColorRGB(0x4e1609, "french-puce", register=True, index=True) - ColorRGB(0xc72c48, "french-raspberry", register=True, index=True) - ColorRGB(0xf64a8a, "french-rose", register=True, index=True) - ColorRGB(0x77b5fe, "french-sky-blue", register=True, index=True) - ColorRGB(0x8806ce, "french-violet", register=True, index=True) - ColorRGB(0xac1e44, "french-wine", register=True, index=True) - ColorRGB(0xa6e7ff, "fresh-air", register=True, index=True) - ColorRGB(0x5b8930, "fresh-onion", register=True, index=True) - ColorRGB(0xe936a7, "frostbite", register=True, index=True) - ColorRGB(0xff00ff, "fuchsia", register=True, index=True) - ColorRGB(0xff77ff, "fuchsia-pink", register=True, index=True) - ColorRGB(0xcc397b, "fuchsia-purple", register=True, index=True) - ColorRGB(0xc74375, "fuchsia-rose", register=True, index=True) - ColorRGB(0x000000, "full-black", register=True, index=True, aliases=['true-black', 'pure-black']) - ColorRGB(0x0000ff, "full-blue", register=True, index=True) - ColorRGB(0x00ffff, "full-cyan", register=True, index=True) - ColorRGB(0x00ff00, "full-green", register=True, index=True) - ColorRGB(0xff00ff, "full-magenta", register=True, index=True) - ColorRGB(0xff0000, "full-red", register=True, index=True) - ColorRGB(0xffffff, "full-white", register=True, index=True, aliases=['true-white', 'pure-white']) - ColorRGB(0xffff00, "full-yellow", register=True, index=True) - ColorRGB(0xe48400, "fulvous", register=True, index=True) - ColorRGB(0xcc6666, "fuzzy-wuzzy", register=True, index=True) - ColorRGB(0xdcdcdc, "gainsboro", register=True, index=True) - ColorRGB(0xe49b0f, "gamboge", register=True, index=True, variation_map={ - 0xffb61e: "too" }) - ColorRGB(0x996600, "gamboge-orange", register=True, index=True) - ColorRGB(0xffdf46, "gargoyle-gas", register=True, index=True) - ColorRGB(0x733635, "garnet", register=True, index=True) - ColorRGB(0x007f66, "generic-viridian", register=True, index=True) - ColorRGB(0xf8f8ff, "ghost-white", register=True, index=True) - ColorRGB(0xb05c52, "giants-club", register=True, index=True) - ColorRGB(0xfe5a1d, "giants-orange", register=True, index=True) - ColorRGB(0xd8e4bc, "gin", register=True, index=True) - ColorRGB(0x6082b6, "glaucous", register=True, index=True) - ColorRGB(0xd34e36, "glazed-persimmon", register=True, index=True) - ColorRGB(0xab92b3, "glossy-grape", register=True, index=True) - ColorRGB(0x00ab66, "go-green", register=True, index=True) - ColorRGB(0xa57c00, "gold", register=True, index=True, variation_map={ - 0xe6be8a: "crayola", - 0xd4af37: "metallic" }) - ColorRGB(0xcb7e1f, "gold-brown", register=True, index=True) - ColorRGB(0xbd9b16, "gold-foil", register=True, index=True) - ColorRGB(0x85754e, "gold-fusion", register=True, index=True) - ColorRGB(0xffd700, "golden", register=True, index=True) - ColorRGB(0x996515, "golden-brown", register=True, index=True, variation_map={ - 0xc66b27: "kincha" }) - ColorRGB(0xe29c45, "golden-fallen-leaves", register=True, index=True) - ColorRGB(0x7d4e2d, "golden-gray-bamboo", register=True, index=True) - ColorRGB(0xbb8141, "golden-oak", register=True, index=True) - ColorRGB(0xfcc200, "golden-poppy", register=True, index=True) - ColorRGB(0xffdf00, "golden-yellow", register=True, index=True, variation_map={ - 0xffa400: "and-a-particular-rose-varietal" }) - ColorRGB(0xdaa520, "goldenrod", register=True, index=True) - ColorRGB(0x4c8bf5, "google-chrome-blue", register=True, index=True) - ColorRGB(0x1aa260, "google-chrome-green", register=True, index=True) - ColorRGB(0xde5246, "google-chrome-red", register=True, index=True) - ColorRGB(0xffce44, "google-chrome-yellow", register=True, index=True) - ColorRGB(0x203838, "goryeo-storeroom", register=True, index=True) - ColorRGB(0x676767, "granite-gray", register=True, index=True) - ColorRGB(0xa8e4a0, "granny-smith-apple", register=True, index=True) - ColorRGB(0x6f2da8, "grape", register=True, index=True) - ColorRGB(0x63424b, "grape-mouse", register=True, index=True) - ColorRGB(0xbebebe, "gray", register=True, index=True) - ColorRGB(0x465945, "gray-asparagus", register=True, index=True) - ColorRGB(0xbc2d29, "grayed-red", register=True, index=True) - ColorRGB(0x656255, "grayish-dark-green", register=True, index=True) - ColorRGB(0x923916, "grecian-bronze", register=True, index=True) - ColorRGB(0x1cac78, "green", register=True, index=True, variation_map={ - 0x2a603b: "midori", - 0x00a877: "munsell", - 0x009f6b: "ncs", - 0x00ad43: "pantone", - 0x00a550: "pigment", - 0x66b032: "ryb", - 0x008000: "xterm" }) - ColorRGB(0x006442, "green-bamboo", register=True, index=True) - ColorRGB(0x1164b4, "green-blue", register=True, index=True, variation_map={ - 0x2887c8: "crayola" }) - ColorRGB(0x4c721d, "green-cola", register=True, index=True) - ColorRGB(0x009966, "green-cyan", register=True, index=True) - ColorRGB(0xa7f432, "green-lizard", register=True, index=True) - ColorRGB(0x6eaea1, "green-sheen", register=True, index=True) - ColorRGB(0x65ff00, "green-slime", register=True, index=True) - ColorRGB(0x824b35, "green-tea", register=True, index=True) - ColorRGB(0xadff2f, "green-yellow", register=True, index=True, variation_map={ - 0xf0e891: "crayola" }) - ColorRGB(0xbda928, "greenfinch", register=True, index=True) - ColorRGB(0xa99a86, "grullo", register=True, index=True) - ColorRGB(0x2a3439, "gunmetal", register=True, index=True) - ColorRGB(0x00ff7f, "guppie-green", register=True, index=True) - ColorRGB(0xf8f8f8, "guyabano", register=True, index=True) - ColorRGB(0x663854, "halaya-ube", register=True, index=True) - ColorRGB(0x8d608c, "half", register=True, index=True) - ColorRGB(0xeb6123, "halloween-orange", register=True, index=True) - ColorRGB(0x446ccf, "han-blue", register=True, index=True) - ColorRGB(0x5218fa, "han-purple", register=True, index=True) - ColorRGB(0x757d75, "harbor-rat", register=True, index=True) - ColorRGB(0x3fff00, "harlequin", register=True, index=True) - ColorRGB(0x46cb18, "harlequin-green", register=True, index=True) - ColorRGB(0xf29cb7, "harmonious-rose", register=True, index=True) - ColorRGB(0xda9100, "harvest-gold", register=True, index=True) - ColorRGB(0x00c3e3, "hawaii-blue", register=True, index=True) - ColorRGB(0x808000, "heart-gold", register=True, index=True) - ColorRGB(0xff7a00, "heat-wave", register=True, index=True) - ColorRGB(0xdf73ff, "heliotrope", register=True, index=True) - ColorRGB(0xaa98a9, "heliotrope-gray", register=True, index=True) - ColorRGB(0xaa00bb, "heliotrope-magenta", register=True, index=True) - ColorRGB(0xf0fff0, "honeydew", register=True, index=True) - ColorRGB(0x006db0, "honolulu-blue", register=True, index=True) - ColorRGB(0x49796b, "hookers-green", register=True, index=True) - ColorRGB(0x3d5d42, "horsetail", register=True, index=True) - ColorRGB(0xff1dce, "hot-magenta", register=True, index=True) - ColorRGB(0xff69b4, "hot-pink", register=True, index=True) - ColorRGB(0xcf0a2c, "huawei-red", register=True, index=True, variation_map={ - 0xed1c24: "1987-2018" }) - ColorRGB(0xf58f84, "ibis-wing", register=True, index=True) - ColorRGB(0x71a6d2, "iceberg", register=True, index=True) - ColorRGB(0x923c01, "iced-tea", register=True, index=True) - ColorRGB(0xfcf75e, "icterine", register=True, index=True) - ColorRGB(0x71bc78, "iguana-green", register=True, index=True) - ColorRGB(0x319177, "illuminating-emerald", register=True, index=True) - ColorRGB(0x602f6b, "imperial", register=True, index=True) - ColorRGB(0x002395, "imperial-blue", register=True, index=True) - ColorRGB(0x66023c, "imperial-purple", register=True, index=True) - ColorRGB(0xed2939, "imperial-red", register=True, index=True) - ColorRGB(0xb2ec5d, "inchworm", register=True, index=True) - ColorRGB(0x4c516d, "independence", register=True, index=True) - ColorRGB(0x138808, "india-green", register=True, index=True) - ColorRGB(0xcd5c5c, "indian-red", register=True, index=True) - ColorRGB(0xe3a857, "indian-yellow", register=True, index=True) - ColorRGB(0x4b0082, "indigo", register=True, index=True, variation_map={ - 0x233067: "rainbow" }) - ColorRGB(0x2e372e, "indigo-codium-fragile-seaweed-brown", register=True, index=True) - ColorRGB(0x091f92, "indigo-dye", register=True, index=True) - ColorRGB(0x393432, "indigo-ink-brown", register=True, index=True) - ColorRGB(0xebf6f7, "indigo-white", register=True, index=True) - ColorRGB(0xff496c, "infra-red", register=True, index=True) - ColorRGB(0x27221f, "ink", register=True, index=True) - ColorRGB(0x2d4436, "insect-screen", register=True, index=True) - ColorRGB(0xc6c2b6, "inside-of-a-bottle", register=True, index=True) - ColorRGB(0x360ccc, "interdimensional-blue", register=True, index=True) - ColorRGB(0xff4f00, "international-orange", register=True, index=True, variation_map={ - 0xba160c: "engineering", - 0xc0362c: "golden-gate-bridge" }) - ColorRGB(0x5a4fcf, "iris", register=True, index=True, variation_map={ - 0x763568: "ayame-iro" }) - ColorRGB(0xa19d94, "iron", register=True, index=True, variation_map={ - 0x2b3733: "tetsu-iro" }) - ColorRGB(0x344d56, "iron-head-flower", register=True, index=True) - ColorRGB(0x2b3736, "iron-storage", register=True, index=True) - ColorRGB(0xb3446c, "irresistible", register=True, index=True) - ColorRGB(0xf4f0ec, "isabelline", register=True, index=True) - ColorRGB(0x009000, "islamic-green", register=True, index=True) - ColorRGB(0x303940, "ispahan-blue", register=True, index=True) - ColorRGB(0xe9f6ef, "italian-ice", register=True, index=True) - ColorRGB(0x635a52, "italian-leather", register=True, index=True) - ColorRGB(0x906652, "italian-roast", register=True, index=True) - ColorRGB(0xfffff0, "ivory", register=True, index=True) - ColorRGB(0x5e5545, "iwai-brown", register=True, index=True) - ColorRGB(0x3d325d, "jacarta", register=True, index=True) - ColorRGB(0x413628, "jacko-bean", register=True, index=True) - ColorRGB(0x00a86b, "jade", register=True, index=True) - ColorRGB(0x9d2933, "japanese-carmine", register=True, index=True) - ColorRGB(0x264348, "japanese-indigo", register=True, index=True) - ColorRGB(0x7f5d3b, "japanese-iris-and-sooty-bamboo", register=True, index=True) - ColorRGB(0x2f7532, "japanese-laurel", register=True, index=True) - ColorRGB(0xe2b13c, "japanese-triandra-grass", register=True, index=True) - ColorRGB(0x5b3256, "japanese-violet", register=True, index=True) - ColorRGB(0xf8de7e, "jasmine", register=True, index=True) - ColorRGB(0xd73b3e, "jasper", register=True, index=True) - ColorRGB(0xde8f4e, "jasper-orange", register=True, index=True) - ColorRGB(0xa50b5e, "jazzberry-jam", register=True, index=True) - ColorRGB(0xda614e, "jelly-bean", register=True, index=True) - ColorRGB(0x44798e, "jelly-bean-blue", register=True, index=True) - ColorRGB(0x343434, "jet", register=True, index=True) - ColorRGB(0xbbd0c9, "jet-stream", register=True, index=True) - ColorRGB(0xf4ca16, "jonquil", register=True, index=True) - ColorRGB(0x8ab9f1, "jordy-blue", register=True, index=True) - ColorRGB(0xbdda57, "june-bud", register=True, index=True) - ColorRGB(0x29ab87, "jungle-green", register=True, index=True) - ColorRGB(0x4cbb17, "kelly-green", register=True, index=True) - ColorRGB(0x7c1c05, "kenyan-copper", register=True, index=True) - ColorRGB(0x3ab09e, "keppel", register=True, index=True) - ColorRGB(0xe8f48c, "key-lime", register=True, index=True) - ColorRGB(0x3d4c51, "kimono-storage", register=True, index=True) - ColorRGB(0x8ee53f, "kiwi", register=True, index=True) - ColorRGB(0x882d17, "kobe", register=True, index=True) - ColorRGB(0xe79fc4, "kobi", register=True, index=True) - ColorRGB(0x354230, "kombu-green", register=True, index=True) - ColorRGB(0x512888, "ksu-purple", register=True, index=True) - ColorRGB(0xe8000d, "ku-crimson", register=True, index=True) - ColorRGB(0xfb9912, "kumquat", register=True, index=True) - ColorRGB(0xd6cadd, "languid-lavender", register=True, index=True) - ColorRGB(0xe0bc5b, "lanzones", register=True, index=True) - ColorRGB(0x26619c, "lapis-lazuli", register=True, index=True, variation_map={ - 0x1f4788: "ruri-iro" }) - ColorRGB(0xffff66, "laser-lemon", register=True, index=True) - ColorRGB(0xa9ba9d, "laurel-green", register=True, index=True) - ColorRGB(0xcf1020, "lava", register=True, index=True) - ColorRGB(0xb57edc, "lavender", register=True, index=True) - ColorRGB(0xccccff, "lavender-blue", register=True, index=True) - ColorRGB(0xfff0f5, "lavender-blush", register=True, index=True) - ColorRGB(0xc4c3d0, "lavender-gray", register=True, index=True) - ColorRGB(0x9457eb, "lavender-indigo", register=True, index=True) - ColorRGB(0xee82ee, "lavender-magenta", register=True, index=True) - ColorRGB(0xe6e6fa, "lavender-mist", register=True, index=True) - ColorRGB(0xfbaed2, "lavender-pink", register=True, index=True) - ColorRGB(0x967bb6, "lavender-purple", register=True, index=True) - ColorRGB(0xfba0e3, "lavender-rose", register=True, index=True) - ColorRGB(0x7cfc00, "lawn-green", register=True, index=True) - ColorRGB(0x2e211b, "legal-dye", register=True, index=True) - ColorRGB(0xfff700, "lemon", register=True, index=True) - ColorRGB(0xfffacd, "lemon-chiffon", register=True, index=True) - ColorRGB(0xcca01d, "lemon-curry", register=True, index=True) - ColorRGB(0xfdff00, "lemon-glacier", register=True, index=True) - ColorRGB(0xbd3000, "lemon-iced-tea", register=True, index=True) - ColorRGB(0xe3ff00, "lemon-lime", register=True, index=True, variation_map={ - 0x5cff67: "2" }) - ColorRGB(0xf6eabe, "lemon-meringue", register=True, index=True) - ColorRGB(0xfff44f, "lemon-yellow", register=True, index=True, variation_map={ - 0xffff9f: "crayola" }) - ColorRGB(0xba93d8, "lenurple", register=True, index=True) - ColorRGB(0x545aa7, "liberty", register=True, index=True) - ColorRGB(0x1a1110, "licorice", register=True, index=True) - ColorRGB(0xadd8e6, "light-blue", register=True, index=True, variation_map={ - 0x48929b: "asagi-iro" }) - ColorRGB(0x1d697c, "light-blue-flower", register=True, index=True) - ColorRGB(0x044f67, "light-blue-silk", register=True, index=True) - ColorRGB(0xb5651d, "light-brown", register=True, index=True) - ColorRGB(0xe66771, "light-carmine-pink", register=True, index=True) - ColorRGB(0x551f2f, "light-chocolate-cosmos", register=True, index=True) - ColorRGB(0x88ace0, "light-cobalt-blue", register=True, index=True) - ColorRGB(0xf08080, "light-coral", register=True, index=True) - ColorRGB(0xf56991, "light-crimson", register=True, index=True) - ColorRGB(0xe0ffff, "light-cyan", register=True, index=True) - ColorRGB(0xff5ccd, "light-deep-pink", register=True, index=True) - ColorRGB(0xc8ad7f, "light-french-beige", register=True, index=True) - ColorRGB(0xf984ef, "light-fuchsia-pink", register=True, index=True) - ColorRGB(0xb29700, "light-gold", register=True, index=True) - ColorRGB(0xfafad2, "light-goldenrod-yellow", register=True, index=True) - ColorRGB(0xd3d3d3, "light-gray", register=True, index=True) - ColorRGB(0xcc99cc, "light-grayish-magenta", register=True, index=True) - ColorRGB(0x90ee90, "light-green", register=True, index=True) - ColorRGB(0xffb3de, "light-hot-pink", register=True, index=True) - ColorRGB(0xf0e68c, "light-khaki", register=True, index=True) - ColorRGB(0xff80ff, "light-magenta", register=True, index=True) - ColorRGB(0xd39bcb, "light-medium-orchid", register=True, index=True) - ColorRGB(0xaddfad, "light-moss-green", register=True, index=True) - ColorRGB(0xfed8b1, "light-orange", register=True, index=True) - ColorRGB(0xe6a8d7, "light-orchid", register=True, index=True) - ColorRGB(0xb19cd9, "light-pastel-purple", register=True, index=True) - ColorRGB(0xc5cbe1, "light-periwinkle", register=True, index=True) - ColorRGB(0xffb6c1, "light-pink", register=True, index=True) - ColorRGB(0xffcccb, "light-red", register=True, index=True) - ColorRGB(0xffa07a, "light-salmon", register=True, index=True) - ColorRGB(0xff9999, "light-salmon-pink", register=True, index=True) - ColorRGB(0x20b2aa, "light-sea-green", register=True, index=True) - ColorRGB(0xd8d8d8, "light-silver", register=True, index=True) - ColorRGB(0x87cefa, "light-sky-blue", register=True, index=True) - ColorRGB(0x778899, "light-slate-gray", register=True, index=True) - ColorRGB(0xb0c4de, "light-steel-blue", register=True, index=True) - ColorRGB(0xb38b6d, "light-taupe", register=True, index=True) - ColorRGB(0xffffe0, "light-yellow", register=True, index=True, variation_map={ - 0xf7bb7d: "asagi" }) - ColorRGB(0xc8a2c8, "lilac", register=True, index=True) - ColorRGB(0xae98aa, "lilac-luster", register=True, index=True) - ColorRGB(0x32cd32, "lime-green", register=True, index=True) - ColorRGB(0xd1e189, "lime-pulp", register=True, index=True) - ColorRGB(0x9dc209, "limerick", register=True, index=True) - ColorRGB(0x195905, "lincoln-green", register=True, index=True) - ColorRGB(0xfaf0e6, "linen", register=True, index=True) - ColorRGB(0x0072b1, "linkedin-blue", register=True, index=True) - ColorRGB(0x6ca0dc, "little-boy-blue", register=True, index=True) - ColorRGB(0xf8b9d4, "little-girl-pink", register=True, index=True) - ColorRGB(0x674c47, "liver", register=True, index=True, variation_map={ - 0xb86d29: "dogs", - 0x6c2e1f: "organ" }) - ColorRGB(0x987456, "liver-chestnut", register=True, index=True) - ColorRGB(0xb95754, "long-spring", register=True, index=True) - ColorRGB(0xab6134, "loquat", register=True, index=True) - ColorRGB(0xfefdfa, "lotion", register=True, index=True) - ColorRGB(0x15f2fd, "lotion-blue", register=True, index=True) - ColorRGB(0xeccfcf, "lotion-pink", register=True, index=True) - ColorRGB(0xffe4cd, "lumber", register=True, index=True) - ColorRGB(0xe62020, "lust", register=True, index=True) - ColorRGB(0xdc5349, "lychee", register=True, index=True) - ColorRGB(0x7f6b5d, "lye", register=True, index=True) - ColorRGB(0xffbd88, "macaroni-and-cheese", register=True, index=True) - ColorRGB(0xcc3336, "madder-lake", register=True, index=True) - ColorRGB(0xca1f7b, "magenta", register=True, index=True, variation_map={ - 0xd0417e: "pantone", - 0xff0090: "process", - 0x800080: "xterm" }) - ColorRGB(0x9f4576, "magenta-haze", register=True, index=True) - ColorRGB(0xcc338b, "magenta-pink", register=True, index=True) - ColorRGB(0xaaf0d1, "magic-mint", register=True, index=True) - ColorRGB(0xff4466, "magic-potion", register=True, index=True) - ColorRGB(0xf8f4ff, "magnolia", register=True, index=True) - ColorRGB(0xc04000, "mahogany", register=True, index=True) - ColorRGB(0xf2c649, "maize", register=True, index=True) - ColorRGB(0x6050dc, "majorelle-blue", register=True, index=True) - ColorRGB(0x0bda51, "malachite", register=True, index=True) - ColorRGB(0x979aaa, "manatee", register=True, index=True) - ColorRGB(0xf37a48, "mandarin", register=True, index=True) - ColorRGB(0xfdbe02, "mango", register=True, index=True) - ColorRGB(0x96ff00, "mango-green", register=True, index=True) - ColorRGB(0xff8243, "mango-tango", register=True, index=True) - ColorRGB(0xe7c9a9, "manila", register=True, index=True) - ColorRGB(0x74c365, "mantis", register=True, index=True) - ColorRGB(0xbb9351, "maple-syrup", register=True, index=True) - ColorRGB(0x880085, "mardi-gras", register=True, index=True) - ColorRGB(0xf2d930, "margarine", register=True, index=True) - ColorRGB(0xb0c24a, "margarita", register=True, index=True) - ColorRGB(0xeaa221, "marigold", register=True, index=True) - ColorRGB(0x5e2824, "maroon", register=True, index=True, variation_map={ - 0xb03060: "x11" }) - ColorRGB(0xe0b0ff, "mauve", register=True, index=True) - ColorRGB(0x915f6d, "mauve-taupe", register=True, index=True) - ColorRGB(0xef98aa, "mauvelous", register=True, index=True) - ColorRGB(0x47abcc, "maximum-blue", register=True, index=True) - ColorRGB(0x30bfbf, "maximum-blue-green", register=True, index=True) - ColorRGB(0xacace6, "maximum-blue-purple", register=True, index=True) - ColorRGB(0x5e8c31, "maximum-green", register=True, index=True) - ColorRGB(0xd9e650, "maximum-green-yellow", register=True, index=True) - ColorRGB(0xff5b00, "maximum-orange", register=True, index=True) - ColorRGB(0x733380, "maximum-purple", register=True, index=True) - ColorRGB(0xd92121, "maximum-red", register=True, index=True) - ColorRGB(0xa63a79, "maximum-red-purple", register=True, index=True) - ColorRGB(0xfafa37, "maximum-yellow", register=True, index=True) - ColorRGB(0xf2ba49, "maximum-yellow-red", register=True, index=True) - ColorRGB(0x4c9141, "may-green", register=True, index=True) - ColorRGB(0x73c2fb, "maya-blue", register=True, index=True) - ColorRGB(0xf9906f, "meat", register=True, index=True) - ColorRGB(0xe5b73b, "meat-brown", register=True, index=True) - ColorRGB(0x66ddaa, "medium-aquamarine", register=True, index=True) - ColorRGB(0x0000cd, "medium-blue", register=True, index=True) - ColorRGB(0xe2062c, "medium-candy-apple-red", register=True, index=True) - ColorRGB(0xaf4035, "medium-carmine", register=True, index=True) - ColorRGB(0xf3e5ab, "medium-champagne", register=True, index=True) - ColorRGB(0xc93756, "medium-crimson", register=True, index=True) - ColorRGB(0x035096, "medium-electric-blue", register=True, index=True) - ColorRGB(0x1c352d, "medium-jungle-green", register=True, index=True) - ColorRGB(0xdda0dd, "medium-lavender-magenta", register=True, index=True) - ColorRGB(0xba55d3, "medium-orchid", register=True, index=True) - ColorRGB(0x0067a5, "medium-persian-blue", register=True, index=True) - ColorRGB(0x9370db, "medium-purple", register=True, index=True) - ColorRGB(0xbb3385, "medium-red-violet", register=True, index=True) - ColorRGB(0xaa4069, "medium-ruby", register=True, index=True) - ColorRGB(0x3cb371, "medium-sea-green", register=True, index=True) - ColorRGB(0x80daeb, "medium-sky-blue", register=True, index=True) - ColorRGB(0x7b68ee, "medium-slate-blue", register=True, index=True) - ColorRGB(0xc9dc87, "medium-spring-bud", register=True, index=True) - ColorRGB(0x00fa9a, "medium-spring-green", register=True, index=True) - ColorRGB(0x48d1cc, "medium-turquoise", register=True, index=True) - ColorRGB(0xd9603b, "medium-vermilion", register=True, index=True) - ColorRGB(0xc71585, "medium-violet-red", register=True, index=True) - ColorRGB(0xfdbcb4, "melancholy", register=True, index=True) - ColorRGB(0xf8b878, "mellow-apricot", register=True, index=True) - ColorRGB(0xfebaad, "melon", register=True, index=True) - ColorRGB(0xc1f9a2, "menthol", register=True, index=True) - ColorRGB(0x32527b, "metallic-blue", register=True, index=True) - ColorRGB(0xa97142, "metallic-bronze", register=True, index=True) - ColorRGB(0xac4313, "metallic-brown", register=True, index=True) - ColorRGB(0x296e01, "metallic-green", register=True, index=True) - ColorRGB(0xda680f, "metallic-orange", register=True, index=True) - ColorRGB(0xeda6c4, "metallic-pink", register=True, index=True) - ColorRGB(0xa62c2b, "metallic-red", register=True, index=True) - ColorRGB(0x0a7e8c, "metallic-seaweed", register=True, index=True) - ColorRGB(0x9c7c38, "metallic-sunburst", register=True, index=True) - ColorRGB(0x5b0a91, "metallic-violet", register=True, index=True) - ColorRGB(0xfdcc0d, "metallic-yellow", register=True, index=True) - ColorRGB(0xe4007c, "mexican-pink", register=True, index=True) - ColorRGB(0x00a2ed, "microsoft-blue", register=True, index=True) - ColorRGB(0x0078d7, "microsoft-edge-blue", register=True, index=True) - ColorRGB(0x7db700, "microsoft-green", register=True, index=True) - ColorRGB(0xf04e1f, "microsoft-red", register=True, index=True) - ColorRGB(0xfdb900, "microsoft-yellow", register=True, index=True) - ColorRGB(0x7ed4e6, "middle-blue", register=True, index=True) - ColorRGB(0x8dd9cc, "middle-blue-green", register=True, index=True) - ColorRGB(0x8b72be, "middle-blue-purple", register=True, index=True) - ColorRGB(0x8b8680, "middle-gray", register=True, index=True) - ColorRGB(0x4d8c57, "middle-green", register=True, index=True) - ColorRGB(0xacbf60, "middle-green-yellow", register=True, index=True) - ColorRGB(0xd982b5, "middle-purple", register=True, index=True) - ColorRGB(0xe58e73, "middle-red", register=True, index=True) - ColorRGB(0xa55353, "middle-red-purple", register=True, index=True) - ColorRGB(0xffeb00, "middle-yellow", register=True, index=True) - ColorRGB(0xecb176, "middle-yellow-red", register=True, index=True) - ColorRGB(0x702670, "midnight", register=True, index=True) - ColorRGB(0x191970, "midnight-blue", register=True, index=True, variation_map={ - 0x00468c: "2" }) - ColorRGB(0x004953, "midnight-green", register=True, index=True) - ColorRGB(0xffc40c, "mikado-yellow", register=True, index=True) - ColorRGB(0xfdfff5, "milk", register=True, index=True) - ColorRGB(0x84563c, "milk-chocolate", register=True, index=True) - ColorRGB(0xffdae9, "mimi-pink", register=True, index=True) - ColorRGB(0xe3f988, "mindaro", register=True, index=True) - ColorRGB(0x36747d, "ming", register=True, index=True) - ColorRGB(0xf5e050, "minion-yellow", register=True, index=True) - ColorRGB(0x3eb489, "mint", register=True, index=True) - ColorRGB(0xf5fffa, "mint-cream", register=True, index=True) - ColorRGB(0x98ff98, "mint-green", register=True, index=True) - ColorRGB(0xbbb477, "misty-moss", register=True, index=True) - ColorRGB(0xffe4e1, "misty-rose", register=True, index=True) - ColorRGB(0xbea493, "mocha", register=True, index=True) - ColorRGB(0x3aa8c1, "moonstone", register=True, index=True) - ColorRGB(0x73a9c2, "moonstone-blue", register=True, index=True) - ColorRGB(0xae0c00, "mordant-red-19", register=True, index=True) - ColorRGB(0x8da399, "morning-blue", register=True, index=True) - ColorRGB(0x8b7d3a, "moss", register=True, index=True) - ColorRGB(0x8a9a5b, "moss-green", register=True, index=True) - ColorRGB(0x30ba8f, "mountain-meadow", register=True, index=True) - ColorRGB(0x997a8d, "mountbatten-pink", register=True, index=True) - ColorRGB(0x5c544e, "mousy-indigo", register=True, index=True) - ColorRGB(0x766980, "mousy-wisteria", register=True, index=True) - ColorRGB(0x18453b, "msu-green", register=True, index=True) - ColorRGB(0x70543e, "mud", register=True, index=True) - ColorRGB(0xcb6649, "muddy-brown", register=True, index=True) - ColorRGB(0x306030, "mughal-green", register=True, index=True) - ColorRGB(0xc54b8c, "mulberry", register=True, index=True, variation_map={ - 0xc8509b: "crayola" }) - ColorRGB(0x59292c, "mulberry-dye", register=True, index=True) - ColorRGB(0xc57f2e, "mulberry-dyed", register=True, index=True) - ColorRGB(0xffdb58, "mustard", register=True, index=True) - ColorRGB(0xcd7a00, "mustard-brown", register=True, index=True) - ColorRGB(0x6e6e30, "mustard-green", register=True, index=True) - ColorRGB(0xe1ad01, "mustard-yellow", register=True, index=True) - ColorRGB(0x317873, "myrtle-green", register=True, index=True) - ColorRGB(0xd65282, "mystic", register=True, index=True) - ColorRGB(0xad4379, "mystic-maroon", register=True, index=True) - ColorRGB(0xff5500, "mystic-red", register=True, index=True) - ColorRGB(0xf6adc6, "nadeshiko-pink", register=True, index=True) - ColorRGB(0x2a8000, "napier-green", register=True, index=True) - ColorRGB(0xfada5e, "naples-yellow", register=True, index=True) - ColorRGB(0xffdead, "navajo-white", register=True, index=True) - ColorRGB(0x000080, "navy-blue", register=True, index=True) - ColorRGB(0x191f45, "navy-blue-bellflower", register=True, index=True) - ColorRGB(0x1b03a3, "neon-blue", register=True, index=True) - ColorRGB(0xffa343, "neon-carrot", register=True, index=True) - ColorRGB(0xfe4164, "neon-fuchsia", register=True, index=True) - ColorRGB(0x39ff14, "neon-green", register=True, index=True) - ColorRGB(0x006c7f, "new-bridge", register=True, index=True) - ColorRGB(0x214fc6, "new-car", register=True, index=True) - ColorRGB(0xd7837f, "new-york-pink", register=True, index=True) - ColorRGB(0x727472, "nickel", register=True, index=True) - ColorRGB(0x5c4827, "nightingale-brown", register=True, index=True) - ColorRGB(0xe4000f, "nintendo-red", register=True, index=True) - ColorRGB(0xa4dded, "non-photo-blue", register=True, index=True) - ColorRGB(0x059033, "north-texas-green", register=True, index=True) - ColorRGB(0xe9ffdb, "nyanza", register=True, index=True) - ColorRGB(0x4f42b5, "ocean-blue", register=True, index=True) - ColorRGB(0x0077be, "ocean-boat-blue", register=True, index=True) - ColorRGB(0x48bf91, "ocean-green", register=True, index=True) - ColorRGB(0xcc7722, "ochre", register=True, index=True, variation_map={ - 0xff4e20: "earthen-yellow-red-brown", - 0xbe7f51: "lit-earthen-yellow" }) - ColorRGB(0xfd5240, "ogre-odor", register=True, index=True) - ColorRGB(0x5e644f, "old-bamboo", register=True, index=True) - ColorRGB(0x43302e, "old-burgundy", register=True, index=True) - ColorRGB(0xcfb53b, "old-gold", register=True, index=True) - ColorRGB(0xfdf5e6, "old-lace", register=True, index=True) - ColorRGB(0x796878, "old-lavender", register=True, index=True) - ColorRGB(0x673147, "old-mauve", register=True, index=True) - ColorRGB(0x867e36, "old-moss-green", register=True, index=True) - ColorRGB(0xc08081, "old-rose", register=True, index=True) - ColorRGB(0x6b8e23, "olive-drab", register=True, index=True, variation_map={ - 0x3c341f: "7" }) - ColorRGB(0xb5b35c, "olive-green", register=True, index=True) - ColorRGB(0x9ab973, "olivine", register=True, index=True) - ColorRGB(0x4e3e37, "olympic-bronze", register=True, index=True) - ColorRGB(0x364141, "onando", register=True, index=True) - ColorRGB(0xf08f90, "one-kin", register=True, index=True) - ColorRGB(0x353839, "onyx", register=True, index=True) - ColorRGB(0xa8c3bc, "opal", register=True, index=True) - ColorRGB(0xb784a7, "opera-mauve", register=True, index=True) - ColorRGB(0xff1b2d, "opera-red", register=True, index=True) - ColorRGB(0x4d646c, "opposite-flower", register=True, index=True) - ColorRGB(0xff6600, "orange", register=True, index=True, variation_map={ - 0xff7f00: "color-wheel", - 0xff7538: "crayola", - 0xff5800: "pantone", - 0xfb9902: "ryb" }) - ColorRGB(0xff9f00, "orange-peel", register=True, index=True) - ColorRGB(0xff681f, "orange-red", register=True, index=True, variation_map={ - 0xff5349: "crayola" }) - ColorRGB(0xfa5b3d, "orange-soda", register=True, index=True, variation_map={ - 0xeb593d: "2" }) - ColorRGB(0xf5bd1f, "orange-yellow", register=True, index=True, variation_map={ - 0xf8d568: "crayola" }) - ColorRGB(0xda70d6, "orchid", register=True, index=True, variation_map={ - 0xe29cd2: "crayola" }) - ColorRGB(0xf2bdcd, "orchid-pink", register=True, index=True) - ColorRGB(0xfb4f14, "orioles-orange", register=True, index=True) - ColorRGB(0x841617, "ou-crimson-red", register=True, index=True) - ColorRGB(0x414a4c, "outer-space", register=True, index=True, variation_map={ - 0x2d383a: "crayola" }) - ColorRGB(0xff6e4a, "outrageous-orange", register=True, index=True) - ColorRGB(0xe35c38, "overdyed-refreshed-red-brown", register=True, index=True) - ColorRGB(0x002147, "oxford-blue", register=True, index=True) - ColorRGB(0x6d9a79, "oxley", register=True, index=True) - ColorRGB(0x1ca9c9, "pacific-blue", register=True, index=True) - ColorRGB(0x6b4947, "painite", register=True, index=True) - ColorRGB(0x006600, "pakistan-green", register=True, index=True) - ColorRGB(0x273be2, "palatinate-blue", register=True, index=True) - ColorRGB(0x682860, "palatinate-purple", register=True, index=True) - ColorRGB(0x8c9c76, "pale-blue", register=True, index=True) - ColorRGB(0xafeeee, "pale-blue-pale-turquoise", register=True, index=True) - ColorRGB(0x987654, "pale-brown", register=True, index=True) - ColorRGB(0x9bc4e2, "pale-cerulean", register=True, index=True) - ColorRGB(0xddadaf, "pale-chestnut", register=True, index=True) - ColorRGB(0xabcdef, "pale-cornflower-blue", register=True, index=True) - ColorRGB(0x87d3f8, "pale-cyan", register=True, index=True) - ColorRGB(0xaa8736, "pale-fallen-leaves", register=True, index=True) - ColorRGB(0xeee8aa, "pale-goldenrod", register=True, index=True) - ColorRGB(0x98fb98, "pale-green", register=True, index=True) - ColorRGB(0x749f8d, "pale-green-onion", register=True, index=True) - ColorRGB(0xffa565, "pale-incense", register=True, index=True) - ColorRGB(0xdcd0ff, "pale-lavender", register=True, index=True) - ColorRGB(0xf984e5, "pale-magenta", register=True, index=True) - ColorRGB(0xff99cc, "pale-magenta-pink", register=True, index=True) - ColorRGB(0xbba46d, "pale-oak", register=True, index=True) - ColorRGB(0xfca474, "pale-persimmon", register=True, index=True) - ColorRGB(0xfadadd, "pale-pink", register=True, index=True) - ColorRGB(0xfae6fa, "pale-purple", register=True, index=True) - ColorRGB(0xdb7093, "pale-red-violet", register=True, index=True) - ColorRGB(0x96ded1, "pale-robin-egg-blue", register=True, index=True) - ColorRGB(0xc9c0bb, "pale-silver", register=True, index=True) - ColorRGB(0xecebbd, "pale-spring-bud", register=True, index=True) - ColorRGB(0xbc987e, "pale-taupe", register=True, index=True) - ColorRGB(0xcc99ff, "pale-violet", register=True, index=True) - ColorRGB(0x8db255, "pale-young-green-onion", register=True, index=True) - ColorRGB(0x6f9940, "palm-leaf", register=True, index=True) - ColorRGB(0x0040be, "panasonic-blue", register=True, index=True) - ColorRGB(0x78184a, "pansy-purple", register=True, index=True) - ColorRGB(0x009b7d, "paolo-veronese-green", register=True, index=True) - ColorRGB(0xffefd5, "papaya-whip", register=True, index=True) - ColorRGB(0xe63e62, "paradise-pink", register=True, index=True) - ColorRGB(0x7eb6ff, "parakeet-blue", register=True, index=True) - ColorRGB(0xd998a0, "parrot-pink", register=True, index=True) - ColorRGB(0xaec6cf, "pastel-blue", register=True, index=True) - ColorRGB(0x836953, "pastel-brown", register=True, index=True) - ColorRGB(0xcfcfc4, "pastel-gray", register=True, index=True) - ColorRGB(0x77dd77, "pastel-green", register=True, index=True) - ColorRGB(0xf49ac2, "pastel-magenta", register=True, index=True) - ColorRGB(0xffb347, "pastel-orange", register=True, index=True) - ColorRGB(0xdea5a4, "pastel-pink", register=True, index=True) - ColorRGB(0xb39eb5, "pastel-purple", register=True, index=True) - ColorRGB(0xff6961, "pastel-red", register=True, index=True) - ColorRGB(0xcb99c9, "pastel-violet", register=True, index=True) - ColorRGB(0xfdfd96, "pastel-yellow", register=True, index=True) - ColorRGB(0x407a52, "patina", register=True, index=True) - ColorRGB(0x800080, "patriarch", register=True, index=True) - ColorRGB(0xd9b611, "patrinia-flowers", register=True, index=True) - ColorRGB(0xffe5b4, "peach", register=True, index=True, variation_map={ - 0xf47983: "momo-iro" }) - ColorRGB(0xf39998, "peach-burst", register=True, index=True) - ColorRGB(0xffcc99, "peach-orange", register=True, index=True) - ColorRGB(0xffdab9, "peach-puff", register=True, index=True) - ColorRGB(0xfadfad, "peach-yellow", register=True, index=True) - ColorRGB(0xd1e231, "pear", register=True, index=True) - ColorRGB(0xeae0c8, "pearl", register=True, index=True) - ColorRGB(0x88d8c0, "pearl-aqua", register=True, index=True) - ColorRGB(0xb768a2, "pearly-purple", register=True, index=True) - ColorRGB(0xf5f3ef, "penguin-white", register=True, index=True) - ColorRGB(0xe6e200, "peridot", register=True, index=True) - ColorRGB(0xc3cde6, "periwinkle", register=True, index=True) - ColorRGB(0xe12c2c, "permanent-geranium-lake", register=True, index=True) - ColorRGB(0x1c39bb, "persian-blue", register=True, index=True) - ColorRGB(0x00a693, "persian-green", register=True, index=True) - ColorRGB(0x32127a, "persian-indigo", register=True, index=True) - ColorRGB(0xd99058, "persian-orange", register=True, index=True) - ColorRGB(0xf77fbe, "persian-pink", register=True, index=True) - ColorRGB(0x701c1c, "persian-plum", register=True, index=True) - ColorRGB(0xcc3333, "persian-red", register=True, index=True) - ColorRGB(0xfe28a2, "persian-rose", register=True, index=True) - ColorRGB(0xec5800, "persimmon", register=True, index=True) - ColorRGB(0x934337, "persimmon-juice", register=True, index=True) - ColorRGB(0xcd853f, "peru", register=True, index=True) - ColorRGB(0x8ba8b7, "pewter-blue", register=True, index=True) - ColorRGB(0x0038a7, "philippine-blue", register=True, index=True) - ColorRGB(0x6e3a07, "philippine-bronze", register=True, index=True) - ColorRGB(0x5d1916, "philippine-brown", register=True, index=True) - ColorRGB(0xb17304, "philippine-gold", register=True, index=True) - ColorRGB(0x8c8c8c, "philippine-gray", register=True, index=True) - ColorRGB(0x008543, "philippine-green", register=True, index=True) - ColorRGB(0xff7300, "philippine-orange", register=True, index=True) - ColorRGB(0xfa1a8e, "philippine-pink", register=True, index=True) - ColorRGB(0xce1127, "philippine-red", register=True, index=True) - ColorRGB(0xb3b3b3, "philippine-silver", register=True, index=True) - ColorRGB(0x81007f, "philippine-violet", register=True, index=True) - ColorRGB(0xfecb00, "philippine-yellow", register=True, index=True) - ColorRGB(0xdf00ff, "phlox", register=True, index=True) - ColorRGB(0x000f89, "phthalo-blue", register=True, index=True) - ColorRGB(0x123524, "phthalo-green", register=True, index=True) - ColorRGB(0x45b1e8, "picton-blue", register=True, index=True) - ColorRGB(0xc30b4e, "pictorial-carmine", register=True, index=True) - ColorRGB(0xfddde6, "piggy-pink", register=True, index=True) - ColorRGB(0x01796f, "pine-green", register=True, index=True) - ColorRGB(0x454d32, "pine-needle", register=True, index=True) - ColorRGB(0x2a2f23, "pine-tree", register=True, index=True) - ColorRGB(0x563c0d, "pineapple", register=True, index=True) - ColorRGB(0xffc0cb, "pink", register=True, index=True, variation_map={ - 0xd74894: "pantone" }) - ColorRGB(0xfc74fd, "pink-flamingo", register=True, index=True) - ColorRGB(0xffddf4, "pink-lace", register=True, index=True) - ColorRGB(0xd8b2d1, "pink-lavender", register=True, index=True) - ColorRGB(0xe7accf, "pink-pearl", register=True, index=True) - ColorRGB(0x980036, "pink-raspberry", register=True, index=True) - ColorRGB(0xf78fa7, "pink-sherbet", register=True, index=True) - ColorRGB(0x93c572, "pistachio", register=True, index=True) - ColorRGB(0x391285, "pixie-powder", register=True, index=True) - ColorRGB(0x6e5f57, "plain-mouse", register=True, index=True) - ColorRGB(0xe5e4e2, "platinum", register=True, index=True) - ColorRGB(0x8e4585, "plum", register=True, index=True) - ColorRGB(0x97645a, "plum-blossom-mouse", register=True, index=True) - ColorRGB(0xfa9258, "plum-dyed", register=True, index=True) - ColorRGB(0x8f4155, "plum-purple", register=True, index=True) - ColorRGB(0x5946b2, "plump-purple", register=True, index=True) - ColorRGB(0x35654d, "poker-green", register=True, index=True) - ColorRGB(0x985538, "polished-brown", register=True, index=True) - ColorRGB(0x5da493, "polished-pine", register=True, index=True) - ColorRGB(0x660c21, "pomegranate", register=True, index=True) - ColorRGB(0x96a53c, "pomelo", register=True, index=True) - ColorRGB(0xbfbd70, "pomelo-olive", register=True, index=True) - ColorRGB(0xf9ffe3, "pomelo-white", register=True, index=True) - ColorRGB(0xf6a08c, "poppy-petal", register=True, index=True) - ColorRGB(0xbe4f62, "popstar", register=True, index=True) - ColorRGB(0x936900, "porcupine", register=True, index=True) - ColorRGB(0xff5a36, "portland-orange", register=True, index=True) - ColorRGB(0xb0e0e6, "powder-blue", register=True, index=True) - ColorRGB(0xff85cf, "princess-perfume", register=True, index=True) - ColorRGB(0xf58025, "princeton-orange", register=True, index=True) - ColorRGB(0x003153, "prussian-blue", register=True, index=True, variation_map={ - 0x003171: "konjo-iro" }) - ColorRGB(0xcc8899, "puce", register=True, index=True) - ColorRGB(0x722f37, "puce-red", register=True, index=True) - ColorRGB(0x644117, "pullman-brown", register=True, index=True) - ColorRGB(0x3b331c, "pullman-green", register=True, index=True) - ColorRGB(0xff7518, "pumpkin", register=True, index=True) - ColorRGB(0xc3272b, "pure-crimson", register=True, index=True) - ColorRGB(0x6a0dad, "purple", register=True, index=True, variation_map={ - 0x9f00c5: "munsell", - 0x4f284b: "murasaki", - 0xa020f0: "x11" }) - ColorRGB(0x69359c, "purple-heart", register=True, index=True) - ColorRGB(0x512c31, "purple-kite", register=True, index=True) - ColorRGB(0x9678b6, "purple-mountain-majesty", register=True, index=True) - ColorRGB(0x4e5180, "purple-navy", register=True, index=True) - ColorRGB(0xfe4eda, "purple-pizzazz", register=True, index=True) - ColorRGB(0x9c51b6, "purple-plum", register=True, index=True) - ColorRGB(0x50404d, "purple-taupe", register=True, index=True) - ColorRGB(0x9a4eae, "purpureus", register=True, index=True) - ColorRGB(0x51484f, "quartz", register=True, index=True) - ColorRGB(0x436b95, "queen-blue", register=True, index=True) - ColorRGB(0xe8ccd7, "queen-pink", register=True, index=True) - ColorRGB(0xa6a6a6, "quick-silver", register=True, index=True) - ColorRGB(0x8e3a59, "quinacridone-magenta", register=True, index=True) - ColorRGB(0x6a5445, "quincy", register=True, index=True) - ColorRGB(0x491e3c, "rabbit-ear-iris", register=True, index=True) - ColorRGB(0xff355e, "radical-red", register=True, index=True) - ColorRGB(0x242124, "raisin-black", register=True, index=True) - ColorRGB(0xfbab60, "rajah", register=True, index=True) - ColorRGB(0xc71232, "rambutan", register=True, index=True) - ColorRGB(0xa72127, "rambutan-red", register=True, index=True) - ColorRGB(0xe3b130, "rape-blossom-brown", register=True, index=True) - ColorRGB(0xa17917, "rapeseed-oil", register=True, index=True) - ColorRGB(0xe30b5d, "raspberry", register=True, index=True) - ColorRGB(0xe25098, "raspberry-pink", register=True, index=True) - ColorRGB(0xd68a59, "raw-sienna", register=True, index=True) - ColorRGB(0x826644, "raw-umber", register=True, index=True) - ColorRGB(0xff33cc, "razzle-dazzle-rose", register=True, index=True) - ColorRGB(0xe3256b, "razzmatazz", register=True, index=True) - ColorRGB(0x8d4e85, "razzmic-berry", register=True, index=True) - ColorRGB(0x663399, "rebecca-purple", register=True, index=True) - ColorRGB(0xee204d, "red", register=True, index=True, variation_map={ - 0xf2003c: "munsell", - 0xc40233: "ncs", - 0xfe2712: "ryb", - 0x800000: "xterm" }) - ColorRGB(0x672422, "red-bean", register=True, index=True) - ColorRGB(0x9d2b22, "red-birch", register=True, index=True) - ColorRGB(0xfb8136, "red-bronze", register=True, index=True) - ColorRGB(0xa13d2d, "red-brown", register=True, index=True, variation_map={ - 0x8b352d: "lit-chestnut-plum" }) - ColorRGB(0xb62020, "red-cola", register=True, index=True) - ColorRGB(0x860111, "red-devil", register=True, index=True) - ColorRGB(0xf07f5e, "red-incense", register=True, index=True) - ColorRGB(0x913228, "red-kite", register=True, index=True) - ColorRGB(0x9f5233, "red-ochre", register=True, index=True) - ColorRGB(0xff4500, "red-orange", register=True, index=True, variation_map={ - 0xdc3023: "lit-orangutan" }) - ColorRGB(0xdb5a6b, "red-plum", register=True, index=True) - ColorRGB(0xe40078, "red-purple", register=True, index=True) - ColorRGB(0xfd3a4a, "red-salsa", register=True, index=True) - ColorRGB(0x922b3e, "red-violet", register=True, index=True, variation_map={ - 0xc0448f: "crayola" }) - ColorRGB(0xbb7796, "red-wisteria", register=True, index=True) - ColorRGB(0xa45a52, "redwood", register=True, index=True) - ColorRGB(0x522d80, "regalia", register=True, index=True) - ColorRGB(0x002387, "resolution-blue", register=True, index=True) - ColorRGB(0x777696, "rhythm", register=True, index=True) - ColorRGB(0x004040, "rich-black", register=True, index=True, variation_map={ - 0x010b13: "fogra29", - 0x010203: "fogra39" }) - ColorRGB(0xf1a7fe, "rich-brilliant-lavender", register=True, index=True) - ColorRGB(0x0892d0, "rich-electric-blue", register=True, index=True) - ColorRGB(0xf57f4f, "rich-gardenia", register=True, index=True) - ColorRGB(0xa76bcf, "rich-lavender", register=True, index=True) - ColorRGB(0xb666d2, "rich-lilac", register=True, index=True) - ColorRGB(0x444c38, "rifle-green", register=True, index=True) - ColorRGB(0x534a32, "rikan-brown", register=True, index=True) - ColorRGB(0xff7952, "rinsed-out-red", register=True, index=True) - ColorRGB(0xffc324, "ripe-mango", register=True, index=True) - ColorRGB(0x00cccc, "robin-egg-blue", register=True, index=True) - ColorRGB(0x8a7f80, "rocket-metallic", register=True, index=True) - ColorRGB(0x838996, "roman-silver", register=True, index=True) - ColorRGB(0x290e05, "root-beer", register=True, index=True) - ColorRGB(0xf9429e, "rose-bonbon", register=True, index=True) - ColorRGB(0x9e5e6f, "rose-dust", register=True, index=True) - ColorRGB(0x674846, "rose-ebony", register=True, index=True) - ColorRGB(0x960145, "rose-garnet", register=True, index=True) - ColorRGB(0xb76e79, "rose-gold", register=True, index=True) - ColorRGB(0xff66cc, "rose-pink", register=True, index=True) - ColorRGB(0xbd559c, "rose-quartz-pink", register=True, index=True) - ColorRGB(0xc21e56, "rose-red", register=True, index=True) - ColorRGB(0x905d5d, "rose-taupe", register=True, index=True) - ColorRGB(0xab4e52, "rose-vale", register=True, index=True) - ColorRGB(0x65000b, "rosewood", register=True, index=True) - ColorRGB(0xd40000, "rosso-corsa", register=True, index=True) - ColorRGB(0xbc8f8f, "rosy-brown", register=True, index=True) - ColorRGB(0x0038a8, "royal-azure", register=True, index=True) - ColorRGB(0x002366, "royal-blue", register=True, index=True, variation_map={ - 0x4169e1: "light" }) - ColorRGB(0x523b35, "royal-brown", register=True, index=True) - ColorRGB(0xca2c92, "royal-fuchsia", register=True, index=True) - ColorRGB(0x136207, "royal-green", register=True, index=True) - ColorRGB(0xf99245, "royal-orange", register=True, index=True) - ColorRGB(0xe73895, "royal-pink", register=True, index=True) - ColorRGB(0x7851a9, "royal-purple", register=True, index=True) - ColorRGB(0xd00060, "royal-red", register=True, index=True, variation_map={ - 0x9b1c31: "2" }) - ColorRGB(0xce4676, "ruber", register=True, index=True) - ColorRGB(0xd10056, "rubine-red", register=True, index=True) - ColorRGB(0xe0115f, "ruby", register=True, index=True) - ColorRGB(0x9b111e, "ruby-red", register=True, index=True) - ColorRGB(0xff0028, "ruddy", register=True, index=True) - ColorRGB(0xbb6528, "ruddy-brown", register=True, index=True) - ColorRGB(0xe18e96, "ruddy-pink", register=True, index=True) - ColorRGB(0xa81c07, "rufous", register=True, index=True) - ColorRGB(0x716675, "rum", register=True, index=True) - ColorRGB(0x80461b, "russet", register=True, index=True) - ColorRGB(0x679267, "russian-green", register=True, index=True) - ColorRGB(0x32174d, "russian-violet", register=True, index=True) - ColorRGB(0xb7410e, "rust", register=True, index=True) - ColorRGB(0x6a7f7a, "rusted-light-blue", register=True, index=True) - ColorRGB(0x898a74, "rusty-celadon", register=True, index=True) - ColorRGB(0xda2c43, "rusty-red", register=True, index=True) - ColorRGB(0x455859, "rusty-storage", register=True, index=True) - ColorRGB(0x3a403b, "rusty-storeroom", register=True, index=True) - ColorRGB(0x043927, "sacramento-state-green", register=True, index=True) - ColorRGB(0x8b4513, "saddle-brown", register=True, index=True) - ColorRGB(0xff7800, "safety-orange", register=True, index=True, variation_map={ - 0xff6700: "blaze-orange" }) - ColorRGB(0xeed202, "safety-yellow", register=True, index=True) - ColorRGB(0x5a4f74, "safflower", register=True, index=True) - ColorRGB(0xf4c430, "saffron", register=True, index=True) - ColorRGB(0xbcb88a, "sage", register=True, index=True) - ColorRGB(0xfa8072, "salmon", register=True, index=True) - ColorRGB(0xff91a4, "salmon-pink", register=True, index=True) - ColorRGB(0xe7968b, "salmon-rose", register=True, index=True) - ColorRGB(0x12279e, "samsung-blue", register=True, index=True) - ColorRGB(0xecd540, "sandstorm", register=True, index=True) - ColorRGB(0xf4a460, "sandy-brown", register=True, index=True) - ColorRGB(0xfdd9b5, "sandy-tan", register=True, index=True) - ColorRGB(0x92000a, "sangria", register=True, index=True) - ColorRGB(0x507d2a, "sap-green", register=True, index=True) - ColorRGB(0x7e2639, "sappanwood", register=True, index=True) - ColorRGB(0xa24f46, "sappanwood-incense", register=True, index=True) - ColorRGB(0x0f52ba, "sapphire", register=True, index=True) - ColorRGB(0xff4681, "sasquatch-socks", register=True, index=True) - ColorRGB(0xcba135, "satin-sheen-gold", register=True, index=True) - ColorRGB(0xec956c, "sawtooth-oak", register=True, index=True) - ColorRGB(0xff2400, "scarlet", register=True, index=True, variation_map={ - 0xcf3a24: "blood" }) - ColorRGB(0xffd800, "school-bus-yellow", register=True, index=True) - ColorRGB(0x351f19, "scorched-brown", register=True, index=True) - ColorRGB(0x66ff66, "screamin-green", register=True, index=True) - ColorRGB(0x006994, "sea-blue", register=True, index=True) - ColorRGB(0x9fe2bf, "sea-foam-green", register=True, index=True) - ColorRGB(0x2e8b57, "sea-green", register=True, index=True, variation_map={ - 0x00ffcd: "crayola" }) - ColorRGB(0x4bc7cf, "sea-serpent", register=True, index=True) - ColorRGB(0x59260b, "seal-brown", register=True, index=True) - ColorRGB(0xfff5ee, "seashell", register=True, index=True) - ColorRGB(0xffba00, "selective-yellow", register=True, index=True) - ColorRGB(0x826b58, "sen-no-rikyus-tea", register=True, index=True) - ColorRGB(0x704214, "sepia", register=True, index=True) - ColorRGB(0xb1b7af, "sequoia-beige", register=True, index=True) - ColorRGB(0x00a870, "sesame-street-green", register=True, index=True) - ColorRGB(0x8a795d, "shadow", register=True, index=True) - ColorRGB(0x778ba5, "shadow-blue", register=True, index=True) - ColorRGB(0xffcff1, "shampoo", register=True, index=True) - ColorRGB(0x009e60, "shamrock-green", register=True, index=True) - ColorRGB(0xffe670, "shandy", register=True, index=True) - ColorRGB(0x8fd400, "sheen-green", register=True, index=True) - ColorRGB(0xd98695, "shimmering-blush", register=True, index=True) - ColorRGB(0x5fa778, "shiny-shamrock", register=True, index=True) - ColorRGB(0xfc0fc0, "shocking-pink", register=True, index=True, variation_map={ - 0xff6fff: "crayola" }) - ColorRGB(0x354e4b, "silk-crepe-brown", register=True, index=True) - ColorRGB(0xaaa9ad, "silver", register=True, index=True) - ColorRGB(0xacacac, "silver-chalice", register=True, index=True) - ColorRGB(0xafb1ae, "silver-foil", register=True, index=True) - ColorRGB(0x97867c, "silver-gray", register=True, index=True) - ColorRGB(0x5d89ba, "silver-lake-blue", register=True, index=True) - ColorRGB(0xc4aead, "silver-pink", register=True, index=True) - ColorRGB(0xbfc1c2, "silver-sand", register=True, index=True) - ColorRGB(0x4c3d30, "simmered-seaweed", register=True, index=True) - ColorRGB(0xcb410b, "sinopia", register=True, index=True) - ColorRGB(0x7a942e, "siskin-sprout-yellow", register=True, index=True) - ColorRGB(0xff3855, "sizzling-red", register=True, index=True) - ColorRGB(0xffdb00, "sizzling-sunrise", register=True, index=True) - ColorRGB(0x007474, "skobeloff", register=True, index=True) - ColorRGB(0x87ceeb, "sky-blue", register=True, index=True, variation_map={ - 0x76d7ea: "crayola", - 0x4d8fac: "sora-iro" }) - ColorRGB(0xcf71af, "sky-magenta", register=True, index=True) - ColorRGB(0x6a5acd, "slate-blue", register=True, index=True) - ColorRGB(0x708090, "slate-gray", register=True, index=True) - ColorRGB(0x299617, "slimy-green", register=True, index=True) - ColorRGB(0xff6d3a, "smashed-pumpkin", register=True, index=True) - ColorRGB(0xc84186, "smitten", register=True, index=True) - ColorRGB(0x738276, "smoke", register=True, index=True) - ColorRGB(0x832a0d, "smokey-topaz", register=True, index=True) - ColorRGB(0x100c08, "smoky-black", register=True, index=True) - ColorRGB(0x933d41, "smoky-topaz", register=True, index=True) - ColorRGB(0xfffafa, "snow", register=True, index=True) - ColorRGB(0xcec8ef, "soap", register=True, index=True) - ColorRGB(0x545a2c, "soldier-green", register=True, index=True) - ColorRGB(0x893843, "solid-pink", register=True, index=True) - ColorRGB(0x757575, "sonic-silver", register=True, index=True) - ColorRGB(0x4d4b3a, "sooty-willow-bamboo", register=True, index=True) - ColorRGB(0x1d2951, "space-cadet", register=True, index=True) - ColorRGB(0x807532, "spanish-bistre", register=True, index=True) - ColorRGB(0x0070b8, "spanish-blue", register=True, index=True) - ColorRGB(0xd10047, "spanish-carmine", register=True, index=True) - ColorRGB(0xe51a4c, "spanish-crimson", register=True, index=True) - ColorRGB(0x989898, "spanish-gray", register=True, index=True) - ColorRGB(0x009150, "spanish-green", register=True, index=True) - ColorRGB(0xe86100, "spanish-orange", register=True, index=True) - ColorRGB(0xf7bfbe, "spanish-pink", register=True, index=True) - ColorRGB(0x66033c, "spanish-purple", register=True, index=True) - ColorRGB(0xe60026, "spanish-red", register=True, index=True) - ColorRGB(0x4c2882, "spanish-violet", register=True, index=True) - ColorRGB(0x007f5c, "spanish-viridian", register=True, index=True) - ColorRGB(0xf6b511, "spanish-yellow", register=True, index=True) - ColorRGB(0x8c4736, "sparrow-brown", register=True, index=True) - ColorRGB(0x9e1316, "spartan-crimson", register=True, index=True) - ColorRGB(0x8b5f4d, "spicy-mix", register=True, index=True) - ColorRGB(0xb35c44, "spicy-red-brown", register=True, index=True) - ColorRGB(0x0fc0fc, "spiro-disco-ball", register=True, index=True) - ColorRGB(0xfdfe03, "sponge", register=True, index=True) - ColorRGB(0xa7fc00, "spring-bud", register=True, index=True) - ColorRGB(0x87ff2a, "spring-frost", register=True, index=True) - ColorRGB(0xec2131, "sprint-red", register=True, index=True) - ColorRGB(0xffdd05, "sprint-yellow", register=True, index=True) - ColorRGB(0x23297a, "st-patricks-blue", register=True, index=True) - ColorRGB(0x78779b, "stained-red", register=True, index=True) - ColorRGB(0x007bb8, "star-command-blue", register=True, index=True) - ColorRGB(0xd3b17d, "steamed-chestnut", register=True, index=True) - ColorRGB(0x4682b4, "steel-blue", register=True, index=True) - ColorRGB(0xcc33cc, "steel-pink", register=True, index=True) - ColorRGB(0x5f8a8b, "steel-teal", register=True, index=True) - ColorRGB(0xa09484, "stone-terrace", register=True, index=True) - ColorRGB(0xcf142b, "stop-red", register=True, index=True) - ColorRGB(0x3d4035, "storeroom-brown", register=True, index=True) - ColorRGB(0x4f666a, "stormcloud", register=True, index=True) - ColorRGB(0xe4d96f, "straw", register=True, index=True) - ColorRGB(0xfc5a8d, "strawberry", register=True, index=True) - ColorRGB(0xd9463e, "strawberry-daiquiri", register=True, index=True) - ColorRGB(0x8b171a, "strawberry-jam", register=True, index=True) - ColorRGB(0xc83f49, "strawberry-red", register=True, index=True) - ColorRGB(0xe9399e, "strong-boy-pink", register=True, index=True) - ColorRGB(0xffa26b, "stylish-persimmon", register=True, index=True) - ColorRGB(0x914e75, "sugar-plum", register=True, index=True) - ColorRGB(0xe08a1e, "sumac-dyed", register=True, index=True, variation_map={ - 0x592b1f: "korozen" }) - ColorRGB(0xff404c, "sunburnt-cyclops", register=True, index=True) - ColorRGB(0xffcc33, "sunglow", register=True, index=True) - ColorRGB(0xf2f27a, "sunny", register=True, index=True) - ColorRGB(0xe3ab57, "sunray", register=True, index=True) - ColorRGB(0xc27863, "sunrise-coral", register=True, index=True) - ColorRGB(0xfd5e53, "sunset-orange", register=True, index=True) - ColorRGB(0xffc922, "sunset-yellow", register=True, index=True) - ColorRGB(0xcf6ba9, "super-pink", register=True, index=True) - ColorRGB(0xf8b889, "superuser", register=True, index=True) - ColorRGB(0xa83731, "sweet-brown", register=True, index=True) - ColorRGB(0xf29eab, "sweet-sixteen", register=True, index=True) - ColorRGB(0xd2b48c, "tan", register=True, index=True, variation_map={ - 0xd99a6c: "crayola" }) - ColorRGB(0xf94d00, "tangelo", register=True, index=True) - ColorRGB(0xf28500, "tangerine", register=True, index=True) - ColorRGB(0xffcc00, "tangerine-yellow", register=True, index=True) - ColorRGB(0xff4200, "taobao-orange", register=True, index=True) - ColorRGB(0x003b6f, "tardis-blue", register=True, index=True) - ColorRGB(0xfb4d46, "tart-orange", register=True, index=True) - ColorRGB(0x976e9a, "tatarian-aster", register=True, index=True) - ColorRGB(0x8b8589, "taupe-gray", register=True, index=True) - ColorRGB(0xd0f0c0, "tea-green", register=True, index=True) - ColorRGB(0x008080, "teal", register=True, index=True) - ColorRGB(0x367588, "teal-blue", register=True, index=True) - ColorRGB(0x99e6b3, "teal-deer", register=True, index=True) - ColorRGB(0x00827f, "teal-green", register=True, index=True) - ColorRGB(0xcf3476, "telemagenta", register=True, index=True) - ColorRGB(0x3c2126, "temptress", register=True, index=True) - ColorRGB(0xcd5700, "tenne", register=True, index=True) - ColorRGB(0xe2725b, "terra-cotta", register=True, index=True) - ColorRGB(0x785e49, "the-color-of-an-undried-wall", register=True, index=True) - ColorRGB(0xa87ca0, "thin", register=True, index=True) - ColorRGB(0xd8bfd8, "thistle", register=True, index=True, variation_map={ - 0xebb0d7: "crayola" }) - ColorRGB(0x317589, "thousand-herb", register=True, index=True) - ColorRGB(0x3b3429, "thousand-year-old-brown", register=True, index=True) - ColorRGB(0x374231, "thousand-year-old-green", register=True, index=True) - ColorRGB(0xf7665a, "thrice-dyed-crimson", register=True, index=True) - ColorRGB(0xfc89ac, "tickle-me-pink", register=True, index=True) - ColorRGB(0x0abab5, "tiffany-blue", register=True, index=True) - ColorRGB(0xe08d3c, "tigers-eye", register=True, index=True) - ColorRGB(0xdbd7d2, "timberwolf", register=True, index=True) - ColorRGB(0x878681, "titanium", register=True, index=True) - ColorRGB(0xeee600, "titanium-yellow", register=True, index=True) - ColorRGB(0xff6347, "tomato", register=True, index=True) - ColorRGB(0xb21807, "tomato-sauce", register=True, index=True) - ColorRGB(0x746cc0, "toolbox", register=True, index=True) - ColorRGB(0xffc87c, "topaz", register=True, index=True) - ColorRGB(0xfd0e35, "tractor-red", register=True, index=True) - ColorRGB(0xa4345d, "tree-peony", register=True, index=True) - ColorRGB(0x808080, "trolley-gray", register=True, index=True) - ColorRGB(0x00755e, "tropical-rain-forest", register=True, index=True) - ColorRGB(0xcda4de, "tropical-violet", register=True, index=True) - ColorRGB(0x0073cf, "true-blue", register=True, index=True, variation_map={ - 0x2d68c4: "2" }) - ColorRGB(0x8f1d21, "true-red", register=True, index=True) - ColorRGB(0x3e8ede, "tufts-blue", register=True, index=True) - ColorRGB(0xff878d, "tulip", register=True, index=True) - ColorRGB(0xdeaa88, "tumbleweed", register=True, index=True) - ColorRGB(0xb57281, "turkish-rose", register=True, index=True) - ColorRGB(0xe69b3a, "turmeric", register=True, index=True) - ColorRGB(0x40e0d0, "turquoise", register=True, index=True) - ColorRGB(0x00ffef, "turquoise-blue", register=True, index=True) - ColorRGB(0xa0d6b4, "turquoise-green", register=True, index=True) - ColorRGB(0x00c5cd, "turquoise-surf", register=True, index=True) - ColorRGB(0x7c4848, "tuscan-red", register=True, index=True) - ColorRGB(0xc09999, "tuscany", register=True, index=True) - ColorRGB(0x8a496b, "twilight-lavender", register=True, index=True) - ColorRGB(0x26a7de, "twitter-blue", register=True, index=True) - ColorRGB(0x0033aa, "ua-blue", register=True, index=True) - ColorRGB(0xd9004c, "ua-red", register=True, index=True) - ColorRGB(0x8878c3, "ube", register=True, index=True) - ColorRGB(0x536895, "ucla-blue", register=True, index=True) - ColorRGB(0xffb300, "ucla-gold", register=True, index=True) - ColorRGB(0xba0001, "ue-red", register=True, index=True) - ColorRGB(0x3cd070, "ufo-green", register=True, index=True) - ColorRGB(0xfc6c85, "ultra-red", register=True, index=True) - ColorRGB(0x5d8cae, "ultramarine", register=True, index=True) - ColorRGB(0x4166f5, "ultramarine-blue", register=True, index=True) - ColorRGB(0x635147, "umber", register=True, index=True) - ColorRGB(0xffddca, "unbleached-silk", register=True, index=True) - ColorRGB(0xbcb58c, "underside-of-willow-leaves", register=True, index=True) - ColorRGB(0x5b92e5, "united-nations-blue", register=True, index=True) - ColorRGB(0xb78727, "university-of-california-gold", register=True, index=True) - ColorRGB(0xf77f00, "university-of-tennessee-orange", register=True, index=True) - ColorRGB(0x7b1113, "up-maroon", register=True, index=True) - ColorRGB(0xae2029, "upsdell-red", register=True, index=True) - ColorRGB(0xe1ad21, "urobilin", register=True, index=True) - ColorRGB(0x004f98, "usafa-blue", register=True, index=True) - ColorRGB(0xd3003f, "utah-crimson", register=True, index=True) - ColorRGB(0x080808, "vampire-black", register=True, index=True) - ColorRGB(0x664228, "van-dyke-brown", register=True, index=True) - ColorRGB(0xf38fa9, "vanilla-ice", register=True, index=True) - ColorRGB(0xc5b358, "vegas-gold", register=True, index=True) - ColorRGB(0x224634, "velvet", register=True, index=True) - ColorRGB(0xc80815, "venetian-red", register=True, index=True) - ColorRGB(0x43b3ae, "verdigris", register=True, index=True) - ColorRGB(0xcd040b, "verizon-red", register=True, index=True, variation_map={ - 0xec1c24: "2000-2015" }) - ColorRGB(0xd9381e, "vermilion", register=True, index=True) - ColorRGB(0x18880d, "verse-green", register=True, index=True) - ColorRGB(0x74bbfb, "very-light-azure", register=True, index=True) - ColorRGB(0x6666ff, "very-light-blue", register=True, index=True) - ColorRGB(0x64e986, "very-light-malachite-green", register=True, index=True) - ColorRGB(0xffb077, "very-light-tangelo", register=True, index=True) - ColorRGB(0xffdfbf, "very-pale-orange", register=True, index=True) - ColorRGB(0xffffbf, "very-pale-yellow", register=True, index=True) - ColorRGB(0xf4e9ce, "victorian-white", register=True, index=True) - ColorRGB(0x6d2b50, "vine-grape", register=True, index=True) - ColorRGB(0x38a32a, "vine-green", register=True, index=True) - ColorRGB(0x7f00ff, "violet", register=True, index=True, variation_map={ - 0x963d7f: "crayola", - 0x8601af: "ryb" }) - ColorRGB(0x324ab2, "violet-blue", register=True, index=True, variation_map={ - 0x766ec8: "crayola" }) - ColorRGB(0xf75394, "violet-red", register=True, index=True, variation_map={ - 0x891446: "2" }) - ColorRGB(0x8366f4, "violets-are-blue", register=True, index=True) - ColorRGB(0x674403, "violin-brown", register=True, index=True) - ColorRGB(0x009698, "viridian-green", register=True, index=True) - ColorRGB(0x7c9ed9, "vista-blue", register=True, index=True) - ColorRGB(0xef3939, "vivaldi-red", register=True, index=True) - ColorRGB(0x922724, "vivid-auburn", register=True, index=True) - ColorRGB(0x9f1d35, "vivid-burgundy", register=True, index=True) - ColorRGB(0xda1d81, "vivid-cerise", register=True, index=True) - ColorRGB(0x00aaee, "vivid-cerulean", register=True, index=True) - ColorRGB(0xcc0033, "vivid-crimson", register=True, index=True) - ColorRGB(0xff9900, "vivid-gamboge", register=True, index=True) - ColorRGB(0xa6d608, "vivid-lime-green", register=True, index=True) - ColorRGB(0x00cc33, "vivid-malachite", register=True, index=True) - ColorRGB(0xb80ce3, "vivid-mulberry", register=True, index=True) - ColorRGB(0xff5f00, "vivid-orange", register=True, index=True) - ColorRGB(0xffa000, "vivid-orange-peel", register=True, index=True) - ColorRGB(0xcc00ff, "vivid-orchid", register=True, index=True) - ColorRGB(0xff006c, "vivid-raspberry", register=True, index=True) - ColorRGB(0xf70d1a, "vivid-red", register=True, index=True) - ColorRGB(0xdf6124, "vivid-red-tangelo", register=True, index=True) - ColorRGB(0x00ccff, "vivid-sky-blue", register=True, index=True) - ColorRGB(0xf07427, "vivid-tangelo", register=True, index=True) - ColorRGB(0xffa089, "vivid-tangerine", register=True, index=True) - ColorRGB(0xe56024, "vivid-vermilion", register=True, index=True) - ColorRGB(0x9f00ff, "vivid-violet", register=True, index=True) - ColorRGB(0xffe302, "vivid-yellow", register=True, index=True) - ColorRGB(0xbfc0ee, "vodka", register=True, index=True) - ColorRGB(0xceff00, "volt", register=True, index=True) - ColorRGB(0x34b233, "wageningen-green", register=True, index=True) - ColorRGB(0x9f7462, "walnut-dyed", register=True, index=True) - ColorRGB(0x004242, "warm-black", register=True, index=True) - ColorRGB(0xffb3a7, "washed-out-crimson", register=True, index=True) - ColorRGB(0xec8254, "washed-out-persimmon", register=True, index=True) - ColorRGB(0xd4f1f9, "water", register=True, index=True) - ColorRGB(0xb56c60, "water-persimmon", register=True, index=True) - ColorRGB(0xeeff1b, "watermelon-yellow", register=True, index=True) - ColorRGB(0xa4f4f9, "waterspout", register=True, index=True) - ColorRGB(0x593a27, "weathered-bamboo", register=True, index=True) - ColorRGB(0x1f8eed, "weebly-blue", register=True, index=True) - ColorRGB(0xff9a00, "weebly-orange", register=True, index=True) - ColorRGB(0x7c98ab, "weldon-blue", register=True, index=True) - ColorRGB(0x645452, "wenge", register=True, index=True) - ColorRGB(0xf5deb3, "wheat", register=True, index=True) - ColorRGB(0xc5c8c6, "white", register=True, index=True) - ColorRGB(0xede6d6, "white-chocolate", register=True, index=True) - ColorRGB(0xe6e0d4, "white-coffee", register=True, index=True) - ColorRGB(0xb9a193, "white-mouse", register=True, index=True) - ColorRGB(0xce9f6f, "white-oak", register=True, index=True) - ColorRGB(0xc48e69, "white-tea", register=True, index=True) - ColorRGB(0xa5ba93, "whitish-green", register=True, index=True) - ColorRGB(0xa2add0, "wild-blue-yonder", register=True, index=True) - ColorRGB(0xd470a2, "wild-orchid", register=True, index=True) - ColorRGB(0xff43a4, "wild-strawberry", register=True, index=True) - ColorRGB(0x8c9e5e, "willow-dye", register=True, index=True) - ColorRGB(0x817b69, "willow-gray", register=True, index=True) - ColorRGB(0x9c8a4d, "willow-tea", register=True, index=True) - ColorRGB(0xfd5800, "willpower-orange", register=True, index=True) - ColorRGB(0xab4c3d, "wilted-brown", register=True, index=True) - ColorRGB(0xa75502, "windsor-tan", register=True, index=True) - ColorRGB(0xb11226, "wine-red", register=True, index=True) - ColorRGB(0xff007c, "winter-sky", register=True, index=True) - ColorRGB(0xa0e6ff, "winter-wizard", register=True, index=True) - ColorRGB(0x56887d, "wintergreen-dream", register=True, index=True) - ColorRGB(0xc9a0dc, "wisteria", register=True, index=True, variation_map={ - 0x89729e: "fuji-iro" }) - ColorRGB(0x4d3b3c, "wisteria-and-burnt-bamboo", register=True, index=True) - ColorRGB(0x875f9a, "wisteria-purple", register=True, index=True) - ColorRGB(0x738678, "xanadu", register=True, index=True) - ColorRGB(0x0e7a0d, "xbox-green", register=True, index=True) - ColorRGB(0xfd4900, "xiaomi-orange", register=True, index=True) - ColorRGB(0x0f4d92, "yale-blue", register=True, index=True) - ColorRGB(0x1c2841, "yankees-blue", register=True, index=True) - ColorRGB(0xfce883, "yellow", register=True, index=True, variation_map={ - 0xefcc00: "munsell", - 0xfedf00: "pantone", - 0xfefe33: "ryb", - 0x808000: "xterm" }) - ColorRGB(0x9acd32, "yellow-green", register=True, index=True, variation_map={ - 0x30b21a: "color-wheel", - 0xc5e384: "crayola" }) - ColorRGB(0xffae42, "yellow-orange", register=True, index=True, variation_map={ - 0xff9505: "color-wheel" }) - ColorRGB(0xfff000, "yellow-rose", register=True, index=True) - ColorRGB(0x896c39, "yellow-sea-pine-brown", register=True, index=True) - ColorRGB(0x2e5090, "yin-mn-blue", register=True, index=True) - ColorRGB(0x6b9362, "young-bamboo", register=True, index=True) - ColorRGB(0xb2071d, "youtube-red", register=True, index=True) - ColorRGB(0x0014a8, "zaffre", register=True, index=True) - ColorRGB(0xebc2af, "zinnwaldite", register=True, index=True) - ColorRGB(0x2c1608, "zinnwaldite-brown", register=True, index=True) - ColorRGB(0x39a78e, "zomp", register=True, index=True) - # fmt: on diff --git a/pytermor/cval.py.tpl b/pytermor/cval.py.tpl deleted file mode 100644 index 3136ec5..0000000 --- a/pytermor/cval.py.tpl +++ /dev/null @@ -1,20 +0,0 @@ -# ----------------------------------------------------------------------------- -# pytermor [ANSI formatted terminal output toolset] -# (c) 2022. A. Shavykin <0.delameter@gmail.com> -# ----------------------------------------------------------------------------- -# AUTOGENERATED MODULE -# %t -""" -Color preset list. -""" -from .color import Color16, Color256, ColorRGB -from .ansi import IntCode - - -class CVAL: - """ - - """ - # fmt: off -%s - # fmt: on diff --git a/pytermor/render.py b/pytermor/render.py new file mode 100644 index 0000000..d514dd0 --- /dev/null +++ b/pytermor/render.py @@ -0,0 +1,777 @@ +# ----------------------------------------------------------------------------- +# pytermor [ANSI formatted terminal output toolset] +# (c) 2022. A. Shavykin <0.delameter@gmail.com> +# ----------------------------------------------------------------------------- +""" +Module with output formatters. By default :class:`SgrRenderer` is used. It +also contains compatibility settings, see `SgrRenderer.set_up()`. + +Working with non-default renderer can be achieved in two ways: + +a. Method `RendererManager.set_up()` sets the default renderer globally. After that + calling ``str()`` will automatically invoke said renderer and all + formatting will be applied. +b. Alternatively, you can use renderer's own class method `IRenderer.render()` + directly and avoid messing up with the manager: ``HtmlRenderer.render()`` + +.. rubric:: TL;DR + +To unconditionally print formatted message to output terminal, do something like this: + +>>> from pytermor import SgrRenderer, Styles, Text +>>> SgrRenderer.set_up(force_styles=True) +>>> print(Text('Warning: AAAA', Styles.WARNING)) +\x1b[33mWarning: AAAA\x1b[39m + + +.. testsetup:: * + + from pytermor.color import Colors + from pytermor.render import * + + SgrRenderer.set_up(force_styles=True) + +----- + +.. todo :: + + Scheme can be simplified, too many unnecessary abstractions for now. + + Renderable + (implemented by Text) should include algorithms for creating intermediate + styles for text pieces that lie in beetween first opening sequence (or tag) + and second, for example -- this happens when one Text instance is included + into another. + Style's + responsibility is to preserve the state of text piece and thats it. + Renderer + should transform style into corresponding output format and thats it. + + API 2: + Text(string, style, leave_open = True) # no style means all open styles will + be closed at the end + Text().append(string, style, leave_open = True) + Text().prepend(string, style, leave_open = False) + Text().raw + Text().apply(style) + Text().render(with=IRenderer()) + Text() + Text() = Text().append(Text().raw, Text().style) + Text() + str = Text().append(str) + str + Text() = Text().prepend(str) + + Style(style, fg, bg...) + # no Style().render()! + IRenderer().setup() + IRenderer().render(text) + SgrRenderer().is_sgr_usage_allowed() + + renderers should have instance methods only! +""" +from __future__ import annotations + +import sys +from abc import abstractmethod, ABCMeta +from dataclasses import dataclass, field +from functools import reduce +from typing import List, Sized, Any +from typing import Type, Dict, Set + +from pytermor.common import LogicError +from .ansi import SequenceSGR, Span, NOOP_SEQ, Seqs, IntCodes +from .color import Color, ColorRGB, ColorIndexed16, ColorIndexed256, NOOP_COLOR, Colors +from .common import Registry +from .util.string_filter import ReplaceSGR + + +class Renderable(Sized, metaclass=ABCMeta): + """ + Renderable abstract class. Can be inherited if the default style + overlaps resolution mechanism implemented in `Text` is not good enough + and you want to implement your own. + """ + def render(self) -> str: + return self._render_using(RendererManager.get_default()) + + @abstractmethod + def _render_using(self, renderer: Type[IRenderer]) -> str: + raise NotImplemented + + def __str__(self) -> str: + return self.render() + + @abstractmethod + def __len__(self) -> int: + raise NotImplemented + + +class Text(Renderable): + """ + Text + """ + + def __init__(self, text: Any = None, style: Style|str = None): + self._runs = [self._TextRun(text, style)] + + def _render_using(self, renderer: Type[IRenderer]) -> str: + return ''.join(run._render_using(renderer) for run in self._runs) + + def raw(self) -> str: + return ''.join(run.raw() for run in self._runs) + + def append(self, text: str|Text): + if isinstance(text, str): + self._runs.append(self._TextRun(text)) + elif isinstance(text, Text): + self._runs += text._runs + else: + raise TypeError('Can add Text to another Text instance or str only') + + def prepend(self, text: str|Text): + if isinstance(text, str): + self._runs.insert(0, self._TextRun(text)) + elif isinstance(text, Text): + self._runs = text._runs + self._runs + else: + raise TypeError('Can add Text to another Text instance or str only') + + def __len__(self) -> int: + return sum(len(r) for r in self._runs) + + def __format__(self, *args, **kwargs) -> str: + runs_amount = len(self._runs) + if runs_amount == 0: + return ''.__format__(*args, **kwargs) + if runs_amount > 1: + raise RuntimeError( + f'Can only __format__ Texts consisting of 0 or 1 TextRuns, ' + f'got {runs_amount}. Consider applying the styles and creating' + f' the Text instance after value formatting.') + return self._runs[0].__format__(*args, **kwargs) + + def __add__(self, other: str|Text) -> Text: + self.append(other) + return self + + def __iadd__(self, other: str|Text) -> Text: + self.append(other) + return self + + def __radd__(self, other: str|Text) -> Text: + self.prepend(other) + return self + + class _TextRun(Renderable): + def __init__(self, string: Any = None, style: Style|str = None): + self._string: str = str(string) if string else '' + if isinstance(style, str): + style = Style(fg=style) + self._style: Style|None = style + + def _render_using(self, renderer: Type[IRenderer]) -> str: + if not self._style: + return self._string + return renderer.render(self._string, self._style) + + def raw(self) -> str: + return self._string + + def __len__(self) -> int: + return len(self._string) + + def __format__(self, *args, **kwargs) -> str: + self._string = self._string.__format__(*args, **kwargs) + return self.render() + + +@dataclass +class Style: + """Create a new ``Style()``. + + Key difference between ``Styles`` and ``Spans`` or ``SGRs`` is that + ``Styles`` describe colors in RGB format and therefore support output + rendering in several different formats (see :mod:`._render`). + + Both ``fg`` and ``bg`` can be specified as: + + 1. :class:`.Color` instance or library preset; + 2. key code -- name of any of aforementioned presets, case-insensitive; + 3. integer color value in hexademical RGB format. + 4. None -- the color will be unset. + + :param fg: Foreground (i.e., text) color. + :param bg: Background color. + :param inherit: Parent instance to copy unset properties from. + :param blink: Blinking effect; *supported by limited amount of Renderers*. + :param bold: Bold or increased intensity. + :param crosslined: Strikethrough. + :param dim: Faint, decreased intensity. + :param double_underlined: + Faint, decreased intensity. + :param inversed: Swap foreground and background colors. + :param italic: Italic. + :param overlined: Overline. + :param underlined: Underline. + :param class_name: Arbitary string used by some renderers, e.g. by ``HtmlRenderer``. + + >>> Style(fg='green', bold=True) + Style[fg=008000, no bg, bold] + >>> Style(bg=0x0000ff) + Style[no fg, bg=0000ff] + >>> Style(fg=Colors.DEEP_SKY_BLUE_1, bg=Colors.GREY_93) + Style[fg=00afff, bg=eeeeee] + """ + _fg: Color = field(default=None, init=False) + _bg: Color = field(default=None, init=False) + + def __init__(self, inherit: Style = None, fg: Color|int|str = None, + bg: Color|int|str = None, blink: bool = None, bold: bool = None, + crosslined: bool = None, dim: bool = None, + double_underlined: bool = None, inversed: bool = None, + italic: bool = None, overlined: bool = None, underlined: bool = None, + class_name: str = None): + if fg is not None: + self._fg = self._resolve_color(fg, True) + if bg is not None: + self._bg = self._resolve_color(bg, True) + + self.blink = blink + self.bold = bold + self.crosslined = crosslined + self.dim = dim + self.double_underlined = double_underlined + self.inversed = inversed + self.italic = italic + self.overlined = overlined + self.underlined = underlined + self.class_name = class_name + + if inherit is not None: + self._clone_from(inherit) + + if self._fg is None: + self._fg = NOOP_COLOR + if self._bg is None: + self._bg = NOOP_COLOR + + def text(self, text: Any) -> Text: + return Text(text, self) + + def render(self, text: Any) -> str: + return self.text(text).render() + + def autopick_fg(self) -> Style: + """ + Pick ``fg_color`` depending on ``bg_color``. Set ``fg_color`` to + either 4% gray (almost black) if background is bright, or to 80% gray + (bright gray) if it is dark. If background is None, do nothing. + + .. todo :: + + check if there is a better algorithm, + because current thinks text on #000080 should be black + + :return: self + """ + if self._bg is None or self._bg.hex_value is None: + return self + + h, s, v = Color.hex_value_to_hsv_channels(self._bg.hex_value) + if v >= .45: + self._fg = Colors.RGB_GREY_4 + else: + self._fg = Colors.RGB_GREY_80 + return self + + def flip(self) -> Style: + """ + Swap foreground color and background color. + :return: self + """ + self._fg, self._bg = self._bg, self._fg + return self + + # noinspection PyMethodMayBeStatic + def _resolve_color(self, arg: str|int|Color, nullable: bool) -> Color|None: + if isinstance(arg, Color): + return arg + + if isinstance(arg, int): + return ColorRGB(arg) + + if isinstance(arg, str): + resolved_color = Colors.resolve(arg) + if not isinstance(resolved_color, Color): + raise ValueError(f'Attribute is not valid Color: {resolved_color}') + return resolved_color + + return None if nullable else NOOP_COLOR + + def _clone_from(self, inherit: Style): + for attr in list(self.__dict__.keys()) + ['_fg', '_bg']: + inherit_val = getattr(inherit, attr) + if getattr(self, attr) is None and inherit_val is not None: + setattr(self, attr, inherit_val) + + def __repr__(self): + if self._fg is None or self._bg is None: + return self.__class__.__name__ + '[uninitialized]' + props_set = [self.fg.format_value('fg=', 'no fg'), + self.bg.format_value('bg=', 'no bg'), ] + for attr_name in dir(self): + if not attr_name.startswith('_'): + attr = getattr(self, attr_name) + if isinstance(attr, bool) and attr is True: + props_set.append(attr_name) + + return self.__class__.__name__ + '[{:s}]'.format(', '.join(props_set)) + + @property + def fg(self) -> Color: + return self._fg + + @property + def bg(self) -> Color: + return self._bg + + @fg.setter + def fg(self, val: str|int|Color): + self._fg: Color = self._resolve_color(val, nullable=False) + + @bg.setter + def bg(self, val: str|int|Color): + self._bg: Color = self._resolve_color(val, nullable=False) + + +NOOP_STYLE = Style() +""" +Special style which passes the text +furthrer without any modifications. +""" + + +class RendererManager: + _default: Type[IRenderer] = None + + @classmethod + def set_up(cls, default_renderer: Type[IRenderer]|None = None): + """ + Set up renderer preferences. Affects all renderer types. + + :param default_renderer: + Default renderer to use globally. Passing None will result in library + default setting restored (`SgrRenderer`). + + >>> RendererManager.set_up(DebugRenderer) + >>> Text('text', Style(fg='red')).render() + '|ǝ31|text|ǝ39|' + + >>> NoOpRenderer.render('text',Style(fg='red')) + 'text' + """ + cls._default = default_renderer or SgrRenderer + + @classmethod + def get_default(cls) -> Type[IRenderer]: + """ Get global default renderer type. """ + return cls._default + + +class IRenderer(metaclass=ABCMeta): + """ Renderer interface. """ + + @classmethod + @abstractmethod + def render(cls, text: Any, style: Style = NOOP_STYLE) -> str: + """ + Apply colors and attributes described in ``style`` argument to + ``text`` and return the result. Output format depends on renderer's + class (which defines the implementation). + """ + raise NotImplementedError + + +class SgrRenderer(IRenderer): + """ + Default renderer invoked by `Text._render()`. Transforms `Color` instances + defined in ``style`` into ANSI control sequence bytes and merges them with + input string. + + Respects compatibility preferences (see `RendererManager.set_up()`) and + maps RGB colors to closest *indexed* colors if terminal doesn't support + RGB output. In case terminal doesn't support even 256 colors, falls back + to 16-color pallete and picks closest counterparts again the same way. + + Type of output ``SequenceSGR`` depends on type of `Color` variables in + ``style`` argument. Keeping all that in mind, let's summarize: + + 1. `ColorRGB` can be rendered as True Color sequence, 256-color sequence + or 16-color sequence depending on compatibility settings. + 2. `ColorIndexed256` can be rendered as 256-color sequence or 16-color + sequence. + 3. `ColorIndexed16` can be rendered as 16-color sequence. + 4. Nothing of the above will happen and all Colors will be discarded + completely if output is not a terminal emulator or if the developer + explicitly set up the renderer to do so (**force_styles** = False). + + >>> SgrRenderer.render('text', Style(fg='red', bold=True)) + '\\x1b[1;31mtext\\x1b[22;39m' + """ + _force_styles: bool|None = False + _compatibility_256_colors: bool = False + _compatibility_16_colors: bool = False + + @classmethod + def set_up(cls, force_styles: bool|None = False, + compatibility_256_colors: bool = False, + compatibility_16_colors: bool = False): + """ + Set up renderer preferences. Affects all renderer types. + + .. todo :: + Rewrite this part. Default should be *256* OR *RGB* if COLORTERM is either + ``truecolor`` or ``24bit``. `setup()` overrides this, of course. + + :param force_styles: + + * If set to *None*, all renderers will pass input text through themselves + without any changes (i.e. no colors and attributes will be applied). + * If set to *True*, renderers will always apply the formatting regardless + of other internal rules and algorithms. + * If set to *False* [default], the final decision will be made + by every renderer independently, based on their own algorithms. + + :param compatibility_256_colors: + + Disable *RGB* (or True Color) output mode. *256-color* sequences will + be printed out instead of disabled ones. Useful when combined with + ``curses`` -- that way you can check the terminal capabilities from the + inside of that terminal and switch to different output mode at once. + + :param compatibility_16_colors: + + Disable *256-color* output mode and default *16-color* sequences instead. + If this setting is set to *True*, the value of ``compatibility_256_colors`` + will be ignored completely. + + """ + cls._force_styles = force_styles + cls._compatibility_256_colors = compatibility_256_colors + cls._compatibility_16_colors = compatibility_16_colors + + @classmethod + def render(cls, text: Any, style: Style = NOOP_STYLE): + opening_seq = cls._render_attributes(style, squash=True) + \ + cls._render_color(style.fg, False) + \ + cls._render_color(style.bg, True) + + # in case there are line breaks -- split text to lines and apply + # SGRs for each line separately. it increases the chances that style + # will be correctly displayed regardless of implementation details of + # user's pager, multiplexer, terminal emulator etc. + rendered_text = '' + for line in str(text).splitlines(keepends=True): + rendered_text += Span(opening_seq).wrap(line) + return rendered_text + + @classmethod + def _render_attributes(cls, style: Style, squash: bool) -> List[SequenceSGR]|SequenceSGR: + if not cls.is_sgr_usage_allowed(): + return NOOP_SEQ if squash else [NOOP_SEQ] + + result = [] + if style.blink: result += [Seqs.BLINK_SLOW] + if style.bold: result += [Seqs.BOLD] + if style.crosslined: result += [Seqs.CROSSLINED] + if style.dim: result += [Seqs.DIM] + if style.double_underlined: result += [Seqs.DOUBLE_UNDERLINED] + if style.inversed: result += [Seqs.INVERSED] + if style.italic: result += [Seqs.ITALIC] + if style.overlined: result += [Seqs.OVERLINED] + if style.underlined: result += [Seqs.UNDERLINED] + + if squash: + return reduce(lambda p, c: p + c, result, NOOP_SEQ) + return result + + @classmethod + def _render_color(cls, color: Color, bg: bool) -> SequenceSGR: + hex_value = color.hex_value + + if not cls.is_sgr_usage_allowed() or hex_value is None: + return NOOP_SEQ + + if isinstance(color, ColorRGB): + if cls._compatibility_16_colors: + return ColorIndexed16.find_closest(hex_value).to_sgr(bg=bg) + if cls._compatibility_256_colors: + return ColorIndexed256.find_closest(hex_value).to_sgr(bg=bg) + return color.to_sgr(bg=bg) + + elif isinstance(color, ColorIndexed256): + if cls._compatibility_16_colors: + return ColorIndexed16.find_closest(hex_value).to_sgr(bg=bg) + return color.to_sgr(bg=bg) + + elif isinstance(color, ColorIndexed16): + return color.to_sgr(bg=bg) + + raise NotImplementedError(f'Unknown Color inhertior {color!s}') + + @classmethod + def is_sgr_usage_allowed(cls) -> bool: + if cls._force_styles is True: + return True + if cls._force_styles is None: + return False + return sys.stdout.isatty() + + +class TmuxRenderer(SgrRenderer): + """ + tmux + """ + + SGR_TO_TMUX_MAP = { + NOOP_SEQ: '', + Seqs.RESET: 'default', + + Seqs.BOLD: 'bold', + Seqs.DIM: 'dim', + Seqs.ITALIC: 'italics', + Seqs.UNDERLINED: 'underscore', + Seqs.BLINK_SLOW: 'blink', + Seqs.BLINK_FAST: 'blink', + Seqs.BLINK_DEFAULT: 'blink', + Seqs.INVERSED: 'reverse', + Seqs.HIDDEN: 'hidden', + Seqs.CROSSLINED: 'strikethrough', + Seqs.DOUBLE_UNDERLINED: 'double-underscore', + Seqs.OVERLINED: 'overline', + + Seqs.BOLD_DIM_OFF: 'nobold nodim', + Seqs.ITALIC_OFF: 'noitalics', + Seqs.UNDERLINED_OFF: 'nounderscore', + Seqs.BLINK_OFF: 'noblink', + Seqs.INVERSED_OFF: 'noreverse', + Seqs.HIDDEN_OFF: 'nohidden', + Seqs.CROSSLINED_OFF: 'nostrikethrough', + Seqs.OVERLINED_OFF: 'nooverline', + + Seqs.BLACK: 'fg=black', + Seqs.RED: 'fg=red', + Seqs.GREEN: 'fg=green', + Seqs.YELLOW: 'fg=yellow', + Seqs.BLUE: 'fg=blue', + Seqs.MAGENTA: 'fg=magenta', + Seqs.CYAN: 'fg=cyan', + Seqs.WHITE: 'fg=white', + Seqs.COLOR_OFF: 'fg=default', + + Seqs.BG_BLACK: 'bg=black', + Seqs.BG_RED: 'bg=red', + Seqs.BG_GREEN: 'bg=green', + Seqs.BG_YELLOW: 'bg=yellow', + Seqs.BG_BLUE: 'bg=blue', + Seqs.BG_MAGENTA: 'bg=magenta', + Seqs.BG_CYAN: 'bg=cyan', + Seqs.BG_WHITE: 'bg=white', + Seqs.BG_COLOR_OFF: 'bg=default', + + Seqs.GRAY: 'fg=brightblack', + Seqs.HI_RED: 'fg=brightred', + Seqs.HI_GREEN: 'fg=brightgreen', + Seqs.HI_YELLOW: 'fg=brightyellow', + Seqs.HI_BLUE: 'fg=brightblue', + Seqs.HI_MAGENTA: 'fg=brightmagenta', + Seqs.HI_CYAN: 'fg=brightcyan', + Seqs.HI_WHITE: 'fg=brightwhite', + + Seqs.BG_GRAY: 'bg=brightblack', + Seqs.BG_HI_RED: 'bg=brightred', + Seqs.BG_HI_GREEN: 'bg=brightgreen', + Seqs.BG_HI_YELLOW: 'bg=brightyellow', + Seqs.BG_HI_BLUE: 'bg=brightblue', + Seqs.BG_HI_MAGENTA: 'bg=brightmagenta', + Seqs.BG_HI_CYAN: 'bg=brightcyan', + Seqs.BG_HI_WHITE: 'bg=brightwhite', + } + + @classmethod + def render(cls, text: Any, style: Style = NOOP_STYLE): + opening_sgrs = [ + *cls._render_attributes(style, False), + cls._render_color(style.fg, False), + cls._render_color(style.bg, True), + ] + opening_tmux_style = cls._sgr_to_tmux_style(*opening_sgrs) + closing_tmux_style = ''.join( + cls._sgr_to_tmux_style(Span(sgr).closing_seq) for sgr in opening_sgrs + ) + + rendered_text = '' + for line in str(text).splitlines(keepends=True): + rendered_text += opening_tmux_style + line + closing_tmux_style + return rendered_text + + @classmethod + def _sgr_to_tmux_style(cls, *sgrs: SequenceSGR) -> str: + result = '' + for sgr in sgrs: + if sgr.is_color_extended: + target = 'fg' + if sgr.params[0] == IntCodes.BG_COLOR_EXTENDED: + target = 'bg' + + if sgr.params[1] == IntCodes.EXTENDED_MODE_256: + color = 'color{}'.format(sgr.params[2]) + elif sgr.params[1] == IntCodes.EXTENDED_MODE_RGB: + color = '#{:06x}'.format( + ColorRGB.rgb_channels_to_hex_value(*sgr.params[2:]) + ) + else: + raise ValueError(f"Unknown SGR param #2 (idx 1): {sgr!r}") + + result += f'#[{target}={color}]' + continue + + tmux_style_decl = cls.SGR_TO_TMUX_MAP.get(sgr) + if tmux_style_decl is None: + raise LogicError(f'No tmux definiton is present for {sgr!r}') + if len(tmux_style_decl) > 0: + result += f'#[{tmux_style_decl}]' + return result + + +class NoOpRenderer(IRenderer): + """ + Special renderer type that does nothing with the input string and just + returns it as is. That's true only when it _is_ a str beforehand; + otherwise argument will be casted to str and then returned. + + >>> NoOpRenderer.render('text', Style(fg='red', bold=True)) + 'text' + """ + + @classmethod + def render(cls, text: Any, style: Style = NOOP_STYLE) -> str: + return str(text) + + +class HtmlRenderer(IRenderer): + """ + html + + >>> HtmlRenderer.render('text',Style(fg='red', bold=True)) + 'text' + """ + + DEFAULT_ATTRS = ['color', 'background-color', 'font-weight', 'font-style', + 'text-decoration', 'border', 'filter', ] + + @classmethod + def render(cls, text: Any, style: Style = NOOP_STYLE) -> str: + span_styles: Dict[str, Set[str]] = dict() + for attr in cls._get_default_attrs(): + span_styles[attr] = set() + + if style.fg.hex_value is not None: + span_styles['color'].add(style.fg.format_value("#")) + if style.bg.hex_value is not None: + span_styles['background-color'].add(style.bg.format_value("#")) + + if style.blink: # modern browsers doesn't support it without shit piled up + span_styles['border'].update(('1px', 'dotted')) + if style.bold: + span_styles['font-weight'].add('700') + if style.crosslined: + span_styles['text-decoration'].add('line-through') + if style.dim: + span_styles['filter'].update(('saturate(0.5)', 'brightness(0.75)')) + if style.double_underlined: + span_styles['text-decoration'].update(('underline', 'double')) + if style.inversed: + span_styles['color'], span_styles['background-color'] = \ + span_styles['background-color'], span_styles['color'] + if style.italic: + span_styles['font-style'].add('italic') + if style.overlined: + span_styles['text-decoration'].add('overline') + if style.underlined: + span_styles['text-decoration'].add('underline') + + span_class_str = '' if style.class_name is None else f' class="{style.class_name}"' + span_style_str = '; '.join(f"{k}: {' '.join(v)}" + for k, v in span_styles.items() + if len(v) > 0) + return f''+str(text)+'' # @TODO # attribues + + @classmethod + def _get_default_attrs(cls) -> List[str]: + return cls.DEFAULT_ATTRS + + +class DebugRenderer(SgrRenderer): + """ + DebugRenderer + + >>> DebugRenderer.render('text',Style(fg='red', bold=True)) + '|ǝ1;31|text|ǝ22;39|' + """ + + @classmethod + def render(cls, text: Any, style: Style = NOOP_STYLE) -> str: + return ReplaceSGR(r'|ǝ\3|').apply(super().render(str(text), style)) + + @classmethod + def is_sgr_usage_allowed(cls) -> bool: + return True + + +RendererManager.set_up() + + +class Styles(Registry[Style]): + """ + Some ready-to-use styles. Can be used as examples. + + This registry has unique keys in comparsion with other ones (`Seqs` / `Spans` / + `IntCodes`), + Therefore there is no risk of key/value duplication and all presets can be listed + in the initial place -- at API docs page directly. + """ + + WARNING = Style(fg=Colors.YELLOW) + WARNING_LABEL = Style(WARNING, bold=True) + WARNING_ACCENT = Style(fg=Colors.HI_YELLOW) + + ERROR = Style(fg=Colors.RED) + ERROR_LABEL = Style(ERROR, bold=True) + ERROR_ACCENT = Style(fg=Colors.HI_RED) + + CRITICAL = Style(bg=Colors.HI_RED, fg=Colors.HI_WHITE) + CRITICAL_LABEL = Style(CRITICAL, bold=True) + CRITICAL_ACCENT = Style(CRITICAL, bold=True, blink=True) + + +def distribute_padded(values: List, max_len: int, pad_before: bool = False, + pad_after: bool = False, ) -> str: + if pad_before: + values.insert(0, '') + if pad_after: + values.append('') + + values_amount = len(values) + gapes_amount = values_amount - 1 + values_len = sum(len(v) for v in values) + spaces_amount = max_len - values_len + if spaces_amount < gapes_amount: + raise ValueError(f'There is not enough space for all values with padding') + + result = '' + for value_idx, value in enumerate(values): + gape_len = spaces_amount // (gapes_amount or 1) # for last value + result += value + ' ' * gape_len + gapes_amount -= 1 + spaces_amount -= gape_len + + return result diff --git a/pytermor/renderer.py b/pytermor/renderer.py deleted file mode 100644 index afbed47..0000000 --- a/pytermor/renderer.py +++ /dev/null @@ -1,658 +0,0 @@ -# ----------------------------------------------------------------------------- -# pytermor [ANSI formatted terminal output toolset] -# (c) 2022-2023. A. Shavykin <0.delameter@gmail.com> -# ----------------------------------------------------------------------------- -""" -Output formatters. Default global renderer type is `SgrRenderer`. -""" -from __future__ import annotations - -import enum -import os -import sys -import typing as t -from abc import abstractmethod, ABCMeta -from functools import reduce -from hashlib import md5 - -from .ansi import SequenceSGR, NOOP_SEQ, SeqIndex, enclose -from .color import IColor, Color16, Color256, ColorRGB, NOOP_COLOR -from .common import logger, FT -from .style import Style, NOOP_STYLE, Styles, make_style -from .utilmisc import get_qname -from .utilstr import SgrStringReplacer - - -T = t.TypeVar("T", bound="IRenderer") - - -def _digest(fingerprint: str) -> int: - return int.from_bytes(md5(fingerprint.encode()).digest(), "big") - - -class RendererManager: - """ - Class for global rendering mode setup. - - Selecting the renderer can be accomplished in several ways: - - a. By using general-purpose functions `text.render()` and `text.echo()` -- - both have an argument ``renderer`` (preferrable; introduced in `pytermor 2.x`). - b. Method `RendererManager.set_default()` sets the default renderer globally. - After that calling `text.render()` will automatically invoke a said renderer - and apply the required formatting (that is, if ``renderer`` argument is - left empty). - c. Alternatively, you can use renderer's instance method - `render() ` directly and avoid messing up with the manager, - but that's not recommended and possibly will be deprecated in future versions). - - Generally speaking, if you need to invoke a custom renderer just once, it's - convenient to use the first method for this matter, and use the second one - in all the other cases. - - On the contrary, if there is a necessity to use more than one renderer - alternatingly, it's better to avoid using the global one at all, and just - instantiate and invoke both renderers independently. - - .. rubric :: TL;DR - - To unconditionally print formatted message to standard output, do something like - this: - - >>> from pytermor import render, RendererManager, Styles - >>> RendererManager.set_default_format_always() - >>> render('Warning: AAAA', Styles.WARNING) - '\x1b[33mWarning: AAAA\x1b[39m' - - """ - - _default: IRenderer = None - - @classmethod - def set_default(cls, renderer: IRenderer | t.Type[IRenderer] = None): - # noinspection PyUnresolvedReferences - """ - Select a global renderer. - - >>> RendererManager.set_default(SgrRendererDebugger(OutputMode.XTERM_16)) - >>> render('text', Style(fg='red')) - '(ǝ[31m)text(ǝ[39m)' - - :param renderer: - Default renderer to use globally. Calling this method without arguments - will result in library default renderer `SgrRenderer` being set as default. - - All the methods with the ``renderer`` argument (e.g., `text.render()`) - will use the global default one if said argument is omitted or set to *None*. - - You can specify either the renderer class, in which case manager will - instantiate it with the default parameters, or provide already instantiated - and set up renderer, which will be registred as global. - """ - if isinstance(renderer, type): - renderer = renderer() - cls._default = renderer or SgrRenderer() - - @classmethod - def get_default(cls) -> IRenderer: - """ - Get global renderer instance (`SgrRenderer`, or the one provided earlier with - `set_default()`). - """ - return cls._default - - @classmethod - def set_default_format_always(cls): - """ - Shortcut for forcing all control sequences to be present in the - output of a global renderer. - - Note that it applies only to the renderer that is set up as default at - the moment of calling this method, i.e., all previously created instances, - as well as the ones that will be created afterwards, are unaffected. - """ - cls.set_default(SgrRenderer(OutputMode.TRUE_COLOR)) - - @classmethod - def set_default_format_never(cls): - """ - Shortcut for disabling all output formatting of a global renderer. - """ - cls.set_default(SgrRenderer(OutputMode.NO_ANSI)) - - -class IRenderer(metaclass=ABCMeta): - """Renderer interface.""" - - def __hash__(self) -> int: - """ - Method returning a unique number reflecting current renderer's state. Used for - rendered strings caching. Two renderers of the same class and with the same - settings should have equal hashes, so that cached strings could be reused. - When the internal state of the renderer changes, this number should change as - well, in order to invalidate the caches. - """ - - @property - @abstractmethod - def is_caching_allowed(self) -> bool: - """ - Class-level property. - - :return: *True* if caching of renderer's results makes any sense and *False* - otherwise. - """ - - @property - @abstractmethod - def is_format_allowed(self) -> bool: - """ - :return: *True* if renderer is set up to use the formatting and will do - it on invocation, and *False* otherwise. - """ - - @abstractmethod - def render(self, string: str, fmt: FT = None) -> str: - """ - Apply colors and attributes described in ``fmt`` argument to - ``string`` and return the result. Output format depends on renderer's - class, which defines the implementation. - - :param string: String to format. - :param fmt: Style or color to apply. If ``fmt`` is a `IColor` instance, - it is assumed to be a foreground color. See `FT`. - :return: String with formatting applied, or without it, depending on - renderer settings. - """ - - @abstractmethod - def clone(self: T, *args: t.Any, **kwargs: t.Any) -> T: - """ - Make a copy of the renderer with the same setup. - - :rtype: self - """ - - def __repr__(self): - return self.__class__.__qualname__ + "[]" - - -class OutputMode(enum.Enum): - """ - Determines what types of SGR sequences are allowed to use in the output. - """ - - NO_ANSI = "no_ansi" - """ - The renderer discards all color and format information completely. - """ - XTERM_16 = "xterm_16" - """ - 16-colors mode. Enforces the renderer to approximate all color types - to `Color16` and render them as basic mode selection SGR sequences - (``ESC [31m``, ``ESC [42m`` etc). See `Color.approximate()` for approximation - algorithm details. - """ - XTERM_256 = "xterm_256" - """ - 256-colors mode. Allows the renderer to use either `Color16` or `Color256` - (but RGB will be approximated to 256-color pallette). - """ - TRUE_COLOR = "true_color" - """ - RGB color mode. Does not apply restrictions to color rendering. - """ - AUTO = "auto" - """ - Lets the renderer select the most suitable mode by itself. - See `SgrRenderer` constructor documentation for the details. - """ - - -class SgrRenderer(IRenderer): - """ - Default renderer invoked by `Text.render()`. Transforms `IColor` instances - defined in ``style`` into ANSI control sequence bytes and merges them with - input string. Type of resulting `SequenceSGR` depends on type of `IColor` - instances in ``style`` argument and current output mode of the renderer. - - 1. `ColorRGB` can be rendered as True Color sequence, 256-color sequence - or 16-color sequence depending on specified `OutputMode`. - 2. `Color256` can be rendered as 256-color sequence or 16-color - sequence. - 3. `Color16` will be rendered as 16-color sequence. - 4. Nothing of the above will happen and all formatting will be discarded - completely if output device is not a terminal emulator or if the developer - explicitly set up the renderer to do so (`OutputMode.NO_ANSI`). - - Renderer approximates RGB colors to closest **indexed** colors if terminal doesn't - support RGB output. In case terminal doesn't support even 256 colors, it - falls back to 16-color palette and picks closest samples again the same way. - See `OutputMode` documentation for exact mappings. - - >>> SgrRenderer(OutputMode.XTERM_256).render('text', Styles.WARNING_LABEL) - '\x1b[1;33mtext\x1b[22;39m' - >>> SgrRenderer(OutputMode.NO_ANSI).render('text', Styles.WARNING_LABEL) - 'text' - - :param output_mode: - SGR output mode to use. Valid values are listed in `OutputMode` enum. - - With `OutputMode.AUTO` the renderer will first check if the output - device is a terminal emulator, and use `OutputMode.NO_ANSI` when it - is not. Otherwise, the renderer will read ``TERM`` environment - variable and follow these rules: - - - `OutputMode.NO_ANSI` if ``TERM`` is set to ``xterm``. - - `OutputMode.XTERM_16` if ``TERM`` is set to ``xterm-color``. - - `OutputMode.XTERM_256` in all other cases. - - Special case is when ``TERM`` equals to ``xterm-256color`` **and** - ``COLORTERM`` is either ``truecolor`` or ``24bit``, then - `OutputMode.TRUE_COLOR` will be used. - """ - - _COLOR_UPPER_BOUNDS: t.Dict[OutputMode, t.Type[IColor]] = { - OutputMode.XTERM_16: Color16, - OutputMode.XTERM_256: Color256, - OutputMode.TRUE_COLOR: ColorRGB, - } - - def __init__(self, output_mode: OutputMode = OutputMode.AUTO, io: t.IO = sys.stdout): - self._output_mode: OutputMode = self._determine_output_mode(output_mode, io) - self._color_upper_bound: t.Type[IColor] | None = self._COLOR_UPPER_BOUNDS.get( - self._output_mode, None - ) - - logger.debug( - f"Instantiated {self.__class__.__qualname__}" - f"[{self._output_mode.name} <- {output_mode.name}, " - f"upper bound {get_qname(self._color_upper_bound)}]" - ) - - def __hash__(self) -> int: - # although this renderer is immutable, its state can be set up differently - # on initialization. ``_color_upper_bound`` is a derived variable from - # ``_output_mode`` with one-to-one mapping, thus it can be omitted. - return _digest(self.__class__.__qualname__ + "." + self._output_mode.value) - - @property - def is_caching_allowed(self) -> bool: - return True - - @property - def is_format_allowed(self) -> bool: - return self._output_mode is not OutputMode.NO_ANSI - - def render(self, string: str, fmt: FT = None) -> str: - style = make_style(fmt) - opening_seq = ( - self._render_attributes(style, squash=True) - + self._render_color(style.fg, False) - + self._render_color(style.bg, True) - ) - - # in case there are line breaks -- split text to lines and apply - # SGRs for each line separately. it increases the chances that style - # will be correctly displayed regardless of implementation details of - # user's pager, multiplexer, terminal emulator etc. - rendered_text = "" - for line in string.splitlines(keepends=True): - rendered_text += enclose(opening_seq, line) - return rendered_text - - def clone(self) -> SgrRenderer: - return SgrRenderer(self._output_mode) - - def _determine_output_mode(self, arg_value: OutputMode, io: t.IO) -> OutputMode: - if arg_value is not OutputMode.AUTO: - return arg_value - - isatty = io.isatty() - term = os.environ.get("TERM", None) - colorterm = os.environ.get("COLORTERM", None) - - logger.debug(f"{io.name} is a terminal: {isatty}") - logger.debug(f"Environment: TERM='{term}'") - logger.debug(f"Environment: COLORTERM='{colorterm}'") - - if not isatty: - return OutputMode.NO_ANSI - if term == "xterm": - return OutputMode.NO_ANSI - if term == "xterm-color": - return OutputMode.XTERM_16 - if colorterm in ("truecolor", "24bit"): - return OutputMode.TRUE_COLOR - return OutputMode.XTERM_256 - - def _render_attributes( - self, style: Style, squash: bool - ) -> t.List[SequenceSGR] | SequenceSGR: - if not self.is_format_allowed: - return NOOP_SEQ if squash else [NOOP_SEQ] - - result = [] - if style.blink: - result += [SeqIndex.BLINK_SLOW] - if style.bold: - result += [SeqIndex.BOLD] - if style.crosslined: - result += [SeqIndex.CROSSLINED] - if style.dim: - result += [SeqIndex.DIM] - if style.double_underlined: - result += [SeqIndex.DOUBLE_UNDERLINED] - if style.inversed: - result += [SeqIndex.INVERSED] - if style.italic: - result += [SeqIndex.ITALIC] - if style.overlined: - result += [SeqIndex.OVERLINED] - if style.underlined: - result += [SeqIndex.UNDERLINED] - - if squash: - return reduce(lambda p, c: p + c, result, NOOP_SEQ) - return result - - def _render_color(self, color: IColor, bg: bool) -> SequenceSGR: - if not self.is_format_allowed or color == NOOP_COLOR: - return NOOP_SEQ - return color.to_sgr(bg, self._color_upper_bound) - - -class TmuxRenderer(IRenderer): - """ - Translates `Styles