From abdc9121dde63e9c37e50b6fa77924887a7aa4e5 Mon Sep 17 00:00:00 2001 From: Todd Leonhardt Date: Sat, 30 Aug 2025 13:17:44 -0400 Subject: [PATCH 1/9] Draft example for setting a theme --- examples/rich_theme.py | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100755 examples/rich_theme.py diff --git a/examples/rich_theme.py b/examples/rich_theme.py new file mode 100755 index 000000000..9923cf4b1 --- /dev/null +++ b/examples/rich_theme.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python3 +"""A simple example of setting a custom theme for a cmd2 application.""" + +from rich.style import Style + +import cmd2 +import cmd2.rich_utils as ru +from cmd2 import Cmd2Style, Color + + +class ThemedApp(cmd2.Cmd): + """A simple cmd2 application with a custom theme.""" + + def __init__(self, *args, **kwargs): + """Initialize the application.""" + super().__init__(*args, **kwargs) + self.intro = "This is a themed application. Try the 'theme_show' command." + + # Create a custom theme + custom_theme = { + Cmd2Style.SUCCESS: Style(color=Color.CYAN), + Cmd2Style.WARNING: Style(color=Color.MAGENTA), + Cmd2Style.ERROR: Style(color=Color.BRIGHT_RED), + "argparse.args": Style(color=Color.AQUAMARINE3, underline=True), + "inspect.attr": Style(color=Color.DARK_GOLDENROD, bold=True), + } + ru.set_theme(custom_theme) + + @cmd2.with_category("Theme Commands") + def do_theme_show(self, _: cmd2.Statement): + """Showcases the custom theme by printing messages with different styles.""" + self.poutput("This is a basic output message.") + self.psuccess("This is a success message.") + self.warning("This is a warning message.") + self.error("This is an error message.") + + +if __name__ == "__main__": + import sys + + app = ThemedApp() + sys.exit(app.cmdloop()) From 6d9dba9aa4e62c5fb9a808bc12d2902deae12f4d Mon Sep 17 00:00:00 2001 From: Todd Leonhardt Date: Sat, 30 Aug 2025 13:22:38 -0400 Subject: [PATCH 2/9] Fix typos --- examples/rich_theme.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/rich_theme.py b/examples/rich_theme.py index 9923cf4b1..9be4d2b58 100755 --- a/examples/rich_theme.py +++ b/examples/rich_theme.py @@ -31,8 +31,8 @@ def do_theme_show(self, _: cmd2.Statement): """Showcases the custom theme by printing messages with different styles.""" self.poutput("This is a basic output message.") self.psuccess("This is a success message.") - self.warning("This is a warning message.") - self.error("This is an error message.") + self.pwarning("This is a warning message.") + self.perror("This is an error message.") if __name__ == "__main__": From 06c2fe183fd7c40c988935465573902cf6caf59b Mon Sep 17 00:00:00 2001 From: Todd Leonhardt Date: Sat, 30 Aug 2025 13:45:50 -0400 Subject: [PATCH 3/9] Add some more elements to the custom theme --- examples/rich_theme.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/examples/rich_theme.py b/examples/rich_theme.py index 9be4d2b58..4560753a0 100755 --- a/examples/rich_theme.py +++ b/examples/rich_theme.py @@ -21,6 +21,9 @@ def __init__(self, *args, **kwargs): Cmd2Style.SUCCESS: Style(color=Color.CYAN), Cmd2Style.WARNING: Style(color=Color.MAGENTA), Cmd2Style.ERROR: Style(color=Color.BRIGHT_RED), + Cmd2Style.HELP_HEADER: Style(color=Color.YELLOW), + Cmd2Style.HELP_LEADER: Style(color=Color.PURPLE), + Cmd2Style.TABLE_BORDER: Style(color=Color.BLUE), "argparse.args": Style(color=Color.AQUAMARINE3, underline=True), "inspect.attr": Style(color=Color.DARK_GOLDENROD, bold=True), } From 7ea367ef7029e2e565ab9299db93ad698968a5d1 Mon Sep 17 00:00:00 2001 From: Todd Leonhardt Date: Sat, 30 Aug 2025 13:58:45 -0400 Subject: [PATCH 4/9] Added in a custom self.doc_leader --- examples/rich_theme.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/examples/rich_theme.py b/examples/rich_theme.py index 4560753a0..088b9cd1d 100755 --- a/examples/rich_theme.py +++ b/examples/rich_theme.py @@ -16,14 +16,17 @@ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.intro = "This is a themed application. Try the 'theme_show' command." + # Set text which prints right before all of the help tables are listed. + self.doc_leader = "Welcome to this glorious help ..." + # Create a custom theme custom_theme = { Cmd2Style.SUCCESS: Style(color=Color.CYAN), Cmd2Style.WARNING: Style(color=Color.MAGENTA), Cmd2Style.ERROR: Style(color=Color.BRIGHT_RED), Cmd2Style.HELP_HEADER: Style(color=Color.YELLOW), - Cmd2Style.HELP_LEADER: Style(color=Color.PURPLE), - Cmd2Style.TABLE_BORDER: Style(color=Color.BLUE), + Cmd2Style.HELP_LEADER: Style(color=Color.VIOLET), + Cmd2Style.TABLE_BORDER: Style(color=Color.LIGHT_SKY_BLUE1), "argparse.args": Style(color=Color.AQUAMARINE3, underline=True), "inspect.attr": Style(color=Color.DARK_GOLDENROD, bold=True), } From 09600a27f10826eaccbd9dead766a33736754d21 Mon Sep 17 00:00:00 2001 From: Todd Leonhardt Date: Sat, 30 Aug 2025 14:03:46 -0400 Subject: [PATCH 5/9] Add in setting background color for one style to make it discoverable that this is an option --- examples/rich_theme.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/rich_theme.py b/examples/rich_theme.py index 088b9cd1d..fbde48763 100755 --- a/examples/rich_theme.py +++ b/examples/rich_theme.py @@ -25,7 +25,7 @@ def __init__(self, *args, **kwargs): Cmd2Style.WARNING: Style(color=Color.MAGENTA), Cmd2Style.ERROR: Style(color=Color.BRIGHT_RED), Cmd2Style.HELP_HEADER: Style(color=Color.YELLOW), - Cmd2Style.HELP_LEADER: Style(color=Color.VIOLET), + Cmd2Style.HELP_LEADER: Style(color=Color.DARK_VIOLET, bgcolor=Color.BRIGHT_WHITE), Cmd2Style.TABLE_BORDER: Style(color=Color.LIGHT_SKY_BLUE1), "argparse.args": Style(color=Color.AQUAMARINE3, underline=True), "inspect.attr": Style(color=Color.DARK_GOLDENROD, bold=True), From 4c96b03f9aa2a83545b49beb430db0d54009f3e2 Mon Sep 17 00:00:00 2001 From: Todd Leonhardt Date: Sat, 30 Aug 2025 14:41:49 -0400 Subject: [PATCH 6/9] Change some styles to show off different options --- examples/rich_theme.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/examples/rich_theme.py b/examples/rich_theme.py index fbde48763..a886c0fc3 100755 --- a/examples/rich_theme.py +++ b/examples/rich_theme.py @@ -21,11 +21,11 @@ def __init__(self, *args, **kwargs): # Create a custom theme custom_theme = { - Cmd2Style.SUCCESS: Style(color=Color.CYAN), - Cmd2Style.WARNING: Style(color=Color.MAGENTA), - Cmd2Style.ERROR: Style(color=Color.BRIGHT_RED), - Cmd2Style.HELP_HEADER: Style(color=Color.YELLOW), - Cmd2Style.HELP_LEADER: Style(color=Color.DARK_VIOLET, bgcolor=Color.BRIGHT_WHITE), + Cmd2Style.SUCCESS: Style(color=Color.GREEN), + Cmd2Style.WARNING: Style(color=Color.ORANGE1), + Cmd2Style.ERROR: Style(color=Color.PINK1), + Cmd2Style.HELP_HEADER: Style(color=Color.CYAN, bgcolor="#44475a"), + Cmd2Style.HELP_LEADER: Style(color="#f8f8f2", bgcolor="#282a36"), Cmd2Style.TABLE_BORDER: Style(color=Color.LIGHT_SKY_BLUE1), "argparse.args": Style(color=Color.AQUAMARINE3, underline=True), "inspect.attr": Style(color=Color.DARK_GOLDENROD, bold=True), @@ -35,10 +35,12 @@ def __init__(self, *args, **kwargs): @cmd2.with_category("Theme Commands") def do_theme_show(self, _: cmd2.Statement): """Showcases the custom theme by printing messages with different styles.""" + # NOTE: Using soft_wrap=False will ensure display looks correct when background colors are part of the style self.poutput("This is a basic output message.") - self.psuccess("This is a success message.") - self.pwarning("This is a warning message.") - self.perror("This is an error message.") + self.psuccess("This is a success message.", soft_wrap=False) + self.pwarning("This is a warning message.", soft_wrap=False) + self.perror("This is an error message.", soft_wrap=False) + self.pexcept(ValueError("This is a dummy ValueError exception.")) if __name__ == "__main__": From 37c5b93671b04f8e47e7a8bbae65d0f97a04400f Mon Sep 17 00:00:00 2001 From: Todd Leonhardt Date: Sat, 30 Aug 2025 14:54:01 -0400 Subject: [PATCH 7/9] Add comments about how colors can be defined --- examples/rich_theme.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/examples/rich_theme.py b/examples/rich_theme.py index a886c0fc3..d35d70029 100755 --- a/examples/rich_theme.py +++ b/examples/rich_theme.py @@ -20,13 +20,15 @@ def __init__(self, *args, **kwargs): self.doc_leader = "Welcome to this glorious help ..." # Create a custom theme + # Colors can come from the cmd2.color.Color StrEnum class, be RGB hex values, or + # be any of the rich standard colors: https://rich.readthedocs.io/en/stable/appendix/colors.html custom_theme = { - Cmd2Style.SUCCESS: Style(color=Color.GREEN), + Cmd2Style.SUCCESS: Style(color=Color.GREEN), # Use color from cmd2 Color class Cmd2Style.WARNING: Style(color=Color.ORANGE1), Cmd2Style.ERROR: Style(color=Color.PINK1), Cmd2Style.HELP_HEADER: Style(color=Color.CYAN, bgcolor="#44475a"), - Cmd2Style.HELP_LEADER: Style(color="#f8f8f2", bgcolor="#282a36"), - Cmd2Style.TABLE_BORDER: Style(color=Color.LIGHT_SKY_BLUE1), + Cmd2Style.HELP_LEADER: Style(color="#f8f8f2", bgcolor="#282a36"), # use RGX hex colors + Cmd2Style.TABLE_BORDER: Style(color="turquoise2"), # use a rich standard color "argparse.args": Style(color=Color.AQUAMARINE3, underline=True), "inspect.attr": Style(color=Color.DARK_GOLDENROD, bold=True), } From 4adaf0d76a599904064c5145c4d9ccb658f7ae01 Mon Sep 17 00:00:00 2001 From: Todd Leonhardt Date: Sat, 30 Aug 2025 14:57:51 -0400 Subject: [PATCH 8/9] Fix typo --- examples/rich_theme.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/rich_theme.py b/examples/rich_theme.py index d35d70029..df512b346 100755 --- a/examples/rich_theme.py +++ b/examples/rich_theme.py @@ -27,7 +27,7 @@ def __init__(self, *args, **kwargs): Cmd2Style.WARNING: Style(color=Color.ORANGE1), Cmd2Style.ERROR: Style(color=Color.PINK1), Cmd2Style.HELP_HEADER: Style(color=Color.CYAN, bgcolor="#44475a"), - Cmd2Style.HELP_LEADER: Style(color="#f8f8f2", bgcolor="#282a36"), # use RGX hex colors + Cmd2Style.HELP_LEADER: Style(color="#f8f8f2", bgcolor="#282a36"), # use RGB hex colors Cmd2Style.TABLE_BORDER: Style(color="turquoise2"), # use a rich standard color "argparse.args": Style(color=Color.AQUAMARINE3, underline=True), "inspect.attr": Style(color=Color.DARK_GOLDENROD, bold=True), From 2125b0071190a66c17379572084c0643ea059a17 Mon Sep 17 00:00:00 2001 From: Todd Leonhardt Date: Sat, 30 Aug 2025 16:07:05 -0400 Subject: [PATCH 9/9] Overrode "traceback.exc_type" --- examples/rich_theme.py | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/rich_theme.py b/examples/rich_theme.py index df512b346..e07dfdf9c 100755 --- a/examples/rich_theme.py +++ b/examples/rich_theme.py @@ -29,6 +29,7 @@ def __init__(self, *args, **kwargs): Cmd2Style.HELP_HEADER: Style(color=Color.CYAN, bgcolor="#44475a"), Cmd2Style.HELP_LEADER: Style(color="#f8f8f2", bgcolor="#282a36"), # use RGB hex colors Cmd2Style.TABLE_BORDER: Style(color="turquoise2"), # use a rich standard color + "traceback.exc_type": Style(color=Color.RED, bgcolor=Color.LIGHT_YELLOW3), "argparse.args": Style(color=Color.AQUAMARINE3, underline=True), "inspect.attr": Style(color=Color.DARK_GOLDENROD, bold=True), }