Skip to content
Merged
Show file tree
Hide file tree
Changes from 18 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
6 changes: 3 additions & 3 deletions docs/api/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

These pages document the public API for `cmd2`. If a method, class, function, attribute, or constant
is not documented here, consider it private and subject to change. There are many classes, methods,
functions, and constants in the source code which do not begin with an underscore but are not
functions, and constants in the source code that do not begin with an underscore but are not
documented here. When looking at the source code for this library, you cannot safely assume that
because something doesn't start with an underscore, it is a public API.
something is a public API just because it doesn't start with an underscore.

If a release of this library changes any of the items documented here, the version number will be
incremented according to the [Semantic Version Specification](https://semver.org).
Expand All @@ -18,7 +18,7 @@ incremented according to the [Semantic Version Specification](https://semver.org
- [cmd2.colors](./colors.md) - StrEnum of all color names supported by the Rich library
- [cmd2.command_definition](./command_definition.md) - supports the definition of commands in
separate classes to be composed into cmd2.Cmd
- [cmd2.constants](./constants.md) - just like it says on the tin
- [cmd2.constants](./constants.md) - constants used in `cmd2`
- [cmd2.decorators](./decorators.md) - decorators for `cmd2` commands
- [cmd2.exceptions](./exceptions.md) - custom `cmd2` exceptions
- [cmd2.history](./history.md) - classes for storing the history of previously entered commands
Expand Down
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
38 changes: 19 additions & 19 deletions docs/examples/alternate_event_loops.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# Alternate Event Loops

Throughout this documentation we have focused on the **90%** use case, that is the use case we
believe around **90+%** of our user base is looking for. This focuses on ease of use and the best
out-of-the-box experience where developers get the most functionality for the least amount of
effort. We are talking about running `cmd2` applications with the `cmdloop()` method:
Throughout this documentation, we have focused on the 90% use case, which we believe applies to over
90% of our user base. This focuses on ease of use and the best out-of-the-box experience, where
developers get the most functionality for the least amount of effort. We are talking about running
`cmd2` applications with the `cmdloop()` method:

```py
from cmd2 import Cmd
Expand All @@ -21,8 +21,8 @@ Many Python concurrency libraries involve or require an event loop which they ar
such as [asyncio](https://docs.python.org/3/library/asyncio.html), [gevent](http://www.gevent.org/),
[Twisted](https://twistedmatrix.com), etc.

`cmd2` applications can be executed in a fashion where `cmd2` doesn't own the main loop for the
program by using code like the following:
`cmd2` applications can be executed in a way where `cmd2` doesn't own the main loop for the program
by using code like the following:

```py
import cmd2
Expand All @@ -44,29 +44,29 @@ 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
that running in this fashion comes with several disadvantages, including:
Running in this way 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 that
running in this fashion comes with several disadvantages, including:

- Requires the developer to write more code
- Does not support transcript testing
Expand Down
57 changes: 29 additions & 28 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 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 built-in features.

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 All @@ -85,11 +87,11 @@ you will see our `maxrepeats` setting show up with its default value of `3`.

## Create A Command

Now we will create our first command, called `speak` which will echo back whatever we tell it to
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 pig latin. We will also use some built in methods for
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 Expand Up @@ -122,7 +124,7 @@ import argparse

There's a bit to unpack here, so let's walk through it. We created `speak_parser`, which uses the
[argparse](https://docs.python.org/3/library/argparse.html) module from the Python standard library
to parse command line input from a user. There is nothing thus far that is specific to `cmd2`.
to parse command line input from a user. So far, there is nothing specific to `cmd2`.

There is also a new method called `do_speak()`. In both
[cmd](https://docs.python.org/3/library/cmd.html) and `cmd2`, methods that start with `do_` become
Expand All @@ -135,12 +137,12 @@ Note the `cmd2.decorators.with_argparser` decorator on the `do_speak()` method.
the user input doesn't meet the requirements defined by the argparser, then an error will be
displayed for the user.
1. It alters our `do_speak` method so that instead of receiving the raw user input as a parameter,
we receive the namespace from the argparser.
we receive the namespace from the argument parser.
1. It creates a help message for us based on the argparser.

You can see in the body of the method how we use the namespace from the argparser (passed in as the
variable `args`). We build an array of words which we will output, honoring both the `--piglatin`
and `--shout` options.
variable `args`). We build a list of words which we will output, honoring both the `--piglatin` and
`--shout` options.

At the end of the method, we use our `maxrepeats` setting as an upper limit to the number of times
we will print the output.
Expand Down Expand Up @@ -196,9 +198,9 @@ def __init__(self):

Shortcuts are passed to the `cmd2` initializer, and if you want the built-in shortcuts of `cmd2` you
have to pass them. These shortcuts are defined as a dictionary, with the key being the shortcut, and
the value containing the command. When using the default shortcuts and also adding your own, it's a
good idea to use the `.update()` method to modify the dictionary. This way if you add a shortcut
that happens to already be in the default set, yours will override, and you won't get any errors at
the value containing the command. When using the default shortcuts and adding your own, it's a good
idea to use the `.update()` method to modify the dictionary. This way, if you add a shortcut that
happens to already be in the default set, yours will override, and you won't get any errors at
runtime.

Run your app again, and type:
Expand All @@ -207,16 +209,15 @@ Run your app again, and type:
(Cmd) shortcuts
```

to see the list of all of the shortcuts, including the one for speak that we just created.
to see the list of all the shortcuts, including the one for speak that we just created.

## Multiline Commands

Some use cases benefit from the ability to have commands that span more than one line. For example,
you might want the ability for your user to type in a SQL command, which can often span lines and
which are terminated with a semicolon. Let's add a
[multiline command](../features/multiline_commands.md) to our application. First we'll create a new
command called `orate`. This code shows both the definition of our `speak` command, and the `orate`
command:
Some use cases benefit from commands that span more than one line. For example, you might want the
ability for your user to type in a SQL command, which can often span lines and which are terminated
with a semicolon. Let's add a [multiline command](../features/multiline_commands.md) to our
application. First we'll create a new command called `orate`. This code shows both the definition of
our `speak` command, and the `orate` command:

```py
@cmd2.with_argparser(speak_parser)
Expand Down
Loading
Loading