Skip to content

Commit c43d987

Browse files
Update examples (#1485)
* Updated color.py and argparse_completion.py examples for cmd2 3.0. * Added a table to a CompletionItem description in argparse_completion.py example. * Updated documentation for Cmd2Style. * Updated initialization.py and python_scripting.py examples for cmd2 3.0. Deleted basic.py and pirate.py examples. * Fix typo and slightly re-order a couple things in top-level README * Fix initialization.py example so it uses a valid startup script and delete redundant alias_startup.py example * Edit initialization.md to auto-load code from the initialization.py example instead of manually copying it by hand * Changed the example title to show examples/initialization.py to make it clearer * Merge redundant examples The following 4 examples all demonstrate various aspects of using `argparse` for command argument processing and have been merged into a single comprehensive example called `argparse_example.py`: - arg_decorators.py - decorator_example.py - arg_print.py - subcommands.py `first_app.py` and `initialization.py` had a lot of overlap in demonstrating basic features of cmd2. I combined them into a single `getting_started.py` example * Create a new command_sets.py example command_sets.py merges three previous examples: - modular_commands_basic.py - modular_commands_dynamic.py - modular_subcommands.py * Added type hints to argparse_example.py and fixed other ruff issues * Fixed comments in examples/command_sets.py * Fixed strings and types in getting_started.py --------- Co-authored-by: Kevin Van Brunt <[email protected]>
1 parent 5d49d55 commit c43d987

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+672
-1061
lines changed

.github/CODEOWNERS

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@
2727

2828
# cmd2 code
2929
cmd2/__init__.py @kmvanbrunt @tleonhardt
30-
cmd2/ansi.py @kmvanbrunt @tleonhardt
3130
cmd2/argparse_*.py @kmvanbrunt @anselor
3231
cmd2/clipboard.py @tleonhardt
3332
cmd2/cmd2.py @tleonhardt @kmvanbrunt
33+
cmd2/colors.py @tleonhardt @kmvanbrunt
3434
cmd2/command_definition.py @anselor
3535
cmd2/constants.py @tleonhardt @kmvanbrunt
3636
cmd2/decorators.py @kmvanbrunt @anselor
@@ -39,8 +39,11 @@ cmd2/history.py @tleonhardt
3939
cmd2/parsing.py @kmvanbrunt
4040
cmd2/plugin.py @anselor
4141
cmd2/py_bridge.py @kmvanbrunt
42+
cmd2/rich_utils.py @kmvanbrunt
4243
cmd2/rl_utils.py @kmvanbrunt
43-
cmd2/table_creator.py @kmvanbrunt
44+
cmd2/string_utils.py @kmvanbrunt
45+
cmd2/styles.py @tleonhardt @kmvanbrunt
46+
cmd2/terminal_utils.py @kmvanbrunt
4447
cmd2/transcript.py @tleonhardt
4548
cmd2/utils.py @tleonhardt @kmvanbrunt
4649

.github/CONTRIBUTING.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ uv venv --python 3.12
269269
Then you can run commands in this isolated virtual environment using `uv` like so:
270270

271271
```sh
272-
uv run examples/basic.py
272+
uv run examples/hello_cmd2.py
273273
```
274274

275275
Alternatively you can activate the virtual environment using the OS-specific command such as this on
@@ -329,7 +329,7 @@ environment is set up and working properly.
329329
You can also run the example app and see a prompt that says "(Cmd)" running the command:
330330

331331
```sh
332-
$ uv run examples/example.py
332+
$ uv run examples/getting_started.py
333333
```
334334

335335
You can type `help` to get help or `quit` to quit. If you see that, then congratulations – you're

README.md

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ menagerie of simple command line tools created by strangers on github and the gu
3939
Unfortunately, when CLIs become significantly complex the ease of command discoverability tends to
4040
fade quickly. On the other hand, Web and traditional desktop GUIs are first in class when it comes
4141
to easily discovering functionality. The price we pay for beautifully colored displays is complexity
42-
required to aggregate disperate applications into larger systems. `cmd2` fills the niche between
42+
required to aggregate disparate applications into larger systems. `cmd2` fills the niche between
4343
high [ease of command discovery](https://clig.dev/#ease-of-discovery) applications and smart
4444
workflow automation systems.
4545

@@ -105,20 +105,16 @@ examples.
105105

106106
## Tutorials
107107

108-
- PyOhio 2019 presentation:
109-
- [video](https://www.youtube.com/watch?v=pebeWrTqIIw)
110-
- [slides](https://github.com/python-cmd2/talks/blob/master/PyOhio_2019/cmd2-PyOhio_2019.pdf)
111-
- [example code](https://github.com/python-cmd2/talks/tree/master/PyOhio_2019/examples)
112-
- [Cookiecutter](https://github.com/cookiecutter/cookiecutter) Templates from community
113-
- Basic cookiecutter template for cmd2 application :
114-
https://github.com/jayrod/cookiecutter-python-cmd2
115-
- Advanced cookiecutter template with external plugin support :
116-
https://github.com/jayrod/cookiecutter-python-cmd2-ext-plug
117108
- [cmd2 example applications](https://github.com/python-cmd2/cmd2/tree/main/examples)
118109
- Basic cmd2 examples to demonstrate how to use various features
119110
- [Advanced Examples](https://github.com/jayrod/cmd2-example-apps)
120111
- More complex examples that demonstrate more featuers about how to put together a complete
121112
application
113+
- [Cookiecutter](https://github.com/cookiecutter/cookiecutter) Templates from community
114+
- Basic cookiecutter template for cmd2 application :
115+
https://github.com/jayrod/cookiecutter-python-cmd2
116+
- Advanced cookiecutter template with external plugin support :
117+
https://github.com/jayrod/cookiecutter-python-cmd2-ext-plug
122118

123119
## Hello World
124120

@@ -161,7 +157,6 @@ reproduce the bug. At a minimum, please state the following:
161157

162158
| Application Name | Description | Organization or Author |
163159
| --------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- |
164-
| [Pobshell](https://github.com/pdalloz/pobshell) | A Bash‑like shell for live Python objects: `cd`, `ls`, `cat`, `find` and _CLI piping_ for object code, str values & more | [Peter Dalloz](https://www.linkedin.com/in/pdalloz) |
165160
| [CephFS Shell](https://github.com/ceph/ceph) | The Ceph File System, or CephFS, is a POSIX-compliant file system built on top of Ceph’s distributed object store | [ceph](https://ceph.com/) |
166161
| [garak](https://github.com/NVIDIA/garak) | LLM vulnerability scanner that checks if an LLM can be made to fail in a way we don't want | [NVIDIA](https://github.com/NVIDIA) |
167162
| [medusa](https://github.com/Ch0pin/medusa) | Binary instrumentation framework that that automates processes for the dynamic analysis of Android and iOS Applications | [Ch0pin](https://github.com/Ch0pin) |
@@ -176,6 +171,7 @@ reproduce the bug. At a minimum, please state the following:
176171
| [tomcatmanager](https://github.com/tomcatmanager/tomcatmanager) | A command line tool and python library for managing a tomcat server | [tomcatmanager](https://github.com/tomcatmanager) |
177172
| [Falcon Toolkit](https://github.com/CrowdStrike/Falcon-Toolkit) | Unleash the power of the CrowdStrike Falcon Platform at the CLI | [CrowdStrike](https://github.com/CrowdStrike) |
178173
| [EXPLIoT](https://gitlab.com/expliot_framework/expliot) | Internet of Things Security Testing and Exploitation framework | [expliot_framework](https://gitlab.com/expliot_framework/) |
174+
| [Pobshell](https://github.com/pdalloz/pobshell) | A Bash‑like shell for live Python objects: `cd`, `ls`, `cat`, `find` and _CLI piping_ for object code, str values & more | [Peter Dalloz](https://www.linkedin.com/in/pdalloz) |
179175

180176
Possibly defunct but still good examples
181177

cmd2/cmd2.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
Settable environment parameters
1111
Parsing commands with `argparse` argument parsers (flags)
1212
Redirection to file or paste buffer (clipboard) with > or >>
13-
Easy transcript-based testing of applications (see examples/example.py)
13+
Easy transcript-based testing of applications (see examples/transcript_example.py)
1414
Bash-style ``select`` available
1515
1616
Note, if self.stdout is different than sys.stdout, then redirection with > and |

cmd2/transcript.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ class Cmd2TestCase(unittest.TestCase):
3434
that will execute the commands in a transcript file and expect the
3535
results shown.
3636
37-
See example.py
37+
See transcript_example.py
3838
"""
3939

4040
cmdapp: Optional['Cmd'] = None

docs/examples/first_app.md renamed to docs/examples/getting_started.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
# First Application
1+
# Getting Started
22

3-
Here's a quick walkthrough of a simple application which demonstrates 8 features of `cmd2`:
3+
Here's a quick walkthrough of a simple application which demonstrates 10 features of `cmd2`:
44

55
- [Settings](../features/settings.md)
66
- [Commands](../features/commands.md)
@@ -14,17 +14,17 @@ Here's a quick walkthrough of a simple application which demonstrates 8 features
1414
If you don't want to type as we go, here is the complete source (you can click to expand and then
1515
click the **Copy** button in the top-right):
1616

17-
??? example
17+
!!! example "getting_started.py"
1818

1919
```py
2020
{%
21-
include "../../examples/first_app.py"
21+
include "../../examples/getting_started.py"
2222
%}
2323
```
2424

2525
## Basic Application
2626

27-
First we need to create a new `cmd2` application. Create a new file `first_app.py` with the
27+
First we need to create a new `cmd2` application. Create a new file `getting_started.py` with the
2828
following contents:
2929

3030
```py
@@ -47,7 +47,7 @@ We have a new class `FirstApp` which is a subclass of [cmd2.Cmd][]. When we tell
4747
file like this:
4848

4949
```shell
50-
$ python first_app.py
50+
$ python getting_started.py
5151
```
5252

5353
it creates an instance of our class, and calls the `cmd2.Cmd.cmdloop` method. This method accepts
@@ -77,7 +77,7 @@ In that initializer, the first thing to do is to make sure we initialize `cmd2`.
7777
run the script, and enter the `set` command to see the settings, like this:
7878

7979
```shell
80-
$ python first_app.py
80+
$ python getting_started.py
8181
(Cmd) set
8282
```
8383

@@ -88,8 +88,8 @@ you will see our `maxrepeats` setting show up with it's default value of `3`.
8888
Now we will create our first command, called `speak` which will echo back whatever we tell it to
8989
say. We are going to use an [argument processor](../features/argument_processing.md) so the `speak`
9090
command can shout and talk piglatin. We will also use some built in methods for
91-
[generating output](../features/generating_output.md). Add this code to `first_app.py`, so that the
92-
`speak_parser` attribute and the `do_speak()` method are part of the `CmdLineApp()` class:
91+
[generating output](../features/generating_output.md). Add this code to `getting_started.py`, so
92+
that the `speak_parser` attribute and the `do_speak()` method are part of the `CmdLineApp()` class:
9393

9494
```py
9595
speak_parser = cmd2.Cmd2ArgumentParser()

docs/examples/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
<!--intro-start-->
44

5-
- [First Application](first_app.md)
5+
- [Getting Started](getting_started.md)
66
- [Alternate Event Loops](alternate_event_loops.md)
77
- [List of cmd2 examples](examples.md)
88

docs/features/argument_processing.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ following for you:
1414

1515
These features are all provided by the `@with_argparser` decorator which is importable from `cmd2`.
1616

17-
See the either the [argprint](https://github.com/python-cmd2/cmd2/blob/main/examples/arg_print.py)
18-
or [decorator](https://github.com/python-cmd2/cmd2/blob/main/examples/decorator_example.py) example
19-
to learn more about how to use the various `cmd2` argument processing decorators in your `cmd2`
20-
applications.
17+
See the
18+
[argparse_example](https://github.com/python-cmd2/cmd2/blob/main/examples/argparse_example.py)
19+
example to learn more about how to use the various `cmd2` argument processing decorators in your
20+
`cmd2` applications.
2121

2222
`cmd2` provides the following [decorators](../api/decorators.md) for assisting with parsing
2323
arguments passed to commands:
@@ -286,8 +286,9 @@ argparse sub-parsers.
286286
You may add multiple layers of subcommands for your command. `cmd2` will automatically traverse and
287287
tab complete subcommands for all commands using argparse.
288288

289-
See the [subcommands](https://github.com/python-cmd2/cmd2/blob/main/examples/subcommands.py) example
290-
to learn more about how to use subcommands in your `cmd2` application.
289+
See the
290+
[argparse_example](https://github.com/python-cmd2/cmd2/blob/main/examples/argparse_example.py)
291+
example to learn more about how to use subcommands in your `cmd2` application.
291292

292293
## Argparse Extensions
293294

docs/features/generating_output.md

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -126,21 +126,6 @@ you can pad it appropriately with spaces. However, there are categories of Unico
126126
occupy 2 cells, and other that occupy 0. To further complicate matters, you might have included ANSI
127127
escape sequences in the output to generate colors on the terminal.
128128

129-
The `cmd2.ansi.style_aware_wcswidth` function solves both of these problems. Pass it a string, and
129+
The `cmd2.string_utils.str_width` function solves both of these problems. Pass it a string, and
130130
regardless of which Unicode characters and ANSI text style escape sequences it contains, it will
131131
tell you how many characters on the screen that string will consume when printed.
132-
133-
## Pretty Printing Data Structures
134-
135-
The `cmd2.Cmd.ppretty` method is similar to the Python
136-
[pprint](https://docs.python.org/3/library/pprint.html) function from the standard `pprint` module.
137-
`cmd2.Cmd.pprint` adds the same conveniences as `cmd2.Cmd.poutput`.
138-
139-
This method provides a capability to “pretty-print” arbitrary Python data structures in a form which
140-
can be used as input to the interpreter and is easy for humans to read.
141-
142-
The formatted representation keeps objects on a single line if it can, and breaks them onto multiple
143-
lines if they don’t fit within the allowed width, adjustable by the width parameter defaulting to 80
144-
characters.
145-
146-
Dictionaries are sorted by key before the display is computed.

docs/features/initialization.md

Lines changed: 6 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -2,81 +2,13 @@
22

33
Here is a basic example `cmd2` application which demonstrates many capabilities which you may wish to utilize while initializing the app:
44

5-
```py
6-
#!/usr/bin/env python3
7-
# coding=utf-8
8-
"""A simple example cmd2 application demonstrating the following:
9-
1) Colorizing/stylizing output
10-
2) Using multiline commands
11-
3) Persistent history
12-
4) How to run an initialization script at startup
13-
5) How to group and categorize commands when displaying them in help
14-
6) Opting-in to using the ipy command to run an IPython shell
15-
7) Allowing access to your application in py and ipy
16-
8) Displaying an intro banner upon starting your application
17-
9) Using a custom prompt
18-
10) How to make custom attributes settable at runtime
19-
"""
20-
import cmd2
21-
from cmd2 import (
22-
Bg,
23-
Fg,
24-
style,
25-
)
5+
!!! example "examples/getting_started.py"
266

27-
28-
class BasicApp(cmd2.Cmd):
29-
CUSTOM_CATEGORY = 'My Custom Commands'
30-
31-
def __init__(self):
32-
super().__init__(
33-
multiline_commands=['echo'],
34-
persistent_history_file='cmd2_history.dat',
35-
startup_script='scripts/startup.txt',
36-
include_ipy=True,
37-
)
38-
39-
# Prints an intro banner once upon application startup
40-
self.intro = style('Welcome to cmd2!', fg=Fg.RED, bg=Bg.WHITE, bold=True)
41-
42-
# Show this as the prompt when asking for input
43-
self.prompt = 'myapp> '
44-
45-
# Used as prompt for multiline commands after the first line
46-
self.continuation_prompt = '... '
47-
48-
# Allow access to your application in py and ipy via self
49-
self.self_in_py = True
50-
51-
# Set the default category name
52-
self.default_category = 'cmd2 Built-in Commands'
53-
54-
# Color to output text in with echo command
55-
self.foreground_color = Fg.CYAN.name.lower()
56-
57-
# Make echo_fg settable at runtime
58-
fg_colors = [c.name.lower() for c in Fg]
59-
self.add_settable(
60-
cmd2.Settable('foreground_color', str, 'Foreground color to use with echo command', self,
61-
choices=fg_colors)
62-
)
63-
64-
@cmd2.with_category(CUSTOM_CATEGORY)
65-
def do_intro(self, _):
66-
"""Display the intro banner"""
67-
self.poutput(self.intro)
68-
69-
@cmd2.with_category(CUSTOM_CATEGORY)
70-
def do_echo(self, arg):
71-
"""Example of a multiline command"""
72-
fg_color = Fg[self.foreground_color.upper()]
73-
self.poutput(style(arg, fg=fg_color))
74-
75-
76-
if __name__ == '__main__':
77-
app = BasicApp()
78-
app.cmdloop()
79-
```
7+
```py
8+
{%
9+
include "../../examples/getting_started.py"
10+
%}
11+
```
8012

8113
## Cmd class initializer
8214

0 commit comments

Comments
 (0)