cmd2 2.6.2__py3-none-any.whl → 3.0.0b1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
cmd2/ansi.py DELETED
@@ -1,1093 +0,0 @@
1
- """Support for ANSI escape sequences.
2
-
3
- These are used for things like applying style to text, setting the window title, and asynchronous alerts.
4
- """
5
-
6
- import functools
7
- import re
8
- from enum import (
9
- Enum,
10
- )
11
- from typing import (
12
- IO,
13
- Any,
14
- Optional,
15
- cast,
16
- )
17
-
18
- from wcwidth import ( # type: ignore[import]
19
- wcswidth,
20
- )
21
-
22
- #######################################################
23
- # Common ANSI escape sequence constants
24
- #######################################################
25
- ESC = '\x1b'
26
- CSI = f'{ESC}['
27
- OSC = f'{ESC}]'
28
- BEL = '\a'
29
-
30
-
31
- class AllowStyle(Enum):
32
- """Values for ``cmd2.ansi.allow_style``."""
33
-
34
- ALWAYS = 'Always' # Always output ANSI style sequences
35
- NEVER = 'Never' # Remove ANSI style sequences from all output
36
- TERMINAL = 'Terminal' # Remove ANSI style sequences if the output is not going to the terminal
37
-
38
- def __str__(self) -> str:
39
- """Return value instead of enum name for printing in cmd2's set command."""
40
- return str(self.value)
41
-
42
- def __repr__(self) -> str:
43
- """Return quoted value instead of enum description for printing in cmd2's set command."""
44
- return repr(self.value)
45
-
46
-
47
- # Controls when ANSI style sequences are allowed in output
48
- allow_style = AllowStyle.TERMINAL
49
- """When using outside of a cmd2 app, set this variable to one of:
50
-
51
- - ``AllowStyle.ALWAYS`` - always output ANSI style sequences
52
- - ``AllowStyle.NEVER`` - remove ANSI style sequences from all output
53
- - ``AllowStyle.TERMINAL`` - remove ANSI style sequences if the output is not going to the terminal
54
-
55
- to control how ANSI style sequences are handled by ``style_aware_write()``.
56
-
57
- ``style_aware_write()`` is called by cmd2 methods like ``poutput()``, ``perror()``,
58
- ``pwarning()``, etc.
59
-
60
- The default is ``AllowStyle.TERMINAL``.
61
- """
62
-
63
- # Regular expression to match ANSI style sequence
64
- ANSI_STYLE_RE = re.compile(rf'{ESC}\[[^m]*m')
65
-
66
- # Matches standard foreground colors: CSI(30-37|90-97|39)m
67
- STD_FG_RE = re.compile(rf'{ESC}\[(?:[39][0-7]|39)m')
68
-
69
- # Matches standard background colors: CSI(40-47|100-107|49)m
70
- STD_BG_RE = re.compile(rf'{ESC}\[(?:(?:4|10)[0-7]|49)m')
71
-
72
- # Matches eight-bit foreground colors: CSI38;5;(0-255)m
73
- EIGHT_BIT_FG_RE = re.compile(rf'{ESC}\[38;5;(?:1?[0-9]?[0-9]?|2[0-4][0-9]|25[0-5])m')
74
-
75
- # Matches eight-bit background colors: CSI48;5;(0-255)m
76
- EIGHT_BIT_BG_RE = re.compile(rf'{ESC}\[48;5;(?:1?[0-9]?[0-9]?|2[0-4][0-9]|25[0-5])m')
77
-
78
- # Matches RGB foreground colors: CSI38;2;(0-255);(0-255);(0-255)m
79
- RGB_FG_RE = re.compile(rf'{ESC}\[38;2(?:;(?:1?[0-9]?[0-9]?|2[0-4][0-9]|25[0-5])){{3}}m')
80
-
81
- # Matches RGB background colors: CSI48;2;(0-255);(0-255);(0-255)m
82
- RGB_BG_RE = re.compile(rf'{ESC}\[48;2(?:;(?:1?[0-9]?[0-9]?|2[0-4][0-9]|25[0-5])){{3}}m')
83
-
84
-
85
- def strip_style(text: str) -> str:
86
- """Strip ANSI style sequences from a string.
87
-
88
- :param text: string which may contain ANSI style sequences
89
- :return: the same string with any ANSI style sequences removed
90
- """
91
- return ANSI_STYLE_RE.sub('', text)
92
-
93
-
94
- def style_aware_wcswidth(text: str) -> int:
95
- """Wrap wcswidth to make it compatible with strings that contain ANSI style sequences.
96
-
97
- This is intended for single line strings. If text contains a newline, this
98
- function will return -1. For multiline strings, call widest_line() instead.
99
-
100
- :param text: the string being measured
101
- :return: The width of the string when printed to the terminal if no errors occur.
102
- If text contains characters with no absolute width (i.e. tabs),
103
- then this function returns -1. Replace tabs with spaces before calling this.
104
- """
105
- # Strip ANSI style sequences since they cause wcswidth to return -1
106
- return cast(int, wcswidth(strip_style(text)))
107
-
108
-
109
- def widest_line(text: str) -> int:
110
- """Return the width of the widest line in a multiline string.
111
-
112
- This wraps style_aware_wcswidth() so it handles ANSI style sequences and has the same
113
- restrictions on non-printable characters.
114
-
115
- :param text: the string being measured
116
- :return: The width of the string when printed to the terminal if no errors occur.
117
- If text contains characters with no absolute width (i.e. tabs),
118
- then this function returns -1. Replace tabs with spaces before calling this.
119
- """
120
- if not text:
121
- return 0
122
-
123
- lines_widths = [style_aware_wcswidth(line) for line in text.splitlines()]
124
- if -1 in lines_widths:
125
- return -1
126
-
127
- return max(lines_widths)
128
-
129
-
130
- def style_aware_write(fileobj: IO[str], msg: str) -> None:
131
- """Write a string to a fileobject and strip its ANSI style sequences if required by allow_style setting.
132
-
133
- :param fileobj: the file object being written to
134
- :param msg: the string being written
135
- """
136
- if allow_style == AllowStyle.NEVER or (allow_style == AllowStyle.TERMINAL and not fileobj.isatty()):
137
- msg = strip_style(msg)
138
- fileobj.write(msg)
139
-
140
-
141
- ####################################################################################
142
- # Utility functions which create various ANSI sequences
143
- ####################################################################################
144
- def set_title(title: str) -> str:
145
- """Generate a string that, when printed, sets a terminal's window title.
146
-
147
- :param title: new title for the window
148
- :return: the set title string
149
- """
150
- return f"{OSC}2;{title}{BEL}"
151
-
152
-
153
- def clear_screen(clear_type: int = 2) -> str:
154
- """Generate a string that, when printed, clears a terminal screen based on value of clear_type.
155
-
156
- :param clear_type: integer which specifies how to clear the screen (Defaults to 2)
157
- Possible values:
158
- 0 - clear from cursor to end of screen
159
- 1 - clear from cursor to beginning of the screen
160
- 2 - clear entire screen
161
- 3 - clear entire screen and delete all lines saved in the scrollback buffer
162
- :return: the clear screen string
163
- :raises ValueError: if clear_type is not a valid value
164
- """
165
- if 0 <= clear_type <= 3:
166
- return f"{CSI}{clear_type}J"
167
- raise ValueError("clear_type must in an integer from 0 to 3")
168
-
169
-
170
- def clear_line(clear_type: int = 2) -> str:
171
- """Generate a string that, when printed, clears a line based on value of clear_type.
172
-
173
- :param clear_type: integer which specifies how to clear the line (Defaults to 2)
174
- Possible values:
175
- 0 - clear from cursor to the end of the line
176
- 1 - clear from cursor to beginning of the line
177
- 2 - clear entire line
178
- :return: the clear line string
179
- :raises ValueError: if clear_type is not a valid value
180
- """
181
- if 0 <= clear_type <= 2:
182
- return f"{CSI}{clear_type}K"
183
- raise ValueError("clear_type must in an integer from 0 to 2")
184
-
185
-
186
- ####################################################################################
187
- # Base classes which are not intended to be used directly
188
- ####################################################################################
189
- class AnsiSequence:
190
- """Base class to create ANSI sequence strings."""
191
-
192
- def __add__(self, other: Any) -> str:
193
- """Support building an ANSI sequence string when self is the left operand.
194
-
195
- e.g. Fg.LIGHT_MAGENTA + "hello"
196
- """
197
- return str(self) + str(other)
198
-
199
- def __radd__(self, other: Any) -> str:
200
- """Support building an ANSI sequence string when self is the right operand.
201
-
202
- e.g. "hello" + Fg.RESET
203
- """
204
- return str(other) + str(self)
205
-
206
-
207
- class FgColor(AnsiSequence):
208
- """Base class for ANSI Sequences which set foreground text color."""
209
-
210
-
211
- class BgColor(AnsiSequence):
212
- """Base class for ANSI Sequences which set background text color."""
213
-
214
-
215
- ####################################################################################
216
- # Implementations intended for direct use (do NOT use outside of cmd2)
217
- ####################################################################################
218
- class Cursor:
219
- """Create ANSI sequences to alter the cursor position."""
220
-
221
- @staticmethod
222
- def UP(count: int = 1) -> str: # noqa: N802
223
- """Move the cursor up a specified amount of lines (Defaults to 1)."""
224
- return f"{CSI}{count}A"
225
-
226
- @staticmethod
227
- def DOWN(count: int = 1) -> str: # noqa: N802
228
- """Move the cursor down a specified amount of lines (Defaults to 1)."""
229
- return f"{CSI}{count}B"
230
-
231
- @staticmethod
232
- def FORWARD(count: int = 1) -> str: # noqa: N802
233
- """Move the cursor forward a specified amount of lines (Defaults to 1)."""
234
- return f"{CSI}{count}C"
235
-
236
- @staticmethod
237
- def BACK(count: int = 1) -> str: # noqa: N802
238
- """Move the cursor back a specified amount of lines (Defaults to 1)."""
239
- return f"{CSI}{count}D"
240
-
241
- @staticmethod
242
- def SET_POS(x: int, y: int) -> str: # noqa: N802
243
- """Set the cursor position to coordinates which are 1-based."""
244
- return f"{CSI}{y};{x}H"
245
-
246
-
247
- class TextStyle(AnsiSequence, Enum):
248
- """Create text style ANSI sequences."""
249
-
250
- # Resets all styles and colors of text
251
- RESET_ALL = 0
252
- ALT_RESET_ALL = ''
253
-
254
- INTENSITY_BOLD = 1
255
- INTENSITY_DIM = 2
256
- INTENSITY_NORMAL = 22
257
-
258
- ITALIC_ENABLE = 3
259
- ITALIC_DISABLE = 23
260
-
261
- OVERLINE_ENABLE = 53
262
- OVERLINE_DISABLE = 55
263
-
264
- STRIKETHROUGH_ENABLE = 9
265
- STRIKETHROUGH_DISABLE = 29
266
-
267
- UNDERLINE_ENABLE = 4
268
- UNDERLINE_DISABLE = 24
269
-
270
- def __str__(self) -> str:
271
- """Return ANSI text style sequence instead of enum name.
272
-
273
- This is helpful when using a TextStyle in an f-string or format() call
274
- e.g. my_str = f"{TextStyle.UNDERLINE_ENABLE}hello{TextStyle.UNDERLINE_DISABLE}".
275
- """
276
- return f"{CSI}{self.value}m"
277
-
278
-
279
- class Fg(FgColor, Enum):
280
- """Create ANSI sequences for the 16 standard terminal foreground text colors.
281
-
282
- A terminal's color settings affect how these colors appear.
283
- To reset any foreground color, use Fg.RESET.
284
- """
285
-
286
- BLACK = 30
287
- RED = 31
288
- GREEN = 32
289
- YELLOW = 33
290
- BLUE = 34
291
- MAGENTA = 35
292
- CYAN = 36
293
- LIGHT_GRAY = 37
294
- DARK_GRAY = 90
295
- LIGHT_RED = 91
296
- LIGHT_GREEN = 92
297
- LIGHT_YELLOW = 93
298
- LIGHT_BLUE = 94
299
- LIGHT_MAGENTA = 95
300
- LIGHT_CYAN = 96
301
- WHITE = 97
302
-
303
- RESET = 39
304
-
305
- def __str__(self) -> str:
306
- """Return ANSI color sequence instead of enum name.
307
-
308
- This is helpful when using an Fg in an f-string or format() call
309
- e.g. my_str = f"{Fg.BLUE}hello{Fg.RESET}".
310
- """
311
- return f"{CSI}{self.value}m"
312
-
313
-
314
- class Bg(BgColor, Enum):
315
- """Create ANSI sequences for the 16 standard terminal background text colors.
316
-
317
- A terminal's color settings affect how these colors appear.
318
- To reset any background color, use Bg.RESET.
319
- """
320
-
321
- BLACK = 40
322
- RED = 41
323
- GREEN = 42
324
- YELLOW = 43
325
- BLUE = 44
326
- MAGENTA = 45
327
- CYAN = 46
328
- LIGHT_GRAY = 47
329
- DARK_GRAY = 100
330
- LIGHT_RED = 101
331
- LIGHT_GREEN = 102
332
- LIGHT_YELLOW = 103
333
- LIGHT_BLUE = 104
334
- LIGHT_MAGENTA = 105
335
- LIGHT_CYAN = 106
336
- WHITE = 107
337
-
338
- RESET = 49
339
-
340
- def __str__(self) -> str:
341
- """Return ANSI color sequence instead of enum name.
342
-
343
- This is helpful when using a Bg in an f-string or format() call
344
- e.g. my_str = f"{Bg.BLACK}hello{Bg.RESET}".
345
- """
346
- return f"{CSI}{self.value}m"
347
-
348
-
349
- class EightBitFg(FgColor, Enum):
350
- """Create ANSI sequences for 8-bit terminal foreground text colors. Most terminals support 8-bit/256-color mode.
351
-
352
- The first 16 colors correspond to the 16 colors from Fg and behave the same way.
353
- To reset any foreground color, including 8-bit, use Fg.RESET.
354
- """
355
-
356
- BLACK = 0
357
- RED = 1
358
- GREEN = 2
359
- YELLOW = 3
360
- BLUE = 4
361
- MAGENTA = 5
362
- CYAN = 6
363
- LIGHT_GRAY = 7
364
- DARK_GRAY = 8
365
- LIGHT_RED = 9
366
- LIGHT_GREEN = 10
367
- LIGHT_YELLOW = 11
368
- LIGHT_BLUE = 12
369
- LIGHT_MAGENTA = 13
370
- LIGHT_CYAN = 14
371
- WHITE = 15
372
- GRAY_0 = 16
373
- NAVY_BLUE = 17
374
- DARK_BLUE = 18
375
- BLUE_3A = 19
376
- BLUE_3B = 20
377
- BLUE_1 = 21
378
- DARK_GREEN = 22
379
- DEEP_SKY_BLUE_4A = 23
380
- DEEP_SKY_BLUE_4B = 24
381
- DEEP_SKY_BLUE_4C = 25
382
- DODGER_BLUE_3 = 26
383
- DODGER_BLUE_2 = 27
384
- GREEN_4 = 28
385
- SPRING_GREEN_4 = 29
386
- TURQUOISE_4 = 30
387
- DEEP_SKY_BLUE_3A = 31
388
- DEEP_SKY_BLUE_3B = 32
389
- DODGER_BLUE_1 = 33
390
- GREEN_3A = 34
391
- SPRING_GREEN_3A = 35
392
- DARK_CYAN = 36
393
- LIGHT_SEA_GREEN = 37
394
- DEEP_SKY_BLUE_2 = 38
395
- DEEP_SKY_BLUE_1 = 39
396
- GREEN_3B = 40
397
- SPRING_GREEN_3B = 41
398
- SPRING_GREEN_2A = 42
399
- CYAN_3 = 43
400
- DARK_TURQUOISE = 44
401
- TURQUOISE_2 = 45
402
- GREEN_1 = 46
403
- SPRING_GREEN_2B = 47
404
- SPRING_GREEN_1 = 48
405
- MEDIUM_SPRING_GREEN = 49
406
- CYAN_2 = 50
407
- CYAN_1 = 51
408
- DARK_RED_1 = 52
409
- DEEP_PINK_4A = 53
410
- PURPLE_4A = 54
411
- PURPLE_4B = 55
412
- PURPLE_3 = 56
413
- BLUE_VIOLET = 57
414
- ORANGE_4A = 58
415
- GRAY_37 = 59
416
- MEDIUM_PURPLE_4 = 60
417
- SLATE_BLUE_3A = 61
418
- SLATE_BLUE_3B = 62
419
- ROYAL_BLUE_1 = 63
420
- CHARTREUSE_4 = 64
421
- DARK_SEA_GREEN_4A = 65
422
- PALE_TURQUOISE_4 = 66
423
- STEEL_BLUE = 67
424
- STEEL_BLUE_3 = 68
425
- CORNFLOWER_BLUE = 69
426
- CHARTREUSE_3A = 70
427
- DARK_SEA_GREEN_4B = 71
428
- CADET_BLUE_2 = 72
429
- CADET_BLUE_1 = 73
430
- SKY_BLUE_3 = 74
431
- STEEL_BLUE_1A = 75
432
- CHARTREUSE_3B = 76
433
- PALE_GREEN_3A = 77
434
- SEA_GREEN_3 = 78
435
- AQUAMARINE_3 = 79
436
- MEDIUM_TURQUOISE = 80
437
- STEEL_BLUE_1B = 81
438
- CHARTREUSE_2A = 82
439
- SEA_GREEN_2 = 83
440
- SEA_GREEN_1A = 84
441
- SEA_GREEN_1B = 85
442
- AQUAMARINE_1A = 86
443
- DARK_SLATE_GRAY_2 = 87
444
- DARK_RED_2 = 88
445
- DEEP_PINK_4B = 89
446
- DARK_MAGENTA_1 = 90
447
- DARK_MAGENTA_2 = 91
448
- DARK_VIOLET_1A = 92
449
- PURPLE_1A = 93
450
- ORANGE_4B = 94
451
- LIGHT_PINK_4 = 95
452
- PLUM_4 = 96
453
- MEDIUM_PURPLE_3A = 97
454
- MEDIUM_PURPLE_3B = 98
455
- SLATE_BLUE_1 = 99
456
- YELLOW_4A = 100
457
- WHEAT_4 = 101
458
- GRAY_53 = 102
459
- LIGHT_SLATE_GRAY = 103
460
- MEDIUM_PURPLE = 104
461
- LIGHT_SLATE_BLUE = 105
462
- YELLOW_4B = 106
463
- DARK_OLIVE_GREEN_3A = 107
464
- DARK_GREEN_SEA = 108
465
- LIGHT_SKY_BLUE_3A = 109
466
- LIGHT_SKY_BLUE_3B = 110
467
- SKY_BLUE_2 = 111
468
- CHARTREUSE_2B = 112
469
- DARK_OLIVE_GREEN_3B = 113
470
- PALE_GREEN_3B = 114
471
- DARK_SEA_GREEN_3A = 115
472
- DARK_SLATE_GRAY_3 = 116
473
- SKY_BLUE_1 = 117
474
- CHARTREUSE_1 = 118
475
- LIGHT_GREEN_2 = 119
476
- LIGHT_GREEN_3 = 120
477
- PALE_GREEN_1A = 121
478
- AQUAMARINE_1B = 122
479
- DARK_SLATE_GRAY_1 = 123
480
- RED_3A = 124
481
- DEEP_PINK_4C = 125
482
- MEDIUM_VIOLET_RED = 126
483
- MAGENTA_3A = 127
484
- DARK_VIOLET_1B = 128
485
- PURPLE_1B = 129
486
- DARK_ORANGE_3A = 130
487
- INDIAN_RED_1A = 131
488
- HOT_PINK_3A = 132
489
- MEDIUM_ORCHID_3 = 133
490
- MEDIUM_ORCHID = 134
491
- MEDIUM_PURPLE_2A = 135
492
- DARK_GOLDENROD = 136
493
- LIGHT_SALMON_3A = 137
494
- ROSY_BROWN = 138
495
- GRAY_63 = 139
496
- MEDIUM_PURPLE_2B = 140
497
- MEDIUM_PURPLE_1 = 141
498
- GOLD_3A = 142
499
- DARK_KHAKI = 143
500
- NAVAJO_WHITE_3 = 144
501
- GRAY_69 = 145
502
- LIGHT_STEEL_BLUE_3 = 146
503
- LIGHT_STEEL_BLUE = 147
504
- YELLOW_3A = 148
505
- DARK_OLIVE_GREEN_3 = 149
506
- DARK_SEA_GREEN_3B = 150
507
- DARK_SEA_GREEN_2 = 151
508
- LIGHT_CYAN_3 = 152
509
- LIGHT_SKY_BLUE_1 = 153
510
- GREEN_YELLOW = 154
511
- DARK_OLIVE_GREEN_2 = 155
512
- PALE_GREEN_1B = 156
513
- DARK_SEA_GREEN_5B = 157
514
- DARK_SEA_GREEN_5A = 158
515
- PALE_TURQUOISE_1 = 159
516
- RED_3B = 160
517
- DEEP_PINK_3A = 161
518
- DEEP_PINK_3B = 162
519
- MAGENTA_3B = 163
520
- MAGENTA_3C = 164
521
- MAGENTA_2A = 165
522
- DARK_ORANGE_3B = 166
523
- INDIAN_RED_1B = 167
524
- HOT_PINK_3B = 168
525
- HOT_PINK_2 = 169
526
- ORCHID = 170
527
- MEDIUM_ORCHID_1A = 171
528
- ORANGE_3 = 172
529
- LIGHT_SALMON_3B = 173
530
- LIGHT_PINK_3 = 174
531
- PINK_3 = 175
532
- PLUM_3 = 176
533
- VIOLET = 177
534
- GOLD_3B = 178
535
- LIGHT_GOLDENROD_3 = 179
536
- TAN = 180
537
- MISTY_ROSE_3 = 181
538
- THISTLE_3 = 182
539
- PLUM_2 = 183
540
- YELLOW_3B = 184
541
- KHAKI_3 = 185
542
- LIGHT_GOLDENROD_2A = 186
543
- LIGHT_YELLOW_3 = 187
544
- GRAY_84 = 188
545
- LIGHT_STEEL_BLUE_1 = 189
546
- YELLOW_2 = 190
547
- DARK_OLIVE_GREEN_1A = 191
548
- DARK_OLIVE_GREEN_1B = 192
549
- DARK_SEA_GREEN_1 = 193
550
- HONEYDEW_2 = 194
551
- LIGHT_CYAN_1 = 195
552
- RED_1 = 196
553
- DEEP_PINK_2 = 197
554
- DEEP_PINK_1A = 198
555
- DEEP_PINK_1B = 199
556
- MAGENTA_2B = 200
557
- MAGENTA_1 = 201
558
- ORANGE_RED_1 = 202
559
- INDIAN_RED_1C = 203
560
- INDIAN_RED_1D = 204
561
- HOT_PINK_1A = 205
562
- HOT_PINK_1B = 206
563
- MEDIUM_ORCHID_1B = 207
564
- DARK_ORANGE = 208
565
- SALMON_1 = 209
566
- LIGHT_CORAL = 210
567
- PALE_VIOLET_RED_1 = 211
568
- ORCHID_2 = 212
569
- ORCHID_1 = 213
570
- ORANGE_1 = 214
571
- SANDY_BROWN = 215
572
- LIGHT_SALMON_1 = 216
573
- LIGHT_PINK_1 = 217
574
- PINK_1 = 218
575
- PLUM_1 = 219
576
- GOLD_1 = 220
577
- LIGHT_GOLDENROD_2B = 221
578
- LIGHT_GOLDENROD_2C = 222
579
- NAVAJO_WHITE_1 = 223
580
- MISTY_ROSE1 = 224
581
- THISTLE_1 = 225
582
- YELLOW_1 = 226
583
- LIGHT_GOLDENROD_1 = 227
584
- KHAKI_1 = 228
585
- WHEAT_1 = 229
586
- CORNSILK_1 = 230
587
- GRAY_100 = 231
588
- GRAY_3 = 232
589
- GRAY_7 = 233
590
- GRAY_11 = 234
591
- GRAY_15 = 235
592
- GRAY_19 = 236
593
- GRAY_23 = 237
594
- GRAY_27 = 238
595
- GRAY_30 = 239
596
- GRAY_35 = 240
597
- GRAY_39 = 241
598
- GRAY_42 = 242
599
- GRAY_46 = 243
600
- GRAY_50 = 244
601
- GRAY_54 = 245
602
- GRAY_58 = 246
603
- GRAY_62 = 247
604
- GRAY_66 = 248
605
- GRAY_70 = 249
606
- GRAY_74 = 250
607
- GRAY_78 = 251
608
- GRAY_82 = 252
609
- GRAY_85 = 253
610
- GRAY_89 = 254
611
- GRAY_93 = 255
612
-
613
- def __str__(self) -> str:
614
- """Return ANSI color sequence instead of enum name.
615
-
616
- This is helpful when using an EightBitFg in an f-string or format() call
617
- e.g. my_str = f"{EightBitFg.SLATE_BLUE_1}hello{Fg.RESET}".
618
- """
619
- return f"{CSI}38;5;{self.value}m"
620
-
621
-
622
- class EightBitBg(BgColor, Enum):
623
- """Create ANSI sequences for 8-bit terminal background text colors. Most terminals support 8-bit/256-color mode.
624
-
625
- The first 16 colors correspond to the 16 colors from Bg and behave the same way.
626
- To reset any background color, including 8-bit, use Bg.RESET.
627
- """
628
-
629
- BLACK = 0
630
- RED = 1
631
- GREEN = 2
632
- YELLOW = 3
633
- BLUE = 4
634
- MAGENTA = 5
635
- CYAN = 6
636
- LIGHT_GRAY = 7
637
- DARK_GRAY = 8
638
- LIGHT_RED = 9
639
- LIGHT_GREEN = 10
640
- LIGHT_YELLOW = 11
641
- LIGHT_BLUE = 12
642
- LIGHT_MAGENTA = 13
643
- LIGHT_CYAN = 14
644
- WHITE = 15
645
- GRAY_0 = 16
646
- NAVY_BLUE = 17
647
- DARK_BLUE = 18
648
- BLUE_3A = 19
649
- BLUE_3B = 20
650
- BLUE_1 = 21
651
- DARK_GREEN = 22
652
- DEEP_SKY_BLUE_4A = 23
653
- DEEP_SKY_BLUE_4B = 24
654
- DEEP_SKY_BLUE_4C = 25
655
- DODGER_BLUE_3 = 26
656
- DODGER_BLUE_2 = 27
657
- GREEN_4 = 28
658
- SPRING_GREEN_4 = 29
659
- TURQUOISE_4 = 30
660
- DEEP_SKY_BLUE_3A = 31
661
- DEEP_SKY_BLUE_3B = 32
662
- DODGER_BLUE_1 = 33
663
- GREEN_3A = 34
664
- SPRING_GREEN_3A = 35
665
- DARK_CYAN = 36
666
- LIGHT_SEA_GREEN = 37
667
- DEEP_SKY_BLUE_2 = 38
668
- DEEP_SKY_BLUE_1 = 39
669
- GREEN_3B = 40
670
- SPRING_GREEN_3B = 41
671
- SPRING_GREEN_2A = 42
672
- CYAN_3 = 43
673
- DARK_TURQUOISE = 44
674
- TURQUOISE_2 = 45
675
- GREEN_1 = 46
676
- SPRING_GREEN_2B = 47
677
- SPRING_GREEN_1 = 48
678
- MEDIUM_SPRING_GREEN = 49
679
- CYAN_2 = 50
680
- CYAN_1 = 51
681
- DARK_RED_1 = 52
682
- DEEP_PINK_4A = 53
683
- PURPLE_4A = 54
684
- PURPLE_4B = 55
685
- PURPLE_3 = 56
686
- BLUE_VIOLET = 57
687
- ORANGE_4A = 58
688
- GRAY_37 = 59
689
- MEDIUM_PURPLE_4 = 60
690
- SLATE_BLUE_3A = 61
691
- SLATE_BLUE_3B = 62
692
- ROYAL_BLUE_1 = 63
693
- CHARTREUSE_4 = 64
694
- DARK_SEA_GREEN_4A = 65
695
- PALE_TURQUOISE_4 = 66
696
- STEEL_BLUE = 67
697
- STEEL_BLUE_3 = 68
698
- CORNFLOWER_BLUE = 69
699
- CHARTREUSE_3A = 70
700
- DARK_SEA_GREEN_4B = 71
701
- CADET_BLUE_2 = 72
702
- CADET_BLUE_1 = 73
703
- SKY_BLUE_3 = 74
704
- STEEL_BLUE_1A = 75
705
- CHARTREUSE_3B = 76
706
- PALE_GREEN_3A = 77
707
- SEA_GREEN_3 = 78
708
- AQUAMARINE_3 = 79
709
- MEDIUM_TURQUOISE = 80
710
- STEEL_BLUE_1B = 81
711
- CHARTREUSE_2A = 82
712
- SEA_GREEN_2 = 83
713
- SEA_GREEN_1A = 84
714
- SEA_GREEN_1B = 85
715
- AQUAMARINE_1A = 86
716
- DARK_SLATE_GRAY_2 = 87
717
- DARK_RED_2 = 88
718
- DEEP_PINK_4B = 89
719
- DARK_MAGENTA_1 = 90
720
- DARK_MAGENTA_2 = 91
721
- DARK_VIOLET_1A = 92
722
- PURPLE_1A = 93
723
- ORANGE_4B = 94
724
- LIGHT_PINK_4 = 95
725
- PLUM_4 = 96
726
- MEDIUM_PURPLE_3A = 97
727
- MEDIUM_PURPLE_3B = 98
728
- SLATE_BLUE_1 = 99
729
- YELLOW_4A = 100
730
- WHEAT_4 = 101
731
- GRAY_53 = 102
732
- LIGHT_SLATE_GRAY = 103
733
- MEDIUM_PURPLE = 104
734
- LIGHT_SLATE_BLUE = 105
735
- YELLOW_4B = 106
736
- DARK_OLIVE_GREEN_3A = 107
737
- DARK_GREEN_SEA = 108
738
- LIGHT_SKY_BLUE_3A = 109
739
- LIGHT_SKY_BLUE_3B = 110
740
- SKY_BLUE_2 = 111
741
- CHARTREUSE_2B = 112
742
- DARK_OLIVE_GREEN_3B = 113
743
- PALE_GREEN_3B = 114
744
- DARK_SEA_GREEN_3A = 115
745
- DARK_SLATE_GRAY_3 = 116
746
- SKY_BLUE_1 = 117
747
- CHARTREUSE_1 = 118
748
- LIGHT_GREEN_2 = 119
749
- LIGHT_GREEN_3 = 120
750
- PALE_GREEN_1A = 121
751
- AQUAMARINE_1B = 122
752
- DARK_SLATE_GRAY_1 = 123
753
- RED_3A = 124
754
- DEEP_PINK_4C = 125
755
- MEDIUM_VIOLET_RED = 126
756
- MAGENTA_3A = 127
757
- DARK_VIOLET_1B = 128
758
- PURPLE_1B = 129
759
- DARK_ORANGE_3A = 130
760
- INDIAN_RED_1A = 131
761
- HOT_PINK_3A = 132
762
- MEDIUM_ORCHID_3 = 133
763
- MEDIUM_ORCHID = 134
764
- MEDIUM_PURPLE_2A = 135
765
- DARK_GOLDENROD = 136
766
- LIGHT_SALMON_3A = 137
767
- ROSY_BROWN = 138
768
- GRAY_63 = 139
769
- MEDIUM_PURPLE_2B = 140
770
- MEDIUM_PURPLE_1 = 141
771
- GOLD_3A = 142
772
- DARK_KHAKI = 143
773
- NAVAJO_WHITE_3 = 144
774
- GRAY_69 = 145
775
- LIGHT_STEEL_BLUE_3 = 146
776
- LIGHT_STEEL_BLUE = 147
777
- YELLOW_3A = 148
778
- DARK_OLIVE_GREEN_3 = 149
779
- DARK_SEA_GREEN_3B = 150
780
- DARK_SEA_GREEN_2 = 151
781
- LIGHT_CYAN_3 = 152
782
- LIGHT_SKY_BLUE_1 = 153
783
- GREEN_YELLOW = 154
784
- DARK_OLIVE_GREEN_2 = 155
785
- PALE_GREEN_1B = 156
786
- DARK_SEA_GREEN_5B = 157
787
- DARK_SEA_GREEN_5A = 158
788
- PALE_TURQUOISE_1 = 159
789
- RED_3B = 160
790
- DEEP_PINK_3A = 161
791
- DEEP_PINK_3B = 162
792
- MAGENTA_3B = 163
793
- MAGENTA_3C = 164
794
- MAGENTA_2A = 165
795
- DARK_ORANGE_3B = 166
796
- INDIAN_RED_1B = 167
797
- HOT_PINK_3B = 168
798
- HOT_PINK_2 = 169
799
- ORCHID = 170
800
- MEDIUM_ORCHID_1A = 171
801
- ORANGE_3 = 172
802
- LIGHT_SALMON_3B = 173
803
- LIGHT_PINK_3 = 174
804
- PINK_3 = 175
805
- PLUM_3 = 176
806
- VIOLET = 177
807
- GOLD_3B = 178
808
- LIGHT_GOLDENROD_3 = 179
809
- TAN = 180
810
- MISTY_ROSE_3 = 181
811
- THISTLE_3 = 182
812
- PLUM_2 = 183
813
- YELLOW_3B = 184
814
- KHAKI_3 = 185
815
- LIGHT_GOLDENROD_2A = 186
816
- LIGHT_YELLOW_3 = 187
817
- GRAY_84 = 188
818
- LIGHT_STEEL_BLUE_1 = 189
819
- YELLOW_2 = 190
820
- DARK_OLIVE_GREEN_1A = 191
821
- DARK_OLIVE_GREEN_1B = 192
822
- DARK_SEA_GREEN_1 = 193
823
- HONEYDEW_2 = 194
824
- LIGHT_CYAN_1 = 195
825
- RED_1 = 196
826
- DEEP_PINK_2 = 197
827
- DEEP_PINK_1A = 198
828
- DEEP_PINK_1B = 199
829
- MAGENTA_2B = 200
830
- MAGENTA_1 = 201
831
- ORANGE_RED_1 = 202
832
- INDIAN_RED_1C = 203
833
- INDIAN_RED_1D = 204
834
- HOT_PINK_1A = 205
835
- HOT_PINK_1B = 206
836
- MEDIUM_ORCHID_1B = 207
837
- DARK_ORANGE = 208
838
- SALMON_1 = 209
839
- LIGHT_CORAL = 210
840
- PALE_VIOLET_RED_1 = 211
841
- ORCHID_2 = 212
842
- ORCHID_1 = 213
843
- ORANGE_1 = 214
844
- SANDY_BROWN = 215
845
- LIGHT_SALMON_1 = 216
846
- LIGHT_PINK_1 = 217
847
- PINK_1 = 218
848
- PLUM_1 = 219
849
- GOLD_1 = 220
850
- LIGHT_GOLDENROD_2B = 221
851
- LIGHT_GOLDENROD_2C = 222
852
- NAVAJO_WHITE_1 = 223
853
- MISTY_ROSE1 = 224
854
- THISTLE_1 = 225
855
- YELLOW_1 = 226
856
- LIGHT_GOLDENROD_1 = 227
857
- KHAKI_1 = 228
858
- WHEAT_1 = 229
859
- CORNSILK_1 = 230
860
- GRAY_100 = 231
861
- GRAY_3 = 232
862
- GRAY_7 = 233
863
- GRAY_11 = 234
864
- GRAY_15 = 235
865
- GRAY_19 = 236
866
- GRAY_23 = 237
867
- GRAY_27 = 238
868
- GRAY_30 = 239
869
- GRAY_35 = 240
870
- GRAY_39 = 241
871
- GRAY_42 = 242
872
- GRAY_46 = 243
873
- GRAY_50 = 244
874
- GRAY_54 = 245
875
- GRAY_58 = 246
876
- GRAY_62 = 247
877
- GRAY_66 = 248
878
- GRAY_70 = 249
879
- GRAY_74 = 250
880
- GRAY_78 = 251
881
- GRAY_82 = 252
882
- GRAY_85 = 253
883
- GRAY_89 = 254
884
- GRAY_93 = 255
885
-
886
- def __str__(self) -> str:
887
- """Return ANSI color sequence instead of enum name.
888
-
889
- This is helpful when using an EightBitBg in an f-string or format() call
890
- e.g. my_str = f"{EightBitBg.KHAKI_3}hello{Bg.RESET}".
891
- """
892
- return f"{CSI}48;5;{self.value}m"
893
-
894
-
895
- class RgbFg(FgColor):
896
- """Create ANSI sequences for 24-bit (RGB) terminal foreground text colors. The terminal must support 24-bit/true-color.
897
-
898
- To reset any foreground color, including 24-bit, use Fg.RESET.
899
- """
900
-
901
- def __init__(self, r: int, g: int, b: int) -> None:
902
- """RgbFg initializer.
903
-
904
- :param r: integer from 0-255 for the red component of the color
905
- :param g: integer from 0-255 for the green component of the color
906
- :param b: integer from 0-255 for the blue component of the color
907
- :raises ValueError: if r, g, or b is not in the range 0-255
908
- """
909
- if any(c < 0 or c > 255 for c in [r, g, b]):
910
- raise ValueError("RGB values must be integers in the range of 0 to 255")
911
-
912
- self._sequence = f"{CSI}38;2;{r};{g};{b}m"
913
-
914
- def __str__(self) -> str:
915
- """Return ANSI color sequence instead of enum name.
916
-
917
- This is helpful when using an RgbFg in an f-string or format() call
918
- e.g. my_str = f"{RgbFg(0, 55, 100)}hello{Fg.RESET}".
919
- """
920
- return self._sequence
921
-
922
-
923
- class RgbBg(BgColor):
924
- """Create ANSI sequences for 24-bit (RGB) terminal background text colors. The terminal must support 24-bit/true-color.
925
-
926
- To reset any background color, including 24-bit, use Bg.RESET.
927
- """
928
-
929
- def __init__(self, r: int, g: int, b: int) -> None:
930
- """RgbBg initializer.
931
-
932
- :param r: integer from 0-255 for the red component of the color
933
- :param g: integer from 0-255 for the green component of the color
934
- :param b: integer from 0-255 for the blue component of the color
935
- :raises ValueError: if r, g, or b is not in the range 0-255
936
- """
937
- if any(c < 0 or c > 255 for c in [r, g, b]):
938
- raise ValueError("RGB values must be integers in the range of 0 to 255")
939
-
940
- self._sequence = f"{CSI}48;2;{r};{g};{b}m"
941
-
942
- def __str__(self) -> str:
943
- """Return ANSI color sequence instead of enum name.
944
-
945
- This is helpful when using an RgbBg in an f-string or format() call
946
- e.g. my_str = f"{RgbBg(100, 255, 27)}hello{Bg.RESET}".
947
- """
948
- return self._sequence
949
-
950
-
951
- def style(
952
- value: Any,
953
- *,
954
- fg: Optional[FgColor] = None,
955
- bg: Optional[BgColor] = None,
956
- bold: Optional[bool] = None,
957
- dim: Optional[bool] = None,
958
- italic: Optional[bool] = None,
959
- overline: Optional[bool] = None,
960
- strikethrough: Optional[bool] = None,
961
- underline: Optional[bool] = None,
962
- ) -> str:
963
- """Apply ANSI colors and/or styles to a string and return it.
964
-
965
- The styling is self contained which means that at the end of the string reset code(s) are issued
966
- to undo whatever styling was done at the beginning.
967
-
968
- :param value: object whose text is to be styled
969
- :param fg: foreground color provided as any subclass of FgColor (e.g. Fg, EightBitFg, RgbFg)
970
- Defaults to no color.
971
- :param bg: foreground color provided as any subclass of BgColor (e.g. Bg, EightBitBg, RgbBg)
972
- Defaults to no color.
973
- :param bold: apply the bold style if True. Defaults to False.
974
- :param dim: apply the dim style if True. Defaults to False.
975
- :param italic: apply the italic style if True. Defaults to False.
976
- :param overline: apply the overline style if True. Defaults to False.
977
- :param strikethrough: apply the strikethrough style if True. Defaults to False.
978
- :param underline: apply the underline style if True. Defaults to False.
979
- :raises TypeError: if fg isn't None or a subclass of FgColor
980
- :raises TypeError: if bg isn't None or a subclass of BgColor
981
- :return: the stylized string
982
- """
983
- # list of strings that add style
984
- additions: list[AnsiSequence] = []
985
-
986
- # list of strings that remove style
987
- removals: list[AnsiSequence] = []
988
-
989
- # Process the style settings
990
- if fg is not None:
991
- if not isinstance(fg, FgColor):
992
- raise TypeError("fg must be a subclass of FgColor")
993
- additions.append(fg)
994
- removals.append(Fg.RESET)
995
-
996
- if bg is not None:
997
- if not isinstance(bg, BgColor):
998
- raise TypeError("bg must a subclass of BgColor")
999
- additions.append(bg)
1000
- removals.append(Bg.RESET)
1001
-
1002
- if bold:
1003
- additions.append(TextStyle.INTENSITY_BOLD)
1004
- removals.append(TextStyle.INTENSITY_NORMAL)
1005
-
1006
- if dim:
1007
- additions.append(TextStyle.INTENSITY_DIM)
1008
- removals.append(TextStyle.INTENSITY_NORMAL)
1009
-
1010
- if italic:
1011
- additions.append(TextStyle.ITALIC_ENABLE)
1012
- removals.append(TextStyle.ITALIC_DISABLE)
1013
-
1014
- if overline:
1015
- additions.append(TextStyle.OVERLINE_ENABLE)
1016
- removals.append(TextStyle.OVERLINE_DISABLE)
1017
-
1018
- if strikethrough:
1019
- additions.append(TextStyle.STRIKETHROUGH_ENABLE)
1020
- removals.append(TextStyle.STRIKETHROUGH_DISABLE)
1021
-
1022
- if underline:
1023
- additions.append(TextStyle.UNDERLINE_ENABLE)
1024
- removals.append(TextStyle.UNDERLINE_DISABLE)
1025
-
1026
- # Combine the ANSI style sequences with the value's text
1027
- return "".join(map(str, additions)) + str(value) + "".join(map(str, removals))
1028
-
1029
-
1030
- # Default styles for printing strings of various types.
1031
- # These can be altered to suit an application's needs and only need to be a
1032
- # function with the following structure: func(str) -> str
1033
- style_success = functools.partial(style, fg=Fg.GREEN)
1034
- """Partial function supplying arguments to [cmd2.ansi.style][] which colors text to signify success"""
1035
-
1036
- style_warning = functools.partial(style, fg=Fg.LIGHT_YELLOW)
1037
- """Partial function supplying arguments to [cmd2.ansi.style][] which colors text to signify a warning"""
1038
-
1039
- style_error = functools.partial(style, fg=Fg.LIGHT_RED)
1040
- """Partial function supplying arguments to [cmd2.ansi.style][] which colors text to signify an error"""
1041
-
1042
-
1043
- def async_alert_str(*, terminal_columns: int, prompt: str, line: str, cursor_offset: int, alert_msg: str) -> str:
1044
- """Calculate the desired string, including ANSI escape codes, for displaying an asynchronous alert message.
1045
-
1046
- :param terminal_columns: terminal width (number of columns)
1047
- :param prompt: current onscreen prompt
1048
- :param line: current contents of the Readline line buffer
1049
- :param cursor_offset: the offset of the current cursor position within line
1050
- :param alert_msg: the message to display to the user
1051
- :return: the correct string so that the alert message appears to the user to be printed above the current line.
1052
- """
1053
- # Split the prompt lines since it can contain newline characters.
1054
- prompt_lines = prompt.splitlines() or ['']
1055
-
1056
- # Calculate how many terminal lines are taken up by all prompt lines except for the last one.
1057
- # That will be included in the input lines calculations since that is where the cursor is.
1058
- num_prompt_terminal_lines = 0
1059
- for prompt_line in prompt_lines[:-1]:
1060
- prompt_line_width = style_aware_wcswidth(prompt_line)
1061
- num_prompt_terminal_lines += int(prompt_line_width / terminal_columns) + 1
1062
-
1063
- # Now calculate how many terminal lines are take up by the input
1064
- last_prompt_line = prompt_lines[-1]
1065
- last_prompt_line_width = style_aware_wcswidth(last_prompt_line)
1066
-
1067
- input_width = last_prompt_line_width + style_aware_wcswidth(line)
1068
-
1069
- num_input_terminal_lines = int(input_width / terminal_columns) + 1
1070
-
1071
- # Get the cursor's offset from the beginning of the first input line
1072
- cursor_input_offset = last_prompt_line_width + cursor_offset
1073
-
1074
- # Calculate what input line the cursor is on
1075
- cursor_input_line = int(cursor_input_offset / terminal_columns) + 1
1076
-
1077
- # Create a string that when printed will clear all input lines and display the alert
1078
- terminal_str = ''
1079
-
1080
- # Move the cursor down to the last input line
1081
- if cursor_input_line != num_input_terminal_lines:
1082
- terminal_str += Cursor.DOWN(num_input_terminal_lines - cursor_input_line)
1083
-
1084
- # Clear each line from the bottom up so that the cursor ends up on the first prompt line
1085
- total_lines = num_prompt_terminal_lines + num_input_terminal_lines
1086
- terminal_str += (clear_line() + Cursor.UP(1)) * (total_lines - 1)
1087
-
1088
- # Clear the first prompt line
1089
- terminal_str += clear_line()
1090
-
1091
- # Move the cursor to the beginning of the first prompt line and print the alert
1092
- terminal_str += '\r' + alert_msg
1093
- return terminal_str