11"""Main ANSI Escape sequence class"""
22
3- from typing import Optional , Iterable
3+ from typing import Any , Dict , Iterable , Optional
44
5- __all__ = ('AnsiEscape' ,)
5+ __all__ = ('AnsiEscape' , 'escape_format' , )
66
7- _CLEAR = '\033 [0m'
7+ _CLEAR : str = '\033 [0m'
88
99
1010class AnsiEscape :
@@ -20,13 +20,60 @@ def __str__(self) -> str:
2020
2121 return ''
2222
23- def __or__ (self , other ) :
23+ def __or__ (self , other : Any ) -> 'AnsiEscape' :
2424 if isinstance (other , AnsiEscape ):
2525 self .sequence += other .sequence
2626 return self
2727
2828 self .string = str (other )
2929 return self
3030
31- def __ror__ (self , other ) :
31+ def __ror__ (self , other : Any ) -> 'AnsiEscape' :
3232 return self .__or__ (other )
33+
34+
35+ def escape_format (string : str , escape_map : Dict [str , AnsiEscape ], case_sensitive : bool = False ) -> str :
36+ """
37+ Maps a dictionary of substrings => escape sequences to the given string,
38+ returning a new string with the sequences applied to all
39+ found substrings.
40+
41+ Example:
42+
43+ COLOURS = {
44+ 'red': esc.FRED,
45+ 'green': esc.FGREEN,
46+ 'yellow': esc.FYELLOW,
47+ 'blue': esc.FBLUE,
48+ 'magenta': esc.FMAGENTA,
49+ 'cyan': esc.FCYAN,
50+ 'white': esc.FWHITE,
51+ 'black': esc.FBLACK,
52+ }
53+
54+ text = \" \" \" Hello, red world! The sun is bright yellow, and the sky cyan blue.
55+ Green, lush fields are all around us.\" \" \"
56+
57+ print(escape_format(text, COLOURS)) # Would print all mapped words in their respective colours
58+
59+ Inspired by: https://www.reddit.com/r/learnpython/comments/rvcg0l/print_colour_in_terminal/hr73v3f/
60+ """
61+
62+ lines = string .splitlines ()
63+ for line_idx , line in enumerate (lines ):
64+
65+ words = line .split (' ' )
66+ for substring , escape in escape_map .items ():
67+
68+ for idx , word in enumerate (words ):
69+
70+ if not case_sensitive :
71+ substring = substring .lower ()
72+ word = word .lower ()
73+
74+ if word .startswith (substring ):
75+ words [idx ] = f'{ escape | word [:len (substring )]} { word [len (substring ):]} '
76+
77+ lines [line_idx ] = ' ' .join (words )
78+
79+ return '\n ' .join (lines )
0 commit comments