From 508194744b987d03e965aeb4f07061a7d9a74501 Mon Sep 17 00:00:00 2001 From: Todd Leonhardt Date: Wed, 20 Aug 2025 23:37:54 -0400 Subject: [PATCH 1/5] Add a simple example to demonstrate the colors available in cmd2.Color --- examples/color.py | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100755 examples/color.py diff --git a/examples/color.py b/examples/color.py new file mode 100755 index 000000000..03801f227 --- /dev/null +++ b/examples/color.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python +"""A sample application for cmd2. Demonstrating colors available in the cmd2.colors.Color enum. + +Execute the taste_the_rainbow command to see the colors available. +""" + +from rich.style import Style + +import cmd2 +from cmd2.colors import Color + + +class CmdLineApp(cmd2.Cmd): + """Example cmd2 application demonstrating colorized output.""" + + def __init__(self) -> None: + # Set include_ipy to True to enable the "ipy" command which runs an interactive IPython shell + super().__init__(include_ipy=True) + self.intro = 'Run the taste_the_rainbow command to see all of the colors available to you in cmd2.' + + rainbow_parser = cmd2.Cmd2ArgumentParser() + rainbow_parser.add_argument('-b', '--background', action='store_true', help='Show background colors as well') + + @cmd2.with_argparser(rainbow_parser) + def do_taste_the_rainbow(self, args) -> None: + """Show all of the colors available within cmd2's Color StrEnum class.""" + + for color_member in Color: + style = Style(bgcolor=color_member.value) if args.background else Style(color=color_member.value) + self.poutput(f"{color_member.name}", style=style) + + +if __name__ == '__main__': + import sys + + c = CmdLineApp() + sys.exit(c.cmdloop()) From a211fdf5690183a7151ad2b584cb5f6f13615e61 Mon Sep 17 00:00:00 2001 From: Todd Leonhardt Date: Wed, 20 Aug 2025 23:49:08 -0400 Subject: [PATCH 2/5] Fix visual appearance when printing background colors --- examples/color.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/color.py b/examples/color.py index 03801f227..2e60db765 100755 --- a/examples/color.py +++ b/examples/color.py @@ -27,7 +27,7 @@ def do_taste_the_rainbow(self, args) -> None: for color_member in Color: style = Style(bgcolor=color_member.value) if args.background else Style(color=color_member.value) - self.poutput(f"{color_member.name}", style=style) + self.poutput(f"{color_member.name}", style=style, soft_wrap=False) if __name__ == '__main__': From 44d82edec2e1f753b643ff33b194bdbfd6bc59f7 Mon Sep 17 00:00:00 2001 From: Todd Leonhardt Date: Wed, 20 Aug 2025 23:59:12 -0400 Subject: [PATCH 3/5] Deleted old examples/colors.py and updated documentation --- docs/features/completion.md | 3 +- examples/README.md | 4 +- examples/colors.py | 89 ------------------------------------- 3 files changed, 3 insertions(+), 93 deletions(-) delete mode 100755 examples/colors.py diff --git a/docs/features/completion.md b/docs/features/completion.md index 47ba9d07e..3d08bf87a 100644 --- a/docs/features/completion.md +++ b/docs/features/completion.md @@ -96,8 +96,7 @@ Tab completion of argument values can be configured by using one of three parame - `completer` See the [arg_decorators](https://github.com/python-cmd2/cmd2/blob/main/examples/arg_decorators.py) -or [colors](https://github.com/python-cmd2/cmd2/blob/main/examples/colors.py) example for a -demonstration of how to use the `choices` parameter. See the +example for a demonstration of how to use the `choices` parameter. See the [argparse_completion](https://github.com/python-cmd2/cmd2/blob/main/examples/argparse_completion.py) example for a demonstration of how to use the `choices_provider` parameter. See the [arg_decorators](https://github.com/python-cmd2/cmd2/blob/main/examples/arg_decorators.py) or diff --git a/examples/README.md b/examples/README.md index 67bd42781..aad2072b1 100644 --- a/examples/README.md +++ b/examples/README.md @@ -32,8 +32,8 @@ each: - Show how to enable custom tab completion by assigning a completer function to `do_*` commands - [cmd2_as_argument.py](https://github.com/python-cmd2/cmd2/blob/main/examples/cmd_as_argument.py) - Demonstrates how to accept and parse command-line arguments when invoking a cmd2 application -- [colors.py](https://github.com/python-cmd2/cmd2/blob/main/examples/colors.py) - - Show various ways of using colorized output within a cmd2 application +- [color.py](https://github.com/python-cmd2/cmd2/blob/main/examples/color.py) + - Show the numerous colors available to use in your cmd2 applications - [custom_parser.py](https://github.com/python-cmd2/cmd2/blob/main/examples/custom_parser.py) - Demonstrates how to create your own custom `Cmd2ArgumentParser` - [decorator_example.py](https://github.com/python-cmd2/cmd2/blob/main/examples/decorator_example.py) diff --git a/examples/colors.py b/examples/colors.py deleted file mode 100755 index fad3c9586..000000000 --- a/examples/colors.py +++ /dev/null @@ -1,89 +0,0 @@ -#!/usr/bin/env python -"""A sample application for cmd2. Demonstrating colorized output. - -Experiment with the command line options on the `speak` command to see how -different output colors ca - -The allow_style setting has three possible values: - -Never - poutput(), pfeedback(), and ppaged() strip all ANSI style sequences - which instruct the terminal to colorize output - -Terminal - (the default value) poutput(), pfeedback(), and ppaged() do not strip any - ANSI style sequences when the output is a terminal, but if the output is - a pipe or a file the style sequences are stripped. If you want colorized - output, add ANSI style sequences using cmd2's internal ansi module. - -Always - poutput(), pfeedback(), and ppaged() never strip ANSI style sequences, - regardless of the output destination -""" - -import cmd2 -from cmd2 import ( - Bg, - Fg, - ansi, -) - -fg_choices = [c.name.lower() for c in Fg] -bg_choices = [c.name.lower() for c in Bg] - - -class CmdLineApp(cmd2.Cmd): - """Example cmd2 application demonstrating colorized output.""" - - def __init__(self) -> None: - # Set include_ipy to True to enable the "ipy" command which runs an interactive IPython shell - super().__init__(include_ipy=True) - - self.maxrepeats = 3 - # Make maxrepeats settable at runtime - self.add_settable(cmd2.Settable('maxrepeats', int, 'max repetitions for speak command', self)) - - # Should ANSI color output be allowed - self.allow_style = ansi.AllowStyle.TERMINAL - - speak_parser = cmd2.Cmd2ArgumentParser() - speak_parser.add_argument('-p', '--piglatin', action='store_true', help='atinLay') - speak_parser.add_argument('-s', '--shout', action='store_true', help='N00B EMULATION MODE') - speak_parser.add_argument('-r', '--repeat', type=int, help='output [n] times') - speak_parser.add_argument('-f', '--fg', choices=fg_choices, help='foreground color to apply to output') - speak_parser.add_argument('-b', '--bg', choices=bg_choices, help='background color to apply to output') - speak_parser.add_argument('-l', '--bold', action='store_true', help='bold the output') - speak_parser.add_argument('-u', '--underline', action='store_true', help='underline the output') - speak_parser.add_argument('words', nargs='+', help='words to say') - - @cmd2.with_argparser(speak_parser) - def do_speak(self, args) -> None: - """Repeats what you tell me to.""" - words = [] - for word in args.words: - if args.piglatin: - word = f'{word[1:]}{word[0]}ay' - if args.shout: - word = word.upper() - words.append(word) - - repetitions = args.repeat or 1 - - fg_color = Fg[args.fg.upper()] if args.fg else None - bg_color = Bg[args.bg.upper()] if args.bg else None - output_str = ansi.style(' '.join(words), fg=fg_color, bg=bg_color, bold=args.bold, underline=args.underline) - - for _ in range(min(repetitions, self.maxrepeats)): - # .poutput handles newlines, and accommodates output redirection too - self.poutput(output_str) - - def do_timetravel(self, _) -> None: - """A command which always generates an error message, to demonstrate custom error colors.""" - self.perror('Mr. Fusion failed to start. Could not energize flux capacitor.') - - -if __name__ == '__main__': - import sys - - c = CmdLineApp() - sys.exit(c.cmdloop()) From 38927240542bc7622d1362240b8200e4e3ca6e54 Mon Sep 17 00:00:00 2001 From: Kevin Van Brunt Date: Thu, 21 Aug 2025 01:21:51 -0400 Subject: [PATCH 4/5] Simplified color example. --- examples/color.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/examples/color.py b/examples/color.py index 2e60db765..cc6e107de 100755 --- a/examples/color.py +++ b/examples/color.py @@ -4,10 +4,15 @@ Execute the taste_the_rainbow command to see the colors available. """ +import argparse + from rich.style import Style import cmd2 -from cmd2.colors import Color +from cmd2 import ( + Color, + stylize, +) class CmdLineApp(cmd2.Cmd): @@ -19,15 +24,16 @@ def __init__(self) -> None: self.intro = 'Run the taste_the_rainbow command to see all of the colors available to you in cmd2.' rainbow_parser = cmd2.Cmd2ArgumentParser() - rainbow_parser.add_argument('-b', '--background', action='store_true', help='Show background colors as well') + rainbow_parser.add_argument('-b', '--background', action='store_true', help='show background colors as well') @cmd2.with_argparser(rainbow_parser) - def do_taste_the_rainbow(self, args) -> None: + def do_taste_the_rainbow(self, args: argparse.Namespace) -> None: """Show all of the colors available within cmd2's Color StrEnum class.""" for color_member in Color: - style = Style(bgcolor=color_member.value) if args.background else Style(color=color_member.value) - self.poutput(f"{color_member.name}", style=style, soft_wrap=False) + style = Style(bgcolor=color_member) if args.background else Style(color=color_member) + styled_name = stylize(color_member.name, style=style) + self.poutput(styled_name) if __name__ == '__main__': From 0aad810f7d2d5e45427b45fc4417b1f110940177 Mon Sep 17 00:00:00 2001 From: Todd Leonhardt Date: Thu, 21 Aug 2025 09:00:06 -0400 Subject: [PATCH 5/5] Added argument to optionally display using a pager --- examples/color.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/examples/color.py b/examples/color.py index cc6e107de..c9cd65b26 100755 --- a/examples/color.py +++ b/examples/color.py @@ -25,15 +25,23 @@ def __init__(self) -> None: rainbow_parser = cmd2.Cmd2ArgumentParser() rainbow_parser.add_argument('-b', '--background', action='store_true', help='show background colors as well') + rainbow_parser.add_argument('-p', '--paged', action='store_true', help='display output using a pager') @cmd2.with_argparser(rainbow_parser) def do_taste_the_rainbow(self, args: argparse.Namespace) -> None: """Show all of the colors available within cmd2's Color StrEnum class.""" + color_names = [] for color_member in Color: style = Style(bgcolor=color_member) if args.background else Style(color=color_member) styled_name = stylize(color_member.name, style=style) - self.poutput(styled_name) + if args.paged: + color_names.append(styled_name) + else: + self.poutput(styled_name) + + if args.paged: + self.ppaged('\n'.join(color_names)) if __name__ == '__main__':