Skip to content
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@

# cmd2 code
cmd2/__init__.py @kmvanbrunt @tleonhardt
cmd2/ansi.py @kmvanbrunt @tleonhardt
cmd2/argparse_*.py @kmvanbrunt @anselor
cmd2/clipboard.py @tleonhardt
cmd2/cmd2.py @tleonhardt @kmvanbrunt
cmd2/colors.py @tleonhardt @kmvanbrunt
cmd2/command_definition.py @anselor
cmd2/constants.py @tleonhardt @kmvanbrunt
cmd2/decorators.py @kmvanbrunt @anselor
Expand All @@ -39,8 +39,11 @@ cmd2/history.py @tleonhardt
cmd2/parsing.py @kmvanbrunt
cmd2/plugin.py @anselor
cmd2/py_bridge.py @kmvanbrunt
cmd2/rich_utils.py @kmvanbrunt
cmd2/rl_utils.py @kmvanbrunt
cmd2/table_creator.py @kmvanbrunt
cmd2/string_utils.py @kmvanbrunt
cmd2/styles.py @tleonhardt @kmvanbrunt
cmd2/terminal_utils.py @kmvanbrunt
cmd2/transcript.py @tleonhardt
cmd2/utils.py @tleonhardt @kmvanbrunt

Expand Down
4 changes: 2 additions & 2 deletions .github/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ uv venv --python 3.12
Then you can run commands in this isolated virtual environment using `uv` like so:

```sh
uv run examples/basic.py
uv run examples/hello_cmd2.py
```

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

```sh
$ uv run examples/example.py
$ uv run examples/getting_started.py
```

You can type `help` to get help or `quit` to quit. If you see that, then congratulations – you're
Expand Down
18 changes: 7 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ menagerie of simple command line tools created by strangers on github and the gu
Unfortunately, when CLIs become significantly complex the ease of command discoverability tends to
fade quickly. On the other hand, Web and traditional desktop GUIs are first in class when it comes
to easily discovering functionality. The price we pay for beautifully colored displays is complexity
required to aggregate disperate applications into larger systems. `cmd2` fills the niche between
required to aggregate disparate applications into larger systems. `cmd2` fills the niche between
high [ease of command discovery](https://clig.dev/#ease-of-discovery) applications and smart
workflow automation systems.

Expand Down Expand Up @@ -105,20 +105,16 @@ examples.

## Tutorials

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

## Hello World

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

| Application Name | Description | Organization or Author |
| --------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- |
| [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) |
| [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/) |
| [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) |
| [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) |
Expand All @@ -176,6 +171,7 @@ reproduce the bug. At a minimum, please state the following:
| [tomcatmanager](https://github.com/tomcatmanager/tomcatmanager) | A command line tool and python library for managing a tomcat server | [tomcatmanager](https://github.com/tomcatmanager) |
| [Falcon Toolkit](https://github.com/CrowdStrike/Falcon-Toolkit) | Unleash the power of the CrowdStrike Falcon Platform at the CLI | [CrowdStrike](https://github.com/CrowdStrike) |
| [EXPLIoT](https://gitlab.com/expliot_framework/expliot) | Internet of Things Security Testing and Exploitation framework | [expliot_framework](https://gitlab.com/expliot_framework/) |
| [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) |

Possibly defunct but still good examples

Expand Down
2 changes: 1 addition & 1 deletion cmd2/cmd2.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
Settable environment parameters
Parsing commands with `argparse` argument parsers (flags)
Redirection to file or paste buffer (clipboard) with > or >>
Easy transcript-based testing of applications (see examples/example.py)
Easy transcript-based testing of applications (see examples/transcript_example.py)
Bash-style ``select`` available

Note, if self.stdout is different than sys.stdout, then redirection with > and |
Expand Down
2 changes: 1 addition & 1 deletion cmd2/styles.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class Cmd2Style(StrEnum):
EXAMPLE = "cmd2.example" # Command line examples in help text
HELP_HEADER = "cmd2.help.header" # Help table header text
HELP_LEADER = "cmd2.help.leader" # Text right before the help tables are listed
RULE_LINE = "rule.line" # Rich style for horizontal rules
RULE_LINE = "rule.line" # Built-in Rich style for horizontal rules
SUCCESS = "cmd2.success" # Success text (used by psuccess())
WARNING = "cmd2.warning" # Warning text (used by pwarning())

Expand Down
2 changes: 1 addition & 1 deletion cmd2/transcript.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class Cmd2TestCase(unittest.TestCase):
that will execute the commands in a transcript file and expect the
results shown.

See example.py
See transcript_example.py
"""

cmdapp: Optional['Cmd'] = None
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# First Application
# Getting Started

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

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

??? example
!!! example "getting_started.py"

```py
{%
include "../../examples/first_app.py"
include "../../examples/getting_started.py"
%}
```

## Basic Application

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

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

```shell
$ python first_app.py
$ python getting_started.py
```

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

```shell
$ python first_app.py
$ python getting_started.py
(Cmd) set
```

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

```py
speak_parser = cmd2.Cmd2ArgumentParser()
Expand Down
2 changes: 1 addition & 1 deletion docs/examples/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<!--intro-start-->

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

Expand Down
13 changes: 7 additions & 6 deletions docs/features/argument_processing.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ following for you:

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

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

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

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

## Argparse Extensions

Expand Down
17 changes: 1 addition & 16 deletions docs/features/generating_output.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,21 +126,6 @@ you can pad it appropriately with spaces. However, there are categories of Unico
occupy 2 cells, and other that occupy 0. To further complicate matters, you might have included ANSI
escape sequences in the output to generate colors on the terminal.

The `cmd2.ansi.style_aware_wcswidth` function solves both of these problems. Pass it a string, and
The `cmd2.string_utils.str_width` function solves both of these problems. Pass it a string, and
regardless of which Unicode characters and ANSI text style escape sequences it contains, it will
tell you how many characters on the screen that string will consume when printed.

## Pretty Printing Data Structures

The `cmd2.Cmd.ppretty` method is similar to the Python
[pprint](https://docs.python.org/3/library/pprint.html) function from the standard `pprint` module.
`cmd2.Cmd.pprint` adds the same conveniences as `cmd2.Cmd.poutput`.

This method provides a capability to “pretty-print” arbitrary Python data structures in a form which
can be used as input to the interpreter and is easy for humans to read.

The formatted representation keeps objects on a single line if it can, and breaks them onto multiple
lines if they don’t fit within the allowed width, adjustable by the width parameter defaulting to 80
characters.

Dictionaries are sorted by key before the display is computed.
80 changes: 6 additions & 74 deletions docs/features/initialization.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,81 +2,13 @@

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

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


class BasicApp(cmd2.Cmd):
CUSTOM_CATEGORY = 'My Custom Commands'

def __init__(self):
super().__init__(
multiline_commands=['echo'],
persistent_history_file='cmd2_history.dat',
startup_script='scripts/startup.txt',
include_ipy=True,
)

# Prints an intro banner once upon application startup
self.intro = style('Welcome to cmd2!', fg=Fg.RED, bg=Bg.WHITE, bold=True)

# Show this as the prompt when asking for input
self.prompt = 'myapp> '

# Used as prompt for multiline commands after the first line
self.continuation_prompt = '... '

# Allow access to your application in py and ipy via self
self.self_in_py = True

# Set the default category name
self.default_category = 'cmd2 Built-in Commands'

# Color to output text in with echo command
self.foreground_color = Fg.CYAN.name.lower()

# Make echo_fg settable at runtime
fg_colors = [c.name.lower() for c in Fg]
self.add_settable(
cmd2.Settable('foreground_color', str, 'Foreground color to use with echo command', self,
choices=fg_colors)
)

@cmd2.with_category(CUSTOM_CATEGORY)
def do_intro(self, _):
"""Display the intro banner"""
self.poutput(self.intro)

@cmd2.with_category(CUSTOM_CATEGORY)
def do_echo(self, arg):
"""Example of a multiline command"""
fg_color = Fg[self.foreground_color.upper()]
self.poutput(style(arg, fg=fg_color))


if __name__ == '__main__':
app = BasicApp()
app.cmdloop()
```
```py
{%
include "../../examples/getting_started.py"
%}
```

## Cmd class initializer

Expand Down
18 changes: 9 additions & 9 deletions docs/features/os.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,23 +69,23 @@ user to enter commands, which are then executed by your program.
You may want to execute commands in your program without prompting the user for any input. There are
several ways you might accomplish this task. The easiest one is to pipe commands and their arguments
into your program via standard input. You don't need to do anything to your program in order to use
this technique. Here's a demonstration using the `examples/example.py` included in the source code
of `cmd2`:
this technique. Here's a demonstration using the `examples/transcript_example.py` included in the
source code of `cmd2`:

$ echo "speak -p some words" | python examples/example.py
$ echo "speak -p some words" | python examples/transcript_example.py
omesay ordsway

Using this same approach you could create a text file containing the commands you would like to run,
one command per line in the file. Say your file was called `somecmds.txt`. To run the commands in
the text file using your `cmd2` program (from a Windows command prompt):

c:\cmd2> type somecmds.txt | python.exe examples/example.py
c:\cmd2> type somecmds.txt | python.exe examples/transcript_example.py
omesay ordsway

By default, `cmd2` programs also look for commands pass as arguments from the operating system
shell, and execute those commands before entering the command loop:

$ python examples/example.py help
$ python examples/transcript_example.py help

Documented commands (use 'help -v' for verbose/'help <topic>' for details):
===========================================================================
Expand All @@ -99,8 +99,8 @@ example, you might have a command inside your `cmd2` program which itself accept
maybe even option strings. Say you wanted to run the `speak` command from the operating system
shell, but have it say it in pig latin:

$ python example/example.py speak -p hello there
python example.py speak -p hello there
$ python example/transcript_example.py speak -p hello there
python transcript_example.py speak -p hello there
usage: speak [-h] [-p] [-s] [-r REPEAT] words [words ...]
speak: error: the following arguments are required: words
*** Unknown syntax: -p
Expand All @@ -122,7 +122,7 @@ Check the source code of this example, especially the `main()` function, to see
Alternatively you can simply wrap the command plus arguments in quotes (either single or double
quotes):

$ python example/example.py "speak -p hello there"
$ python example/transcript_example.py "speak -p hello there"
ellohay heretay
(Cmd)

Expand All @@ -148,6 +148,6 @@ quits while returning an exit code:

Here is another example using `quit`:

$ python example/example.py "speak -p hello there" quit
$ python example/transcript_example.py "speak -p hello there" quit
ellohay heretay
$
Loading
Loading