Skip to content

Commit 3224336

Browse files
committed
Finish making a detailed pass through the existing documentation
1 parent 6cbc0b4 commit 3224336

17 files changed

+177
-154
lines changed

docs/doc_conventions.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ In Markdown all indenting is significant. Use 4 spaces per indenting level.
3636

3737
## Wrapping
3838

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

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

7676
### Links to API Reference
7777

78-
To reference a method or function, do the following:
78+
To reference a class, method, or function, do the following use block quotes around it followed by
79+
empty block quotes. So to reference `cmd2.Cmd`, you using `[cmd2.Cmd][]`.
7980

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

8286
## Referencing cmd2
8387

docs/examples/alternate_event_loops.md

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -44,25 +44,25 @@ if __name__ == '__main__':
4444
app.postloop()
4545
```
4646

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

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

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

6767
Running in this fashion enables the ability to integrate with an external event loop. However, how
6868
to integrate with any specific event loop is beyond the scope of this documentation. Please note

docs/examples/getting_started.md

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# Getting Started
22

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

57
- [Settings](../features/settings.md)
68
- [Commands](../features/commands.md)
@@ -29,36 +31,36 @@ following contents:
2931

3032
```py
3133
#!/usr/bin/env python
32-
"""A simple cmd2 application."""
34+
"""A basic cmd2 application."""
3335
import cmd2
3436

3537

36-
class FirstApp(cmd2.Cmd):
37-
"""A simple cmd2 application."""
38+
class BasicApp(cmd2.Cmd):
39+
"""Cmd2 application to demonstrate many common features."""
3840

3941

4042
if __name__ == '__main__':
4143
import sys
42-
c = FirstApp()
43-
sys.exit(c.cmdloop())
44+
app = BasicApp()
45+
sys.exit(app.cmdloop())
4446
```
4547

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

4951
```shell
5052
$ python getting_started.py
5153
```
5254

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

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

5961
## Create a New Setting
6062

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

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

9496
```py
9597
speak_parser = cmd2.Cmd2ArgumentParser()

docs/features/multiline_commands.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
# Multiline Commands
22

33
Command input may span multiple lines for the commands whose names are listed in the
4-
`multiline_commands` argument to `cmd2.Cmd.__init__()`. These commands will be executed only after
5-
the user has entered a _terminator_. By default, the command terminator is `;`; specifying the
6-
`terminators` optional argument to `cmd2.Cmd.__init__()` allows different terminators. A blank line
7-
is _always_ considered a command terminator (cannot be overridden).
4+
`multiline_commands` argument to [cmd2.Cmd.\_\_init\_\_][cmd2.Cmd.__init__]. These commands will be
5+
executed only after the user has entered a _terminator_. By default, the command terminator is `;`.
6+
Specifying the `terminators` optional argument to `cmd2.Cmd.__init__()` allows different
7+
terminators. A blank line is _always_ considered a command terminator (cannot be overridden).
88

99
In multiline commands, output redirection characters like `>` and `|` are part of the command
1010
arguments unless they appear after the terminator.
@@ -14,7 +14,7 @@ arguments unless they appear after the terminator.
1414
When a user types a **Multiline Command** it may span more than one line of input. The prompt for
1515
the first line of input is specified by the [cmd2.Cmd.prompt][] instance attribute - see
1616
[Customizing the Prompt](./prompt.md#customizing-the-prompt). The prompt for subsequent lines of
17-
input is defined by the `cmd2.Cmd.continuation_prompt` attribute.
17+
input is defined by the [cmd2.Cmd.continuation_prompt][] attribute.
1818

1919
## Use cases
2020

docs/features/os.md

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,14 @@ get a `!` shortcut for `shell`, which allows you to type:
1515

1616
(Cmd) !ls -al
1717

18-
NOTE: `cmd2` provides user-friendly tab completion throughout the process of running a shell
19-
command - first for the shell command name itself, and then for file paths in the argument section.
18+
!!! note
19+
20+
`cmd2` provides user-friendly tab completion throughout the process of running a shell command -
21+
first for the shell command name itself, and then for file paths in the argument section.
22+
23+
However, a `cmd2` application effectively **becomes** the shell, so if you have _extra_ shell
24+
completion configured for your particular shell such as `bash`, `zsh`, `fish`, etc. then this
25+
will not be available within `cmd2`.
2026

2127
## Editors
2228

@@ -36,16 +42,18 @@ system.
3642

3743
## Terminal pagers
3844

39-
Output of any command can be displayed one page at a time using the `cmd2.Cmd.ppaged` method.
45+
Output of any command can be displayed one page at a time using the [cmd2.Cmd.ppaged][] method.
4046

4147
Alternatively, a terminal pager can be invoked directly using the ability to run shell commands with
4248
the `!` shortcut like so:
4349

4450
(Cmd) !less foo.txt
4551

46-
NOTE: Once you are in a terminal pager, that program temporarily has control of your terminal,
47-
**NOT** `cmd2`. Typically you can use either the arrow keys or `<PageUp>`/`<PageDown>` keys to
48-
scroll around or type `q` to quit the pager and return control to your `cmd2` application.
52+
!!! warning
53+
54+
Once you are in a terminal pager, that program temporarily has control of your terminal,
55+
**NOT** `cmd2`. Typically you can use either the arrow keys or `<PageUp>`/`<PageDown>` keys to
56+
scroll around or type `q` to quit the pager and return control to your `cmd2` application.
4957

5058
## Exit codes
5159

@@ -87,10 +95,10 @@ shell, and execute those commands before entering the command loop:
8795

8896
$ python examples/transcript_example.py help
8997

90-
Documented commands (use 'help -v' for verbose/'help <topic>' for details):
91-
===========================================================================
92-
alias help macro orate quit run_script set shortcuts
93-
edit history mumble py run_pyscript say shell speak
98+
Documented Commands
99+
───────────────────
100+
alias help macro orate run_pyscript say shell speak
101+
edit history mumble quit run_script set shortcuts
94102

95103
(Cmd)
96104

@@ -111,8 +119,9 @@ shell, but have it say it in pig latin:
111119
Uh-oh, that's not what we wanted. `cmd2` treated `-p`, `hello`, and `there` as commands, which don't
112120
exist in that program, thus the syntax errors.
113121

114-
There is an easy way around this, which is demonstrated in `examples/cmd_as_argument.py`. By setting
115-
`allow_cli_args=False` you can do your own argument parsing of the command line:
122+
There is an easy way around this, which is demonstrated in
123+
[cmd_as_argument.py](https://github.com/python-cmd2/cmd2/blob/main/examples/cmd_as_argument.py)
124+
example. By setting `allow_cli_args=False` you can do your own argument parsing of the command line:
116125

117126
$ python examples/cmd_as_argument.py speak -p hello there
118127
ellohay heretay

docs/features/packaging.md

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ using idiomatic Python packaging tools such as [pip](https://pip.pypa.io/) or
1616
[uv](https://github.com/astral-sh/uv).
1717

1818
Small tweaks on this process can allow you to publish to private PyPI mirrors such as one hosted on
19-
[AWS CodeArtifact](https://aws.amazon.com/codeartifact/).
19+
[AWS CodeArtifact](https://aws.amazon.com/codeartifact/) or a private
20+
[Artifactory](https://jfrog.com/artifactory/) server.
2021

2122
## Packaging your application in a container using Docker
2223

@@ -33,26 +34,18 @@ This convenient blog post will show you
3334
For developers wishing to package a `cmd2` application into a single binary image or compressed
3435
file, we can recommend all of the following based on personal and professional experience:
3536

37+
- [Nuitka](https://github.com/Nuitka/Nuitka)
38+
- Nuitka is a Python compiler written in Python
39+
- You feed it your Python app, it does a lot of clever things, and spits out an executable or
40+
extension module
41+
- Particularly convenient if you have IP you wish to protect by obfuscating the Python source
42+
code behind your application
3643
- [PyInstaller](https://www.pyinstaller.org)
3744
- Freeze (package) Python programs into stand-alone executables
3845
- PyInstaller bundles a Python application and all its dependencies into a single package
3946
- The user can run the packaged app without installing a Python interpreter or any modules
40-
- [Nuitka](https://nuitka.net)
41-
- Nuitka is a Python compiler written in Python
42-
- You feed it your Python app, it does a lot of clever things, and spits out an executable or
43-
extension module
44-
- This can be particularly convenient if you wish to obfuscate the Python source code behind
45-
your application
46-
- [Conda Constructor](https://github.com/conda/constructor)
47-
- Allows you to create a custom Python distro based on
48-
[Miniconda](https://docs.conda.io/en/latest/miniconda.html)
4947
- [PyOxidizer](https://github.com/indygreg/PyOxidizer)
50-
- PyOxidizer is a utility for producing binaries that embed Python
51-
- PyOxidizer is capable of producing a single file executable - with a copy of Python and all
52-
its dependencies statically linked and all resources embedded in the executable
48+
- A modern Python application packaging and distribution tool implemented in Rust
49+
- A utility for producing binaries that embed Python and all of your dependencies
5350
- You can copy a single executable file to another machine and run a Python application
5451
contained within. It just works.
55-
56-
!!! warning
57-
58-
We haven't personally tested PyOxidizer with `cmd2` applications like everything else on this page, though we have heard good things about it

docs/features/plugins.md

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ extend basic `cmd2` functionality and can be used by multiple applications.
66
There are many ways to add functionality to `cmd2` using a plugin. Most plugins will be implemented
77
as a mixin. A mixin is a class that encapsulates and injects code into another class. Developers who
88
use a plugin in their `cmd2` project will inject the plugin's code into their subclass of
9-
`cmd2.Cmd`.
9+
[cmd2.Cmd][].
1010

1111
## Mixin and Initialization
1212

@@ -38,15 +38,17 @@ class Example(cmd2_myplugin.MyPlugin, cmd2.Cmd):
3838
# all plugins have initialized
3939
```
4040

41-
Note how the plugin must be inherited (or mixed in) before `cmd2.Cmd`. This is required for two
42-
reasons:
41+
!!! warning
4342

44-
- The `cmd.Cmd.__init__` method in the Python standard library does not call `super().__init__()`.
45-
Because of this oversight, if you don't inherit from `MyPlugin` first, the `MyPlugin.__init__()`
46-
method will never be called.
47-
- You may want your plugin to be able to override methods from `cmd2.Cmd`. If you mixin the plugin
48-
after `cmd2.Cmd`, the Python method resolution order will call [cmd2.Cmd][] methods before it
49-
calls those in your plugin.
43+
The plugin must be inherited (or mixed in) before `cmd2.Cmd`. This is required for two
44+
reasons:
45+
46+
- The `cmd.Cmd.__init__` method in the Python standard library does not call `super().__init__()`.
47+
Because of this oversight, if you don't inherit from `MyPlugin` first, the `MyPlugin.__init__()`
48+
method will never be called.
49+
- You may want your plugin to be able to override methods from `cmd2.Cmd`. If you mixin the plugin
50+
after `cmd2.Cmd`, the Python method resolution order will call [cmd2.Cmd][] methods before it
51+
calls those in your plugin.
5052

5153
## Add commands
5254

@@ -77,7 +79,7 @@ class MyPlugin:
7779
self.add_settable(cmd2.Settable('mysetting', str, 'short help message for mysetting', self))
7880
```
7981

80-
You can hide settings from the user by calling `cmd2.Cmd.remove_settable`. See
82+
You can hide settings from the user by calling [cmd2.Cmd.remove_settable][]. See
8183
[Settings](./settings.md) for more information.
8284

8385
## Decorators
@@ -97,8 +99,9 @@ Hooks are a much better approach.
9799
## Hooks
98100

99101
Plugins can register hook methods, which are called by [cmd2.Cmd][] during various points in the
100-
application and command processing lifecycle. Plugins should not override any of the deprecated hook
101-
methods, instead they should register their hooks as described in the [Hooks](./hooks.md) section.
102+
application and command processing lifecycle. Plugins should not override any of the `cmd` base
103+
class hook methods, instead they should register their hooks as described in the [Hooks](./hooks.md)
104+
section.
102105

103106
You should name your hooks so that they begin with the name of your plugin. Hook methods get mixed
104107
into the `cmd2` application and this naming convention helps avoid unintentional method overriding.
@@ -134,4 +137,5 @@ will know what's available.
134137

135138
## Examples
136139

137-
See <https://github.com/python-cmd2/cmd2-plugin-template> for more info.
140+
See [cmd2 Plugin Template](https://github.com/python-cmd2/cmd2/tree/main/plugins/template) for more
141+
info.

docs/features/prompt.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,35 +4,35 @@
44

55
## Customizing the Prompt
66

7-
This prompt can be configured by setting the `cmd2.Cmd.prompt` instance attribute. This contains the
8-
string which should be printed as a prompt for user input. See the
9-
[getting_started](https://github.com/python-cmd2/cmd2/blob/main/examples/getting_started.py) example
10-
for the simple use case of statically setting the prompt.
7+
This prompt can be configured by setting the [cmd2.Cmd.prompt][] instance attribute. This contains
8+
the string which should be printed as a prompt for user input. See the
9+
[getting_started.py](https://github.com/python-cmd2/cmd2/blob/main/examples/getting_started.py)
10+
example for the simple use case of statically setting the prompt.
1111

1212
## Continuation Prompt
1313

1414
When a user types a [Multiline Command](./multiline_commands.md) it may span more than one line of
1515
input. The prompt for the first line of input is specified by the `cmd2.Cmd.prompt` instance
1616
attribute. The prompt for subsequent lines of input is defined by the `cmd2.Cmd.continuation_prompt`
1717
attribute. See the
18-
[getting_started](https://github.com/python-cmd2/cmd2/blob/main/examples/getting_started.py) example
19-
for a demonstration of customizing the continuation prompt.
18+
[getting_started.py](https://github.com/python-cmd2/cmd2/blob/main/examples/getting_started.py)
19+
example for a demonstration of customizing the continuation prompt.
2020

2121
## Updating the prompt
2222

2323
If you wish to update the prompt between commands, you can do so using one of the
2424
[Application Lifecycle Hooks](./hooks.md#application-lifecycle-hooks) such as a
2525
[Postcommand hook](./hooks.md#postcommand-hooks). See
26-
[PythonScripting](https://github.com/python-cmd2/cmd2/blob/main/examples/python_scripting.py) for an
27-
example of dynamically updating the prompt.
26+
[python_scripting.py](https://github.com/python-cmd2/cmd2/blob/main/examples/python_scripting.py)
27+
for an example of dynamically updating the prompt.
2828

2929
## Asynchronous Feedback
3030

3131
`cmd2` provides these functions to provide asynchronous feedback to the user without interfering
3232
with the command line. This means the feedback is provided to the user when they are still entering
3333
text at the prompt. To use this functionality, the application must be running in a terminal that
34-
supports VT100 control characters and readline. Linux, Mac, and Windows 10 and greater all support
35-
these.
34+
supports [VT100](https://en.wikipedia.org/wiki/VT100) control characters and `readline`. Linux, Mac,
35+
and Windows 10 and greater all support these.
3636

3737
::: cmd2.Cmd.async_alert
3838

@@ -49,5 +49,5 @@ Windows 10 and greater all support these.
4949
::: cmd2.Cmd.set_window_title
5050

5151
The easiest way to understand these functions is to see the
52-
[AsyncPrinting](https://github.com/python-cmd2/cmd2/blob/main/examples/async_printing.py) example
53-
for a demonstration.
52+
[async_printing.py](https://github.com/python-cmd2/cmd2/blob/main/examples/async_printing.py)
53+
example for a demonstration.

docs/features/redirection.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,9 @@ output of that to a file called _output.txt_.
5858

5959
## Limitations of Redirection
6060

61-
Some limitations apply to redirection and piping within `cmd2` applications:
61+
!!! warning
6262

63-
- Can only pipe to shell commands, not other `cmd2` application commands
64-
- **stdout** gets redirected/piped, **stderr** does not
63+
Some limitations apply to redirection and piping within `cmd2` applications:
64+
65+
- Can only pipe to shell commands, not other `cmd2` application commands
66+
- **stdout** gets redirected/piped, **stderr** does not

0 commit comments

Comments
 (0)