1""" 
    2The base classes for the styling. 
    3""" 
    4 
    5from __future__ import annotations 
    6 
    7from abc import ABCMeta, abstractmethod 
    8from typing import Callable, Hashable, NamedTuple 
    9 
    10__all__ = [ 
    11    "Attrs", 
    12    "DEFAULT_ATTRS", 
    13    "ANSI_COLOR_NAMES", 
    14    "ANSI_COLOR_NAMES_ALIASES", 
    15    "BaseStyle", 
    16    "DummyStyle", 
    17    "DynamicStyle", 
    18] 
    19 
    20 
    21#: Style attributes. 
    22class Attrs(NamedTuple): 
    23    color: str | None 
    24    bgcolor: str | None 
    25    bold: bool | None 
    26    underline: bool | None 
    27    strike: bool | None 
    28    italic: bool | None 
    29    blink: bool | None 
    30    reverse: bool | None 
    31    hidden: bool | None 
    32    dim: bool | None 
    33 
    34 
    35""" 
    36:param color: Hexadecimal string. E.g. '000000' or Ansi color name: e.g. 'ansiblue' 
    37:param bgcolor: Hexadecimal string. E.g. 'ffffff' or Ansi color name: e.g. 'ansired' 
    38:param bold: Boolean 
    39:param underline: Boolean 
    40:param strike: Boolean 
    41:param italic: Boolean 
    42:param blink: Boolean 
    43:param reverse: Boolean 
    44:param hidden: Boolean 
    45:param dim: Boolean 
    46""" 
    47 
    48#: The default `Attrs`. 
    49DEFAULT_ATTRS = Attrs( 
    50    color="", 
    51    bgcolor="", 
    52    bold=False, 
    53    underline=False, 
    54    strike=False, 
    55    italic=False, 
    56    blink=False, 
    57    reverse=False, 
    58    hidden=False, 
    59    dim=False, 
    60) 
    61 
    62 
    63#: ``Attrs.bgcolor/fgcolor`` can be in either 'ffffff' format, or can be any of 
    64#: the following in case we want to take colors from the 8/16 color palette. 
    65#: Usually, in that case, the terminal application allows to configure the RGB 
    66#: values for these names. 
    67#: ISO 6429 colors 
    68ANSI_COLOR_NAMES = [ 
    69    "ansidefault", 
    70    # Low intensity, dark.  (One or two components 0x80, the other 0x00.) 
    71    "ansiblack", 
    72    "ansired", 
    73    "ansigreen", 
    74    "ansiyellow", 
    75    "ansiblue", 
    76    "ansimagenta", 
    77    "ansicyan", 
    78    "ansigray", 
    79    # High intensity, bright. (One or two components 0xff, the other 0x00. Not supported everywhere.) 
    80    "ansibrightblack", 
    81    "ansibrightred", 
    82    "ansibrightgreen", 
    83    "ansibrightyellow", 
    84    "ansibrightblue", 
    85    "ansibrightmagenta", 
    86    "ansibrightcyan", 
    87    "ansiwhite", 
    88] 
    89 
    90 
    91# People don't use the same ANSI color names everywhere. In prompt_toolkit 1.0 
    92# we used some unconventional names (which were contributed like that to 
    93# Pygments). This is fixed now, but we still support the old names. 
    94 
    95# The table below maps the old aliases to the current names. 
    96ANSI_COLOR_NAMES_ALIASES: dict[str, str] = { 
    97    "ansidarkgray": "ansibrightblack", 
    98    "ansiteal": "ansicyan", 
    99    "ansiturquoise": "ansibrightcyan", 
    100    "ansibrown": "ansiyellow", 
    101    "ansipurple": "ansimagenta", 
    102    "ansifuchsia": "ansibrightmagenta", 
    103    "ansilightgray": "ansigray", 
    104    "ansidarkred": "ansired", 
    105    "ansidarkgreen": "ansigreen", 
    106    "ansidarkblue": "ansiblue", 
    107} 
    108assert set(ANSI_COLOR_NAMES_ALIASES.values()).issubset(set(ANSI_COLOR_NAMES)) 
    109assert not (set(ANSI_COLOR_NAMES_ALIASES.keys()) & set(ANSI_COLOR_NAMES)) 
    110 
    111 
    112class BaseStyle(metaclass=ABCMeta): 
    113    """ 
    114    Abstract base class for prompt_toolkit styles. 
    115    """ 
    116 
    117    @abstractmethod 
    118    def get_attrs_for_style_str( 
    119        self, style_str: str, default: Attrs = DEFAULT_ATTRS 
    120    ) -> Attrs: 
    121        """ 
    122        Return :class:`.Attrs` for the given style string. 
    123 
    124        :param style_str: The style string. This can contain inline styling as 
    125            well as classnames (e.g. "class:title"). 
    126        :param default: `Attrs` to be used if no styling was defined. 
    127        """ 
    128 
    129    @property 
    130    @abstractmethod 
    131    def style_rules(self) -> list[tuple[str, str]]: 
    132        """ 
    133        The list of style rules, used to create this style. 
    134        (Required for `DynamicStyle` and `_MergedStyle` to work.) 
    135        """ 
    136        return [] 
    137 
    138    @abstractmethod 
    139    def invalidation_hash(self) -> Hashable: 
    140        """ 
    141        Invalidation hash for the style. When this changes over time, the 
    142        renderer knows that something in the style changed, and that everything 
    143        has to be redrawn. 
    144        """ 
    145 
    146 
    147class DummyStyle(BaseStyle): 
    148    """ 
    149    A style that doesn't style anything. 
    150    """ 
    151 
    152    def get_attrs_for_style_str( 
    153        self, style_str: str, default: Attrs = DEFAULT_ATTRS 
    154    ) -> Attrs: 
    155        return default 
    156 
    157    def invalidation_hash(self) -> Hashable: 
    158        return 1  # Always the same value. 
    159 
    160    @property 
    161    def style_rules(self) -> list[tuple[str, str]]: 
    162        return [] 
    163 
    164 
    165class DynamicStyle(BaseStyle): 
    166    """ 
    167    Style class that can dynamically returns an other Style. 
    168 
    169    :param get_style: Callable that returns a :class:`.Style` instance. 
    170    """ 
    171 
    172    def __init__(self, get_style: Callable[[], BaseStyle | None]): 
    173        self.get_style = get_style 
    174        self._dummy = DummyStyle() 
    175 
    176    def get_attrs_for_style_str( 
    177        self, style_str: str, default: Attrs = DEFAULT_ATTRS 
    178    ) -> Attrs: 
    179        style = self.get_style() or self._dummy 
    180 
    181        return style.get_attrs_for_style_str(style_str, default) 
    182 
    183    def invalidation_hash(self) -> Hashable: 
    184        return (self.get_style() or self._dummy).invalidation_hash() 
    185 
    186    @property 
    187    def style_rules(self) -> list[tuple[str, str]]: 
    188        return (self.get_style() or self._dummy).style_rules