Skip to content

Commit 0038893

Browse files
committed
Added fg_lookup() and bg_lookup() two-stage color lookup functions
1 parent 2721f8a commit 0038893

File tree

2 files changed

+89
-28
lines changed

2 files changed

+89
-28
lines changed

cmd2/ansi.py

Lines changed: 63 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,7 @@
2121

2222
# Foreground color presets
2323
FG_COLORS = {
24-
'black': Fore.BLACK,
25-
'red': Fore.RED,
26-
'green': Fore.GREEN,
27-
'yellow': Fore.YELLOW,
28-
'blue': Fore.BLUE,
29-
'magenta': Fore.MAGENTA,
30-
'cyan': Fore.CYAN,
31-
'white': Fore.WHITE,
24+
'reset': Fore.RESET,
3225
'gray': Fore.LIGHTBLACK_EX,
3326
'lightred': Fore.LIGHTRED_EX,
3427
'lightblue': Fore.LIGHTBLUE_EX,
@@ -37,19 +30,20 @@
3730
'lightmagenta': Fore.LIGHTMAGENTA_EX,
3831
'lightcyan': Fore.LIGHTCYAN_EX,
3932
'lightwhite': Fore.LIGHTWHITE_EX,
40-
'reset': Fore.RESET,
33+
'bright_black': Fore.LIGHTBLACK_EX,
34+
'bright_red': Fore.LIGHTRED_EX,
35+
'bright_green': Fore.LIGHTGREEN_EX,
36+
'bright_yellow': Fore.LIGHTYELLOW_EX,
37+
'bright_blue': Fore.LIGHTBLUE_EX,
38+
'bright_magenta': Fore.LIGHTMAGENTA_EX,
39+
'bright_cyan': Fore.LIGHTCYAN_EX,
40+
'bright_white': Fore.LIGHTWHITE_EX,
4141
}
42+
FG_RESET = FG_COLORS['reset']
4243

4344
# Background color presets
4445
BG_COLORS = {
45-
'black': Back.BLACK,
46-
'red': Back.RED,
47-
'green': Back.GREEN,
48-
'yellow': Back.YELLOW,
49-
'blue': Back.BLUE,
50-
'magenta': Back.MAGENTA,
51-
'cyan': Back.CYAN,
52-
'white': Back.WHITE,
46+
'reset': Back.RESET,
5347
'gray': Back.LIGHTBLACK_EX,
5448
'lightred': Back.LIGHTRED_EX,
5549
'lightblue': Back.LIGHTBLUE_EX,
@@ -58,8 +52,16 @@
5852
'lightmagenta': Back.LIGHTMAGENTA_EX,
5953
'lightcyan': Back.LIGHTCYAN_EX,
6054
'lightwhite': Back.LIGHTWHITE_EX,
61-
'reset': Back.RESET,
55+
'bright_black': Back.LIGHTBLACK_EX,
56+
'bright_red': Back.LIGHTRED_EX,
57+
'bright_green': Back.LIGHTGREEN_EX,
58+
'bright_yellow': Back.LIGHTYELLOW_EX,
59+
'bright_blue': Back.LIGHTBLUE_EX,
60+
'bright_magenta': Back.LIGHTMAGENTA_EX,
61+
'bright_cyan': Back.LIGHTCYAN_EX,
62+
'bright_white': Back.LIGHTWHITE_EX,
6263
}
64+
BG_RESET = BG_COLORS['reset']
6365

6466
# ANSI escape sequences not provided by colorama
6567
UNDERLINE_ENABLE = colorama.ansi.code_to_chars(4)
@@ -99,6 +101,44 @@ def ansi_aware_write(fileobj: IO, msg: str) -> None:
99101
fileobj.write(msg)
100102

101103

104+
def fg_lookup(fg_name: str) -> str:
105+
"""Look up ANSI escape codes based on foreground color name.
106+
107+
This function first searches the FG_COLORS dictionary and then falls back to searching colorama.Fore.
108+
109+
:param fg_name: foreground color name to look up ANSI escape code(s) for
110+
:return: ANSI escape code(s) associated with this color
111+
:raises ValueError if the color cannot be found
112+
"""
113+
try:
114+
ansi_escape = FG_COLORS[fg_name.lower()]
115+
except KeyError:
116+
try:
117+
ansi_escape = getattr(Fore, fg_name.upper())
118+
except AttributeError:
119+
raise ValueError('Foreground color {!r} does not exist.'.format(fg_name))
120+
return ansi_escape
121+
122+
123+
def bg_lookup(bg_name: str) -> str:
124+
"""Look up ANSI escape codes based on background color name.
125+
126+
This function first searches the BG_COLORS dictionary and then falls back to searching colorama.Back.
127+
128+
:param bg_name: background color name to look up ANSI escape code(s) for
129+
:return: ANSI escape code(s) associated with this color
130+
:raises ValueError if the color cannot be found
131+
"""
132+
try:
133+
ansi_escape = BG_COLORS[bg_name.lower()]
134+
except KeyError:
135+
try:
136+
ansi_escape = getattr(Back, bg_name.upper())
137+
except AttributeError:
138+
raise ValueError('Background color {!r} does not exist.'.format(bg_name))
139+
return ansi_escape
140+
141+
102142
def style(text: Any, *, fg: str = '', bg: str = '', bold: bool = False, underline: bool = False) -> str:
103143
"""
104144
Applies styles to text
@@ -110,6 +150,7 @@ def style(text: Any, *, fg: str = '', bg: str = '', bold: bool = False, underlin
110150
:param underline: apply the underline style if True. Defaults to False.
111151
112152
:return: the stylized string
153+
:raises ValueError if fg or bg color does cannot be found
113154
"""
114155
# List of strings that add style
115156
additions = []
@@ -122,18 +163,12 @@ def style(text: Any, *, fg: str = '', bg: str = '', bold: bool = False, underlin
122163

123164
# Process the style settings
124165
if fg:
125-
try:
126-
additions.append(FG_COLORS[fg.lower()])
127-
removals.append(FG_COLORS['reset'])
128-
except KeyError:
129-
raise ValueError('Color {} does not exist.'.format(fg))
166+
additions.append(fg_lookup(fg))
167+
removals.append(FG_RESET)
130168

131169
if bg:
132-
try:
133-
additions.append(BG_COLORS[bg.lower()])
134-
removals.append(BG_COLORS['reset'])
135-
except KeyError:
136-
raise ValueError('Color {} does not exist.'.format(bg))
170+
additions.append(bg_lookup(bg))
171+
removals.append(BG_RESET)
137172

138173
if bold:
139174
additions.append(Style.BRIGHT)

tests/test_ansi.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,29 @@ def test_style_color_not_exist():
6969

7070
with pytest.raises(ValueError):
7171
ansi.style(base_str, fg='blue', bg='fake')
72+
73+
74+
def test_fg_lookup_dict():
75+
assert ansi.fg_lookup('gray') == Fore.LIGHTBLACK_EX
76+
77+
78+
def test_fg_lookup_colorama():
79+
assert ansi.fg_lookup('green') == Fore.GREEN
80+
81+
82+
def test_fg_lookup_nonexist():
83+
with pytest.raises(ValueError):
84+
ansi.fg_lookup('foo')
85+
86+
87+
def test_bg_lookup_dict():
88+
assert ansi.bg_lookup('gray') == Back.LIGHTBLACK_EX
89+
90+
91+
def test_bg_lookup_colorama():
92+
assert ansi.bg_lookup('green') == Back.GREEN
93+
94+
95+
def test_bg_lookup_nonexist():
96+
with pytest.raises(ValueError):
97+
ansi.bg_lookup('bar')

0 commit comments

Comments
 (0)