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