Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
7460055
Starting to give the documentation a very thorough review
tleonhardt Sep 13, 2025
6b84bd4
More documentation updates
tleonhardt Sep 13, 2025
ef30d8d
Updated docs/features/help.md
tleonhardt Sep 13, 2025
6cbc0b4
Continuing to update documentation
tleonhardt Sep 14, 2025
3224336
Finish making a detailed pass through the existing documentation
tleonhardt Sep 14, 2025
a43764c
Fix a couple typos found by gemini-cli code review
tleonhardt Sep 14, 2025
692fbbd
Fixed a couple typos find by gemini-cli review
tleonhardt Sep 14, 2025
71e8ae7
Minor wording improvements
tleonhardt Sep 14, 2025
31731aa
More minor working improvements
tleonhardt Sep 14, 2025
cfd1c44
Capitalize proper name
tleonhardt Sep 14, 2025
35bf7dd
Simplify some wording
tleonhardt Sep 14, 2025
0298bd3
Added a new documentation section on `cmd2 Major Version Upgrades` an…
tleonhardt Sep 14, 2025
a711640
Added new feature doc on configuring a custom theme
tleonhardt Sep 14, 2025
5168187
A few very minor grammar fixes
tleonhardt Sep 14, 2025
62f00cf
Merge branch 'main' into documentation-review
tleonhardt Sep 15, 2025
3916696
Grammar fix based on feedback
tleonhardt Sep 15, 2025
90f72d3
Added info on description and epliog fields within argument parsers b…
tleonhardt Sep 15, 2025
f6a313e
Deleted ignored ruff rule that no longer exists from ext-test pyproje…
tleonhardt Sep 15, 2025
17a6332
Merge branch 'main' into documentation-review
tleonhardt Sep 16, 2025
1cb3550
Addressed PR comments
tleonhardt Sep 16, 2025
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
10 changes: 7 additions & 3 deletions docs/doc_conventions.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ In Markdown all indenting is significant. Use 4 spaces per indenting level.

## Wrapping

Hard wrap all text so that line lengths are no greater than 120 characters. It makes everything
Hard wrap all text so that line lengths are no greater than 100 characters. It makes everything
easier when editing documentation, and has no impact on reading documentation because we render to
html.

Expand Down Expand Up @@ -75,9 +75,13 @@ When using `mkdocstrings`, it must be preceded by a blank line before and after,

### Links to API Reference

To reference a method or function, do the following:
To reference a class, method, or function, use block quotes around the name of the full namespace
path for it followed by empty block quotes. So to reference `cmd2.Cmd`, you use `[cmd2.Cmd][]`.

TODO: Figure out how to do this
If you want to change the name to use something shorter than the full namespace resolution you can
put the full path in the 2nd set of block quotes instead of leaving it empty and put the shorter
name in the one on the left. So you could also use `[Cmd][cmd2.Cmd]` to link to the API
documentation for `cmd2.Cmd`.

## Referencing cmd2

Expand Down
20 changes: 10 additions & 10 deletions docs/examples/alternate_event_loops.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,25 +44,25 @@ if __name__ == '__main__':
app.postloop()
```

The `cmd2.Cmd.runcmds_plus_hooks()` method runs multiple commands via
`cmd2.Cmd.onecmd_plus_hooks()`.
The [cmd2.Cmd.runcmds_plus_hooks][] method runs multiple commands where each single command is
executed via [cmd2.Cmd.onecmd_plus_hooks][].

The `cmd2.Cmd.onecmd_plus_hooks()` method will do the following to execute a single command in a
The [cmd2.Cmd.onecmd_plus_hooks][] method will do the following to execute a single command in a
normal fashion:

1. Parse user input into a `cmd2.Statement` object
1. Call methods registered with `cmd2.Cmd.register_postparsing_hook()`
1. Parse user input into a [cmd2.Statement][] object
1. Call methods registered with [cmd2.Cmd.register_postparsing_hook][]
1. Redirect output, if user asked for it and it's allowed
1. Start timer
1. Call methods registered with `cmd2.Cmd.register_precmd_hook`
1. Call `cmd2.Cmd.precmd` - for backwards compatibility with `cmd.Cmd`
1. Call methods registered with [cmd2.Cmd.register_precmd_hook][]
1. Call [cmd2.Cmd.precmd][] - for backwards compatibility with `cmd`
1. Add statement to [History](../features/history.md)
1. Call `do_command` method
1. Call methods registered with `cmd2.Cmd.register_postcmd_hook()`
1. Call `cmd2.Cmd.postcmd` - for backwards compatibility with `cmd.Cmd`
1. Call methods registered with [cmd2.Cmd.register_postcmd_hook][]
1. Call [cmd2.Cmd.postcmd][] - for backwards compatibility with `cmd`
1. Stop timer and display the elapsed time
1. Stop redirecting output if it was redirected
1. Call methods registered with `cmd2.Cmd.register_cmdfinalization_hook()`
1. Call methods registered with [cmd2.Cmd.register_cmdfinalization_hook][]

Running in this fashion enables the ability to integrate with an external event loop. However, how
to integrate with any specific event loop is beyond the scope of this documentation. Please note
Expand Down
26 changes: 14 additions & 12 deletions docs/examples/getting_started.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Getting Started

Here's a quick walkthrough of a simple application which demonstrates 10 features of `cmd2`:
Here's a quick walkthrough of a the simple
[getting_started.py](https://github.com/python-cmd2/cmd2/blob/main/examples/getting_started.py)
example application which demonstrates many features of `cmd2`:

- [Settings](../features/settings.md)
- [Commands](../features/commands.md)
Expand Down Expand Up @@ -29,36 +31,36 @@ following contents:

```py
#!/usr/bin/env python
"""A simple cmd2 application."""
"""A basic cmd2 application."""
import cmd2


class FirstApp(cmd2.Cmd):
"""A simple cmd2 application."""
class BasicApp(cmd2.Cmd):
"""Cmd2 application to demonstrate many common features."""


if __name__ == '__main__':
import sys
c = FirstApp()
sys.exit(c.cmdloop())
app = BasicApp()
sys.exit(app.cmdloop())
```

We have a new class `FirstApp` which is a subclass of [cmd2.Cmd][]. When we tell python to run our
We have a new class `BasicApp` which is a subclass of [cmd2.Cmd][]. When we tell Python to run our
file like this:

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

it creates an instance of our class, and calls the `cmd2.Cmd.cmdloop` method. This method accepts
user input and runs commands based on that input. Because we subclassed `cmd2.Cmd`, our new app
already has a bunch of features built in.
The application creates an instance of our class, and calls the [cmd2.Cmd.cmdloop][] method. This
method accepts user input and runs commands based on that input. Because we subclassed `cmd2.Cmd`,
our new app already has a bunch of features built in.

Congratulations, you have a working `cmd2` app. You can run it, and then type `quit` to exit.

## Create a New Setting

Before we create our first command, we are going to add a setting to this app. `cmd2` includes
Before we create our first command, we are going to add a new setting to this app. `cmd2` includes
robust support for [Settings](../features/settings.md). You configure settings during object
initialization, so we need to add an initializer to our class:

Expand Down Expand Up @@ -89,7 +91,7 @@ Now we will create our first command, called `speak` which will echo back whatev
say. We are going to use an [argument processor](../features/argument_processing.md) so the `speak`
command can shout and talk pig latin. We will also use some built in methods for
[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 `FirstApp()` class:
that the `speak_parser` attribute and the `do_speak()` method are part of the `BasicApp()` class:

```py
speak_parser = cmd2.Cmd2ArgumentParser()
Expand Down
55 changes: 31 additions & 24 deletions docs/features/argument_processing.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,20 @@
[argparse](https://docs.python.org/3/library/argparse.html) python module. `cmd2` handles the
following for you:

1. Parsing input and quoted strings like the Unix shell
1. Parse the resulting argument list using an instance of `argparse.ArgumentParser` that you provide
1. Passes the resulting `argparse.Namespace` object to your command function. The `Namespace`
includes the `Statement` object that was created when parsing the command line. It can be
retrieved by calling `cmd2_statement.get()` on the `Namespace`.
1. Parsing input and quoted strings in a manner similar to how POSIX shells do it
1. Parse the resulting argument list using an instance of
[argparse.ArgumentParser](https://docs.python.org/3/library/argparse.html#argparse.ArgumentParser)
that you provide
1. Passes the resulting
[argparse.Namespace](https://docs.python.org/3/library/argparse.html#argparse.Namespace) object
to your command function. The `Namespace` includes the [Statement][cmd2.Statement] object that
was created when parsing the command line. It can be retrieved by calling `cmd2_statement.get()`
on the `Namespace`.
1. Adds the usage message from the argument parser to your command's help.
1. Checks if the `-h/--help` option is present, and if so, displays the help message for the command

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

See the
[argparse_example](https://github.com/python-cmd2/cmd2/blob/main/examples/argparse_example.py)
Expand All @@ -31,11 +36,11 @@ command which might have its own argument parsing.

## Argument Parsing

For each command in the `cmd2` subclass which requires argument parsing, create a unique instance of
`argparse.ArgumentParser()` which can parse the input appropriately for the command. Then decorate
the command method with the `@with_argparser` decorator, passing the argument parser as the first
parameter to the decorator. This changes the second argument to the command method, which will
contain the results of `ArgumentParser.parse_args()`.
For each command in the `cmd2.Cmd` subclass which requires argument parsing, create a unique
instance of `argparse.ArgumentParser()` which can parse the input appropriately for the command.
Then decorate the command method with the `@with_argparser` decorator, passing the argument parser
as the first parameter to the decorator. This changes the second argument to the command method,
which will contain the results of `ArgumentParser.parse_args()`.

Here's what it looks like:

Expand Down Expand Up @@ -65,8 +70,8 @@ def do_speak(self, opts):

`cmd2` sets the `prog` variable in the argument parser based on the name of the method it is decorating. This will override anything you specify in `prog` variable when creating the argument parser.

As of the 3.0.0 release, `cmd2` sets `prog` when the instance-specific parser is created, which is
later than it did previously.
As of the 3.0.0 release, `cmd2` sets `prog` when the instance-specific parser is created, which is
later than it did previously.

## Help Messages

Expand All @@ -84,7 +89,7 @@ argparser.add_argument('tag', help='tag')
argparser.add_argument('content', nargs='+', help='content to surround with tag')
@with_argparser(argparser)
def do_tag(self, args):
"""create a html tag"""
"""Create an HTML tag"""
self.stdout.write('<{0}>{1}</{0}>'.format(args.tag, ' '.join(args.content)))
self.stdout.write('\n')
```
Expand All @@ -94,7 +99,7 @@ the `help tag` command displays:
```text
usage: tag [-h] tag content [content ...]

create an HTML tag
Create an HTML tag

positional arguments:
tag tag
Expand Down Expand Up @@ -168,13 +173,13 @@ This command cannot generate tags with no content, like <br/>

!!! warning

If a command **foo** is decorated with one of cmd2's argparse decorators, then **help_foo** will not be invoked when `help foo` is called. The [argparse](https://docs.python.org/3/library/argparse.html) module provides a rich API which can be used to tweak every aspect of the displayed help and we encourage `cmd2` developers to utilize that.
If a command **foo** is decorated with `cmd2`'s `with_argparse` decorator, then **help_foo** will not be invoked when `help foo` is called. The [argparse](https://docs.python.org/3/library/argparse.html) module provides a rich API which can be used to tweak every aspect of the displayed help and we encourage `cmd2` developers to utilize that.

## Argument List

The default behavior of `cmd2` is to pass the user input directly to your `do_*` methods as a
string. The object passed to your method is actually a `Statement` object, which has additional
attributes that may be helpful, including `arg_list` and `argv`:
string. The object passed to your method is actually a [Statement][cmd2.Statement] object, which has
additional attributes that may be helpful, including `arg_list` and `argv`:

```py
class CmdLineApp(cmd2.Cmd):
Expand All @@ -200,8 +205,8 @@ class CmdLineApp(cmd2.Cmd):

If you don't want to access the additional attributes on the string passed to your `do_*` method you
can still have `cmd2` apply shell parsing rules to the user input and pass you a list of arguments
instead of a string. Apply the `@with_argument_list` decorator to those methods that should receive
an argument list instead of a string:
instead of a string. Apply the [@with_argument_list][cmd2.with_argument_list] decorator to those
methods that should receive an argument list instead of a string:

```py
from cmd2 import with_argument_list
Expand Down Expand Up @@ -272,7 +277,7 @@ def settings_ns_provider(self) -> argparse.Namespace:
return ns
```

To use this function with the argparse decorators, do the following:
To use this function with the `@with_argparser` decorator, do the following:

```py
@with_argparser(my_parser, ns_provider=settings_ns_provider)
Expand All @@ -293,14 +298,16 @@ 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.

The [@as_subcommand_to][cmd2.as_subcommand_to] decorator makes adding subcommands easy.

## Argparse Extensions

`cmd2` augments the standard `argparse.nargs` with range tuple capability:

- `nargs=(5,)` - accept 5 or more items
- `nargs=(8, 12)` - accept 8 to 12 items

`cmd2` also provides the `cmd2.argparse_custom.Cmd2ArgumentParser` class which inherits from
`cmd2` also provides the [Cmd2ArgumentParser][cmd2.Cmd2ArgumentParser] class which inherits from
`argparse.ArgumentParser` and improves error and help output.

## Decorator Order
Expand Down Expand Up @@ -338,8 +345,8 @@ example demonstrates both above cases in a concrete fashion.

## Reserved Argument Names

`cmd2` argparse decorators add the following attributes to argparse Namespaces. To avoid naming
collisions, do not use any of the names for your argparse arguments.
`cmd2`'s `@with_argparser` decorator adds the following attributes to argparse Namespaces. To avoid
naming collisions, do not use any of the names for your argparse arguments.

- `cmd2_statement` - `cmd2.Cmd2AttributeWrapper` object containing the `cmd2.Statement` object that
was created when parsing the command line.
Expand Down
48 changes: 23 additions & 25 deletions docs/features/builtin_commands.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Builtin Commands

Applications which subclass `cmd2.Cmd` inherit a number of commands which may be useful to your
Applications which subclass [cmd2.Cmd][] inherit a number of commands which may be useful to your
users. Developers can [Remove Builtin Commands](#remove-builtin-commands) if they do not want them
to be part of the application.

Expand Down Expand Up @@ -33,9 +33,9 @@ for more information.
This command allows you to view, run, edit, save, or clear previously entered commands from the
history. See [History](history.md) for more information.

### ipy
### ipy (optional)

This optional opt-in command enters an interactive IPython shell. See
This optional opt-in command enters an interactive :simple-jupyter: IPython shell. See
[IPython (optional)](./embedded_python_shells.md#ipython-optional) for more information.

### macro
Expand All @@ -44,9 +44,9 @@ This command manages macros via subcommands `create`, `delete`, and `list`. A ma
alias, but it can contain argument placeholders. See [Macros](./shortcuts_aliases_macros.md#macros)
for more information.

### py
### py (optional)

This command invokes a Python command or shell. See
This optional opt-in command invokes a Python command or shell. See
[Embedded Python Shells](./embedded_python_shells.md) for more information.

### quit
Expand All @@ -63,7 +63,7 @@ This command runs a Python script file inside the `cmd2` application. See
This command runs commands in a script file that is encoded as either ASCII or UTF-8 text. See
[Command Scripts](./scripting.md#command-scripts) for more information.

### \_relative_run_script
### \_relative_run_script (hidden)

This command is hidden from the help that's visible to end users. It runs a script like
[run_script](#run_script) but does so using a path relative to the script that is currently
Expand All @@ -77,21 +77,19 @@ application:

```text
(Cmd) set
Name Value Description
====================================================================================================================
allow_style Terminal Allow ANSI text style sequences in output (valid values:
Always, Never, Terminal)
always_show_hint False Display tab completion hint even when completion suggestions
print
debug True Show full traceback on exception
echo False Echo command issued into output
editor vi Program used by 'edit'
feedback_to_output False Include nonessentials in '|' and '>' results
max_completion_items 50 Maximum number of CompletionItems to display during tab
completion
quiet False Don't print non-essential feedback
scripts_add_to_history True Scripts and pyscripts add commands to history
timing False Report execution times
Name Value Description
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
allow_style Terminal Allow ANSI text style sequences in output (valid values: Always, Never, Terminal)
always_show_hint False Display tab completion hint even when completion suggestions print
debug False Show full traceback on exception
echo False Echo command issued into output
editor vim Program used by 'edit'
feedback_to_output False Include nonessentials in '|' and '>' results
foreground_color cyan Foreground color to use with echo command
max_completion_items 50 Maximum number of CompletionItems to display during tab completion
quiet False Don't print nonessential feedback
scripts_add_to_history True Scripts and pyscripts add commands to history
timing False Report execution times
```

Any of these user-settable parameters can be set while running your app with the `set` command like
Expand Down Expand Up @@ -119,10 +117,10 @@ more information.

## Remove Builtin Commands

Developers may not want to offer the commands builtin to [cmd2.Cmd][] to users of their application.
To remove a command you must delete the method implementing that command from the [cmd2.Cmd][]
object at runtime. For example, if you wanted to remove the [shell](#shell) command from your
application:
Developers may not want to offer all the commands built into [cmd2.Cmd][] to users of their
application. To remove a command you must delete the method implementing that command from the
[cmd2.Cmd][] object at runtime. For example, if you wanted to remove the [shell](#shell) command
from your application:

```py
class NoShellApp(cmd2.Cmd):
Expand Down
10 changes: 2 additions & 8 deletions docs/features/clipboard.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Clipboard Integration

Nearly every operating system has some notion of a short-term storage area which can be accessed by
any program. Usually this is called the clipboard, but sometimes people refer to it as the paste
buffer.
any program. Usually this is called the :clipboard: clipboard, but sometimes people refer to it as
the paste buffer.

`cmd2` integrates with the operating system clipboard using the
[pyperclip](https://github.com/asweigart/pyperclip) module. Command output can be sent to the
Expand Down Expand Up @@ -32,10 +32,4 @@ If you would like your `cmd2` based application to be able to use the clipboard
alternative ways, you can use the following methods (which work uniformly on Windows, macOS, and
Linux).

<!-- prettier-ignore-start -->
::: cmd2.clipboard
handler: python
options:
show_root_heading: false
show_source: false
<!-- prettier-ignore-end -->
Loading
Loading