teddecor.TED.tokens
1from __future__ import annotations 2from functools import cached_property 3from lib2to3.pytree import Base 4from typing import Union, Callable, Dict 5 6from .formatting import build_color, ColorType, LINK, RESET, FUNC 7 8 9class Token: 10 """Generic base class that has a default repr.""" 11 12 def __repr__(self) -> str: 13 return f"<{type(self).__name__}: {self._markup}, {self.value}>" 14 15 16class Reset(Token): 17 @property 18 def value(self) -> str: 19 return RESET 20 21 def __str__(self) -> str: 22 return self.value 23 24 25class Func(Token): 26 def __init__(self, markup: str, funcs: Dict[str, Callable]) -> None: 27 self._markup: str = markup 28 self._func: str = markup[1:].strip().lower() 29 self._caller = lambda string: string 30 self.parse_func(funcs) 31 32 def parse_func(self, funcs: Dict[str, Callable]) -> None: 33 if self._func in funcs: 34 self._caller = funcs[self._func] 35 else: 36 raise ValueError(f"Invalid Function \x1b[1;31m{self._markup}\x1b[0m") 37 38 def exec(self, string: str) -> str: 39 return self._caller(string) 40 41 @property 42 def value(self) -> str: 43 return self._func 44 45 def __str__(self) -> str: 46 return self._markup 47 48 def __repr__(self) -> str: 49 return f"<Func: {self._func}" 50 51 52class HLink(Token): 53 def __init__(self, markup: str) -> None: 54 self._markup = markup.strip() 55 self._closing = False 56 self._value = self.parse_link() 57 58 def parse_link(self) -> str: 59 """Determine if the token is a closing link token and assign _closing accordingly. 60 61 Returns: 62 str: The value of the token based on if the token is closing 63 """ 64 if len(self._markup) == 1: 65 self._closing = True 66 return LINK.CLOSE 67 elif len(self._markup) > 1: 68 return LINK.OPEN(self._markup[1:]) 69 70 @property 71 def value(self) -> str: 72 """Value of the token.""" 73 return self._value 74 75 @value.setter 76 def value(self, value: str) -> str: 77 self._value = value 78 79 @property 80 def closing(self) -> bool: 81 """True if this link token is a closing link token.""" 82 return self._closing 83 84 def __str__(self) -> str: 85 return self.value 86 87 88class Text(Token): 89 """Plain text token.""" 90 91 def __init__(self, markup: str) -> None: 92 self._markup: str = markup 93 self._value: str = markup 94 95 @property 96 def value(self) -> str: 97 """Fomatted value of the tokens markup.""" 98 return self._value 99 100 @value.setter 101 def value(self, text: str) -> str: 102 """Fomatted value of the tokens markup.""" 103 self._value = text 104 105 def __repr__(self) -> str: 106 return f"<{type(self).__name__}: '{self._markup}'>" 107 108 def __str__(self) -> str: 109 return self._value 110 111 112class Color(Token): 113 """A color tokens that is either hex, xterm, rgb, or predefined.""" 114 115 def __init__( 116 self, markup: str, colors: list[int] = None, ctype: ColorType = None 117 ) -> None: 118 self._markup: str = markup 119 self._type, self._colors = build_color(markup) 120 if colors is not None: 121 self._colors = colors 122 if ctype is not None: 123 self._type = ctype 124 125 @cached_property 126 def value(self) -> str: 127 """Fomatted value of the tokens markup.""" 128 return f"{';'.join(self._colors)}" 129 130 @cached_property 131 def type_str(self) -> str: 132 """Redable type of the color.""" 133 if len(self._type) == 1 and self._type[0] == ColorType.FG: 134 return "FG" 135 elif len(self._type) == 1 and self._type[0] == ColorType.BG: 136 return "BG" 137 else: 138 return "FG + BG" 139 140 @property 141 def colors(self) -> list[int]: 142 """List of color codes.""" 143 return self._colors 144 145 @colors.setter 146 def colors(self, colors: list[int]) -> None: 147 self._colors = colors 148 149 @property 150 def type(self) -> ColorType: 151 """The colors type; fg, bg, or both.""" 152 return self._type 153 154 def __repr__(self) -> str: 155 """String representation of the class when printing class.""" 156 return f"<Color: {self.type}, {repr(self.value)}>" 157 158 def __str__(self) -> str: 159 """Full ansi representation of the token.""" 160 return f"\x1b[{';'.join(self._colors)}m" 161 162 163class Bold(Token): 164 def __init__(self, value: str) -> None: 165 self._markup: str = "*" 166 self._value: str = value 167 168 @property 169 def value(self) -> int: 170 """The ansi code for the markup.""" 171 return self._value 172 173 def __str__(self) -> str: 174 """Full ansi representation of the token.""" 175 return f"\x1b[{self.value}m" 176 177 178class Underline(Token): 179 def __init__(self, value: str) -> None: 180 self._markup: str = "_" 181 self._value: str = value 182 183 @property 184 def value(self) -> int: 185 """The ansi code for the markup.""" 186 return self._value 187 188 def __str__(self) -> str: 189 """Full ansi representation of the token.""" 190 return f"\x1b[{self.value}m" 191 192 193class Formatter(Token): 194 """A class used to combine format tokens that are next to eachother.""" 195 196 def __init__(self): 197 self._fg = None 198 self._bg = None 199 self._underline = None 200 self._bold = None 201 202 @property 203 def color(self) -> str: 204 """The colors current in the format""" 205 return f"{self._fg};{self._bg}" 206 207 @color.setter 208 def color(self, color: Color) -> None: 209 if color.type == [ColorType.FG]: 210 self._fg = color 211 elif color.type == [ColorType.BG]: 212 self._bg = color 213 elif color.type == ColorType.BOTH: 214 self._fg = Color("", [color.colors[0]], [ColorType.FG]) 215 self._bg = Color("", [color.colors[1]], [ColorType.BG]) 216 217 @property 218 def bold(self) -> Union[Bold, None]: 219 """The bold toggle currently in the format.""" 220 return self._bold 221 222 @bold.setter 223 def bold(self, bold: Bold) -> None: 224 self._bold = bold if self._bold is None else None 225 226 @property 227 def underline(self) -> Union[Underline, None]: 228 """The underline toggle currently in the format.""" 229 return self._underline 230 231 @bold.setter 232 def underline(self, underline: Underline) -> None: 233 self._underline = underline if self._underline is None else None 234 235 def is_empty(self) -> bool: 236 """True if all of fg, bg, underline, and bold are None.""" 237 return ( 238 self._fg is None 239 and self._bg is None 240 and self._underline is None 241 and self._bold is None 242 ) 243 244 def __str__(self) -> str: 245 values = [] 246 if self._bold is not None: 247 values.append(self._bold.value) 248 if self._underline is not None: 249 values.append(self._underline.value) 250 if self._fg is not None: 251 values.append(self._fg.value) 252 if self._bg is not None: 253 values.append(self._bg.value) 254 255 if len(values) > 0: 256 return f"\x1b[{';'.join(str(value) for value in values)}m" 257 else: 258 return "" 259 260 def __repr__(self) -> str: 261 return f"<Format: {repr(str(self))}>"
class
Token:
10class Token: 11 """Generic base class that has a default repr.""" 12 13 def __repr__(self) -> str: 14 return f"<{type(self).__name__}: {self._markup}, {self.value}>"
Generic base class that has a default repr.
17class Reset(Token): 18 @property 19 def value(self) -> str: 20 return RESET 21 22 def __str__(self) -> str: 23 return self.value
Generic base class that has a default repr.
26class Func(Token): 27 def __init__(self, markup: str, funcs: Dict[str, Callable]) -> None: 28 self._markup: str = markup 29 self._func: str = markup[1:].strip().lower() 30 self._caller = lambda string: string 31 self.parse_func(funcs) 32 33 def parse_func(self, funcs: Dict[str, Callable]) -> None: 34 if self._func in funcs: 35 self._caller = funcs[self._func] 36 else: 37 raise ValueError(f"Invalid Function \x1b[1;31m{self._markup}\x1b[0m") 38 39 def exec(self, string: str) -> str: 40 return self._caller(string) 41 42 @property 43 def value(self) -> str: 44 return self._func 45 46 def __str__(self) -> str: 47 return self._markup 48 49 def __repr__(self) -> str: 50 return f"<Func: {self._func}"
Generic base class that has a default repr.
53class HLink(Token): 54 def __init__(self, markup: str) -> None: 55 self._markup = markup.strip() 56 self._closing = False 57 self._value = self.parse_link() 58 59 def parse_link(self) -> str: 60 """Determine if the token is a closing link token and assign _closing accordingly. 61 62 Returns: 63 str: The value of the token based on if the token is closing 64 """ 65 if len(self._markup) == 1: 66 self._closing = True 67 return LINK.CLOSE 68 elif len(self._markup) > 1: 69 return LINK.OPEN(self._markup[1:]) 70 71 @property 72 def value(self) -> str: 73 """Value of the token.""" 74 return self._value 75 76 @value.setter 77 def value(self, value: str) -> str: 78 self._value = value 79 80 @property 81 def closing(self) -> bool: 82 """True if this link token is a closing link token.""" 83 return self._closing 84 85 def __str__(self) -> str: 86 return self.value
Generic base class that has a default repr.
def
parse_link(self) -> str:
59 def parse_link(self) -> str: 60 """Determine if the token is a closing link token and assign _closing accordingly. 61 62 Returns: 63 str: The value of the token based on if the token is closing 64 """ 65 if len(self._markup) == 1: 66 self._closing = True 67 return LINK.CLOSE 68 elif len(self._markup) > 1: 69 return LINK.OPEN(self._markup[1:])
Determine if the token is a closing link token and assign _closing accordingly.
Returns: str: The value of the token based on if the token is closing
89class Text(Token): 90 """Plain text token.""" 91 92 def __init__(self, markup: str) -> None: 93 self._markup: str = markup 94 self._value: str = markup 95 96 @property 97 def value(self) -> str: 98 """Fomatted value of the tokens markup.""" 99 return self._value 100 101 @value.setter 102 def value(self, text: str) -> str: 103 """Fomatted value of the tokens markup.""" 104 self._value = text 105 106 def __repr__(self) -> str: 107 return f"<{type(self).__name__}: '{self._markup}'>" 108 109 def __str__(self) -> str: 110 return self._value
Plain text token.
113class Color(Token): 114 """A color tokens that is either hex, xterm, rgb, or predefined.""" 115 116 def __init__( 117 self, markup: str, colors: list[int] = None, ctype: ColorType = None 118 ) -> None: 119 self._markup: str = markup 120 self._type, self._colors = build_color(markup) 121 if colors is not None: 122 self._colors = colors 123 if ctype is not None: 124 self._type = ctype 125 126 @cached_property 127 def value(self) -> str: 128 """Fomatted value of the tokens markup.""" 129 return f"{';'.join(self._colors)}" 130 131 @cached_property 132 def type_str(self) -> str: 133 """Redable type of the color.""" 134 if len(self._type) == 1 and self._type[0] == ColorType.FG: 135 return "FG" 136 elif len(self._type) == 1 and self._type[0] == ColorType.BG: 137 return "BG" 138 else: 139 return "FG + BG" 140 141 @property 142 def colors(self) -> list[int]: 143 """List of color codes.""" 144 return self._colors 145 146 @colors.setter 147 def colors(self, colors: list[int]) -> None: 148 self._colors = colors 149 150 @property 151 def type(self) -> ColorType: 152 """The colors type; fg, bg, or both.""" 153 return self._type 154 155 def __repr__(self) -> str: 156 """String representation of the class when printing class.""" 157 return f"<Color: {self.type}, {repr(self.value)}>" 158 159 def __str__(self) -> str: 160 """Full ansi representation of the token.""" 161 return f"\x1b[{';'.join(self._colors)}m"
A color tokens that is either hex, xterm, rgb, or predefined.
164class Bold(Token): 165 def __init__(self, value: str) -> None: 166 self._markup: str = "*" 167 self._value: str = value 168 169 @property 170 def value(self) -> int: 171 """The ansi code for the markup.""" 172 return self._value 173 174 def __str__(self) -> str: 175 """Full ansi representation of the token.""" 176 return f"\x1b[{self.value}m"
Generic base class that has a default repr.
179class Underline(Token): 180 def __init__(self, value: str) -> None: 181 self._markup: str = "_" 182 self._value: str = value 183 184 @property 185 def value(self) -> int: 186 """The ansi code for the markup.""" 187 return self._value 188 189 def __str__(self) -> str: 190 """Full ansi representation of the token.""" 191 return f"\x1b[{self.value}m"
Generic base class that has a default repr.
194class Formatter(Token): 195 """A class used to combine format tokens that are next to eachother.""" 196 197 def __init__(self): 198 self._fg = None 199 self._bg = None 200 self._underline = None 201 self._bold = None 202 203 @property 204 def color(self) -> str: 205 """The colors current in the format""" 206 return f"{self._fg};{self._bg}" 207 208 @color.setter 209 def color(self, color: Color) -> None: 210 if color.type == [ColorType.FG]: 211 self._fg = color 212 elif color.type == [ColorType.BG]: 213 self._bg = color 214 elif color.type == ColorType.BOTH: 215 self._fg = Color("", [color.colors[0]], [ColorType.FG]) 216 self._bg = Color("", [color.colors[1]], [ColorType.BG]) 217 218 @property 219 def bold(self) -> Union[Bold, None]: 220 """The bold toggle currently in the format.""" 221 return self._bold 222 223 @bold.setter 224 def bold(self, bold: Bold) -> None: 225 self._bold = bold if self._bold is None else None 226 227 @property 228 def underline(self) -> Union[Underline, None]: 229 """The underline toggle currently in the format.""" 230 return self._underline 231 232 @bold.setter 233 def underline(self, underline: Underline) -> None: 234 self._underline = underline if self._underline is None else None 235 236 def is_empty(self) -> bool: 237 """True if all of fg, bg, underline, and bold are None.""" 238 return ( 239 self._fg is None 240 and self._bg is None 241 and self._underline is None 242 and self._bold is None 243 ) 244 245 def __str__(self) -> str: 246 values = [] 247 if self._bold is not None: 248 values.append(self._bold.value) 249 if self._underline is not None: 250 values.append(self._underline.value) 251 if self._fg is not None: 252 values.append(self._fg.value) 253 if self._bg is not None: 254 values.append(self._bg.value) 255 256 if len(values) > 0: 257 return f"\x1b[{';'.join(str(value) for value in values)}m" 258 else: 259 return "" 260 261 def __repr__(self) -> str: 262 return f"<Format: {repr(str(self))}>"
A class used to combine format tokens that are next to eachother.