|
3 | 3 | Support for ANSI escape sequences which are used for things like applying style to text, |
4 | 4 | setting the window title, and asynchronous alerts. |
5 | 5 | """ |
| 6 | +from enum import Enum, unique |
6 | 7 | import functools |
7 | 8 | import re |
8 | | -from typing import Any, IO |
| 9 | +from typing import Any, IO, Union |
9 | 10 |
|
10 | 11 | import colorama |
11 | 12 | from colorama import Fore, Back, Style |
|
46 | 47 | 'reset': Fore.RESET, |
47 | 48 | } |
48 | 49 |
|
| 50 | + |
| 51 | +@unique |
| 52 | +class fg(Enum): |
| 53 | + """Enum class for foreground colors (to support IDE autocompletion).""" |
| 54 | + black = Fore.BLACK |
| 55 | + red = Fore.RED |
| 56 | + green = Fore.GREEN |
| 57 | + yellow = Fore.YELLOW |
| 58 | + blue = Fore.BLUE |
| 59 | + magenta = Fore.MAGENTA |
| 60 | + cyan = Fore.CYAN |
| 61 | + white = Fore.WHITE |
| 62 | + bright_black = Fore.LIGHTBLACK_EX |
| 63 | + bright_red = Fore.LIGHTRED_EX |
| 64 | + bright_green = Fore.LIGHTGREEN_EX |
| 65 | + bright_yellow = Fore.LIGHTYELLOW_EX |
| 66 | + bright_blue = Fore.LIGHTBLUE_EX |
| 67 | + bright_magenta = Fore.LIGHTMAGENTA_EX |
| 68 | + bright_cyan = Fore.LIGHTCYAN_EX |
| 69 | + bright_white = Fore.LIGHTWHITE_EX |
| 70 | + reset = Fore.RESET |
| 71 | + |
| 72 | + def __str__(self): |
| 73 | + """Make the value the string representation instead of the enum name.""" |
| 74 | + return self.value |
| 75 | + |
| 76 | + |
49 | 77 | # Background color presets |
50 | 78 | BG_COLORS = { |
51 | 79 | 'black': Back.BLACK, |
|
67 | 95 | 'reset': Back.RESET, |
68 | 96 | } |
69 | 97 |
|
| 98 | + |
| 99 | +@unique |
| 100 | +class bg(Enum): |
| 101 | + """Enum class for background colors (to support IDE autocompletion).""" |
| 102 | + black = Back.BLACK |
| 103 | + red = Back.RED |
| 104 | + green = Back.GREEN |
| 105 | + yellow = Back.YELLOW |
| 106 | + blue = Back.BLUE |
| 107 | + magenta = Back.MAGENTA |
| 108 | + cyan = Back.CYAN |
| 109 | + white = Back.WHITE |
| 110 | + bright_black = Back.LIGHTBLACK_EX |
| 111 | + bright_red = Back.LIGHTRED_EX |
| 112 | + bright_green = Back.LIGHTGREEN_EX |
| 113 | + bright_yellow = Back.LIGHTYELLOW_EX |
| 114 | + bright_blue = Back.LIGHTBLUE_EX |
| 115 | + bright_magenta = Back.LIGHTMAGENTA_EX |
| 116 | + bright_cyan = Back.LIGHTCYAN_EX |
| 117 | + bright_white = Back.LIGHTWHITE_EX |
| 118 | + reset = Back.RESET |
| 119 | + |
| 120 | + def __str__(self): |
| 121 | + """Make the value the string representation instead of the enum name.""" |
| 122 | + return self.value |
| 123 | + |
| 124 | + |
70 | 125 | FG_RESET = FG_COLORS['reset'] |
71 | 126 | BG_RESET = BG_COLORS['reset'] |
72 | 127 | RESET_ALL = Style.RESET_ALL |
|
75 | 130 | INTENSITY_BRIGHT = Style.BRIGHT |
76 | 131 | INTENSITY_DIM = Style.DIM |
77 | 132 | INTENSITY_NORMAL = Style.NORMAL |
78 | | - |
79 | 133 | # ANSI style sequences not provided by colorama |
80 | 134 | UNDERLINE_ENABLE = colorama.ansi.code_to_chars(4) |
81 | 135 | UNDERLINE_DISABLE = colorama.ansi.code_to_chars(24) |
@@ -115,46 +169,52 @@ def style_aware_write(fileobj: IO, msg: str) -> None: |
115 | 169 | fileobj.write(msg) |
116 | 170 |
|
117 | 171 |
|
118 | | -def fg_lookup(fg_name: str) -> str: |
| 172 | +def fg_lookup(fg_name: Union[str, fg]) -> str: |
119 | 173 | """ |
120 | 174 | Look up ANSI escape codes based on foreground color name. |
121 | 175 |
|
122 | | - :param fg_name: foreground color name to look up ANSI escape code(s) for |
| 176 | + :param fg_name: foreground color name or enum to look up ANSI escape code(s) for |
123 | 177 | :return: ANSI escape code(s) associated with this color |
124 | 178 | :raises ValueError: if the color cannot be found |
125 | 179 | """ |
| 180 | + if isinstance(fg_name, fg): |
| 181 | + return fg_name.value |
| 182 | + |
126 | 183 | try: |
127 | 184 | ansi_escape = FG_COLORS[fg_name.lower()] |
128 | 185 | except KeyError: |
129 | 186 | raise ValueError('Foreground color {!r} does not exist.'.format(fg_name)) |
130 | 187 | return ansi_escape |
131 | 188 |
|
132 | 189 |
|
133 | | -def bg_lookup(bg_name: str) -> str: |
| 190 | +def bg_lookup(bg_name: Union[str, bg]) -> str: |
134 | 191 | """ |
135 | 192 | Look up ANSI escape codes based on background color name. |
136 | 193 |
|
137 | | - :param bg_name: background color name to look up ANSI escape code(s) for |
| 194 | + :param bg_name: background color name or enum to look up ANSI escape code(s) for |
138 | 195 | :return: ANSI escape code(s) associated with this color |
139 | 196 | :raises ValueError: if the color cannot be found |
140 | 197 | """ |
| 198 | + if isinstance(bg_name, bg): |
| 199 | + return bg_name.value |
| 200 | + |
141 | 201 | try: |
142 | 202 | ansi_escape = BG_COLORS[bg_name.lower()] |
143 | 203 | except KeyError: |
144 | 204 | raise ValueError('Background color {!r} does not exist.'.format(bg_name)) |
145 | 205 | return ansi_escape |
146 | 206 |
|
147 | 207 |
|
148 | | -def style(text: Any, *, fg: str = '', bg: str = '', bold: bool = False, |
| 208 | +def style(text: Any, *, fg: Union[str, fg] = '', bg: Union[str, bg] = '', bold: bool = False, |
149 | 209 | dim: bool = False, underline: bool = False) -> str: |
150 | 210 | """ |
151 | 211 | Apply ANSI colors and/or styles to a string and return it. |
152 | 212 | The styling is self contained which means that at the end of the string reset code(s) are issued |
153 | 213 | to undo whatever styling was done at the beginning. |
154 | 214 |
|
155 | 215 | :param text: Any object compatible with str.format() |
156 | | - :param fg: foreground color. Relies on `fg_lookup()` to retrieve ANSI escape based on name. Defaults to no color. |
157 | | - :param bg: background color. Relies on `bg_lookup()` to retrieve ANSI escape based on name. Defaults to no color. |
| 216 | + :param fg: foreground color. Relies on `fg_lookup()` to retrieve ANSI escape based on name or enum. Defaults to no color. |
| 217 | + :param bg: background color. Relies on `bg_lookup()` to retrieve ANSI escape based on name or enum. Defaults to no color. |
158 | 218 | :param bold: apply the bold style if True. Can be combined with dim. Defaults to False. |
159 | 219 | :param dim: apply the dim style if True. Can be combined with bold. Defaults to False. |
160 | 220 | :param underline: apply the underline style if True. Defaults to False. |
@@ -197,13 +257,13 @@ def style(text: Any, *, fg: str = '', bg: str = '', bold: bool = False, |
197 | 257 | # Default styles for printing strings of various types. |
198 | 258 | # These can be altered to suit an application's needs and only need to be a |
199 | 259 | # function with the following structure: func(str) -> str |
200 | | -style_success = functools.partial(style, fg='green') |
| 260 | +style_success = functools.partial(style, fg=fg.green) |
201 | 261 | """Partial function supplying arguments to :meth:`cmd2.ansi.style()` which colors text to signify success""" |
202 | 262 |
|
203 | | -style_warning = functools.partial(style, fg='bright_yellow') |
| 263 | +style_warning = functools.partial(style, fg=fg.bright_yellow) |
204 | 264 | """Partial function supplying arguments to :meth:`cmd2.ansi.style()` which colors text to signify a warning""" |
205 | 265 |
|
206 | | -style_error = functools.partial(style, fg='bright_red') |
| 266 | +style_error = functools.partial(style, fg=fg.bright_red) |
207 | 267 | """Partial function supplying arguments to :meth:`cmd2.ansi.style()` which colors text to signify an error""" |
208 | 268 |
|
209 | 269 |
|
|
0 commit comments