Skip to content

Commit a02e688

Browse files
committed
Cmd2Lexer colors are now part of the cmd2 rich theme
1 parent 77fea2f commit a02e688

4 files changed

Lines changed: 58 additions & 30 deletions

File tree

cmd2/pt_utils.py

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
)
2929
from . import rich_utils as ru
3030
from . import string_utils as su
31+
from .styles import Cmd2Style
3132

3233
if TYPE_CHECKING: # pragma: no cover
3334
from rich.color import Color
@@ -259,28 +260,21 @@ class Cmd2Lexer(Lexer):
259260
def __init__(
260261
self,
261262
cmd_app: "Cmd",
262-
command_color: str = "ansigreen",
263-
alias_color: str = "ansicyan",
264-
macro_color: str = "ansimagenta",
265-
flag_color: str = "ansired",
266-
argument_color: str = "ansiyellow",
267263
) -> None:
268264
"""Initialize the Lexer.
269265
270266
:param cmd_app: cmd2.Cmd instance
271-
:param command_color: color to use for commands, defaults to 'ansigreen'
272-
:param alias_color: color to use for aliases, defaults to 'ansicyan'
273-
:param macro_color: color to use for macros, defaults to 'ansimagenta'
274-
:param flag_color: color to use for flags, defaults to 'ansired'
275-
:param argument_color: color to use for arguments, defaults to 'ansiyellow'
276267
"""
277268
super().__init__()
278269
self.cmd_app = cmd_app
279-
self.command_color = command_color
280-
self.alias_color = alias_color
281-
self.macro_color = macro_color
282-
self.flag_color = flag_color
283-
self.argument_color = argument_color
270+
271+
# Retrieve styles dynamically from the current theme
272+
theme = ru.get_theme()
273+
self.command_color = rich_to_pt_style(theme.styles.get(Cmd2Style.LEXER_COMMAND, ""))
274+
self.alias_color = rich_to_pt_style(theme.styles.get(Cmd2Style.LEXER_ALIAS, ""))
275+
self.macro_color = rich_to_pt_style(theme.styles.get(Cmd2Style.LEXER_MACRO, ""))
276+
self.flag_color = rich_to_pt_style(theme.styles.get(Cmd2Style.LEXER_FLAG, ""))
277+
self.argument_color = rich_to_pt_style(theme.styles.get(Cmd2Style.LEXER_ARGUMENT, ""))
284278

285279
def lex_document(self, document: Document) -> Callable[[int], Any]:
286280
"""Lex the document."""

cmd2/styles.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,11 @@ class Cmd2Style(StrEnum):
5656
ERROR = "cmd2.error" # Error text (used by perror())
5757
HELP_HEADER = "cmd2.help.header" # Help table header text
5858
HELP_LEADER = "cmd2.help.leader" # Text right before the help tables are listed
59+
LEXER_COMMAND = "cmd2.lexer.command" # Lexer color for commands
60+
LEXER_ALIAS = "cmd2.lexer.alias" # Lexer color for aliases
61+
LEXER_MACRO = "cmd2.lexer.macro" # Lexer color for macros
62+
LEXER_FLAG = "cmd2.lexer.flag" # Lexer color for flags
63+
LEXER_ARGUMENT = "cmd2.lexer.argument" # Lexer color for arguments
5964
SUCCESS = "cmd2.success" # Success text (used by psuccess())
6065
TABLE_BORDER = "cmd2.table_border" # Applied to cmd2's table borders
6166
WARNING = "cmd2.warning" # Warning text (used by pwarning())
@@ -70,6 +75,11 @@ class Cmd2Style(StrEnum):
7075
Cmd2Style.ERROR: Style(color=Color.BRIGHT_RED),
7176
Cmd2Style.HELP_HEADER: Style(color=Color.BRIGHT_GREEN),
7277
Cmd2Style.HELP_LEADER: Style(color=Color.CYAN),
78+
Cmd2Style.LEXER_COMMAND: Style(color=Color.GREEN),
79+
Cmd2Style.LEXER_ALIAS: Style(color=Color.CYAN),
80+
Cmd2Style.LEXER_MACRO: Style(color=Color.MAGENTA),
81+
Cmd2Style.LEXER_FLAG: Style(color=Color.RED),
82+
Cmd2Style.LEXER_ARGUMENT: Style(color=Color.YELLOW),
7383
Cmd2Style.SUCCESS: Style(color=Color.GREEN),
7484
Cmd2Style.TABLE_BORDER: Style(color=Color.BRIGHT_GREEN),
7585
Cmd2Style.WARNING: Style(color=Color.BRIGHT_YELLOW),

examples/rich_theme.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,13 @@ def __init__(self, *args, **kwargs):
2929
Cmd2Style.HELP_HEADER: Style(color=Color.CYAN, bgcolor="#44475a"),
3030
Cmd2Style.HELP_LEADER: Style(color="#f8f8f2", bgcolor="#282a36"), # use RGB hex colors
3131
Cmd2Style.TABLE_BORDER: Style(color="turquoise2"), # use a rich standard color
32+
Cmd2Style.LEXER_COMMAND: Style(color=Color.LIGHT_GREEN),
33+
Cmd2Style.LEXER_ALIAS: Style(color=Color.LIGHT_CYAN1),
34+
Cmd2Style.LEXER_MACRO: Style(color=Color.LIGHT_CORAL),
35+
Cmd2Style.LEXER_FLAG: Style(color=Color.LIGHT_PINK3),
36+
Cmd2Style.LEXER_ARGUMENT: Style(color=Color.LIGHT_GOLDENROD1),
37+
Cmd2Style.COMPLETION_MENU_ITEM: Style(color=Color.WHITE, bgcolor=Color.NAVY_BLUE),
38+
Cmd2Style.COMPLETION_MENU_META: Style(color=Color.WHITE, bgcolor=Color.DARK_SLATE_GRAY2),
3239
"traceback.exc_type": Style(color=Color.RED, bgcolor=Color.LIGHT_YELLOW3, bold=True),
3340
"argparse.args": Style(color=Color.AQUAMARINE3, underline=True),
3441
}

tests/test_pt_utils.py

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,11 @@ def test_lex_document_command(self, mock_cmd_app):
116116
get_line = lexer.lex_document(document)
117117
tokens = get_line(0)
118118

119-
assert tokens == [("ansigreen", "help"), ("", " "), ("ansiyellow", "something")]
119+
assert tokens == [
120+
("noreverse fg:ansigreen bg:default", "help"),
121+
("", " "),
122+
("noreverse fg:ansiyellow bg:default", "something"),
123+
]
120124

121125
def test_lex_document_alias(self, mock_cmd_app):
122126
"""Test lexing an alias."""
@@ -128,7 +132,7 @@ def test_lex_document_alias(self, mock_cmd_app):
128132
get_line = lexer.lex_document(document)
129133
tokens = get_line(0)
130134

131-
assert tokens == [("ansicyan", "ls"), ("", " "), ("ansired", "-l")]
135+
assert tokens == [("noreverse fg:ansicyan bg:default", "ls"), ("", " "), ("noreverse fg:ansired bg:default", "-l")]
132136

133137
def test_lex_document_macro(self, mock_cmd_app):
134138
"""Test lexing a macro."""
@@ -140,7 +144,11 @@ def test_lex_document_macro(self, mock_cmd_app):
140144
get_line = lexer.lex_document(document)
141145
tokens = get_line(0)
142146

143-
assert tokens == [("ansimagenta", "my_macro"), ("", " "), ("ansiyellow", "arg1")]
147+
assert tokens == [
148+
("noreverse fg:ansimagenta bg:default", "my_macro"),
149+
("", " "),
150+
("noreverse fg:ansiyellow bg:default", "arg1"),
151+
]
144152

145153
def test_lex_document_leading_whitespace(self, mock_cmd_app):
146154
"""Test lexing with leading whitespace."""
@@ -152,7 +160,12 @@ def test_lex_document_leading_whitespace(self, mock_cmd_app):
152160
get_line = lexer.lex_document(document)
153161
tokens = get_line(0)
154162

155-
assert tokens == [("", " "), ("ansigreen", "help"), ("", " "), ("ansiyellow", "something")]
163+
assert tokens == [
164+
("", " "),
165+
("noreverse fg:ansigreen bg:default", "help"),
166+
("", " "),
167+
("noreverse fg:ansiyellow bg:default", "something"),
168+
]
156169

157170
def test_lex_document_unknown_command(self, mock_cmd_app):
158171
"""Test lexing an unknown command."""
@@ -163,7 +176,7 @@ def test_lex_document_unknown_command(self, mock_cmd_app):
163176
get_line = lexer.lex_document(document)
164177
tokens = get_line(0)
165178

166-
assert tokens == [("", "unknown"), ("", " "), ("ansiyellow", "command")]
179+
assert tokens == [("", "unknown"), ("", " "), ("noreverse fg:ansiyellow bg:default", "command")]
167180

168181
def test_lex_document_no_command(self, mock_cmd_app):
169182
"""Test lexing an empty line or line with only whitespace."""
@@ -200,17 +213,17 @@ def test_lex_document_arguments(self, mock_cmd_app):
200213
tokens = get_line(0)
201214

202215
assert tokens == [
203-
("ansigreen", "help"),
216+
("noreverse fg:ansigreen bg:default", "help"),
204217
("", " "),
205-
("ansired", "-v"),
218+
("noreverse fg:ansired bg:default", "-v"),
206219
("", " "),
207-
("ansired", "--name"),
220+
("noreverse fg:ansired bg:default", "--name"),
208221
("", " "),
209-
("ansiyellow", '"John Doe"'),
222+
("noreverse fg:ansiyellow bg:default", '"John Doe"'),
210223
("", " "),
211224
("", ">"),
212225
("", " "),
213-
("ansiyellow", "out.txt"),
226+
("noreverse fg:ansiyellow bg:default", "out.txt"),
214227
]
215228

216229
def test_lex_document_unclosed_quote(self, mock_cmd_app):
@@ -223,7 +236,11 @@ def test_lex_document_unclosed_quote(self, mock_cmd_app):
223236
get_line = lexer.lex_document(document)
224237
tokens = get_line(0)
225238

226-
assert tokens == [("ansigreen", "echo"), ("", " "), ("ansiyellow", '"hello')]
239+
assert tokens == [
240+
("noreverse fg:ansigreen bg:default", "echo"),
241+
("", " "),
242+
("noreverse fg:ansiyellow bg:default", '"hello'),
243+
]
227244

228245
def test_lex_document_shortcut(self, mock_cmd_app):
229246
"""Test lexing a shortcut."""
@@ -235,13 +252,13 @@ def test_lex_document_shortcut(self, mock_cmd_app):
235252
document = Document(line)
236253
get_line = lexer.lex_document(document)
237254
tokens = get_line(0)
238-
assert tokens == [("ansigreen", "!"), ("ansiyellow", "ls")]
255+
assert tokens == [("noreverse fg:ansigreen bg:default", "!"), ("noreverse fg:ansiyellow bg:default", "ls")]
239256

240257
line = "! ls"
241258
document = Document(line)
242259
get_line = lexer.lex_document(document)
243260
tokens = get_line(0)
244-
assert tokens == [("ansigreen", "!"), ("", " "), ("ansiyellow", "ls")]
261+
assert tokens == [("noreverse fg:ansigreen bg:default", "!"), ("", " "), ("noreverse fg:ansiyellow bg:default", "ls")]
245262

246263
def test_lex_document_multiline(self, mock_cmd_app):
247264
"""Test lexing a multiline command."""
@@ -255,11 +272,11 @@ def test_lex_document_multiline(self, mock_cmd_app):
255272

256273
# First line should have command
257274
tokens0 = get_line(0)
258-
assert tokens0 == [("ansigreen", "orate")]
275+
assert tokens0 == [("noreverse fg:ansigreen bg:default", "orate")]
259276

260277
# Second line should have argument (not command)
261278
tokens1 = get_line(1)
262-
assert tokens1 == [("ansiyellow", "help")]
279+
assert tokens1 == [("noreverse fg:ansiyellow bg:default", "help")]
263280

264281

265282
class TestCmd2Completer:

0 commit comments

Comments
 (0)