A modern interactive command-line application building library based on prompt_toolkit
Language: English/δΈζ
- π Built on prompt_toolkit for powerful interactive experiences
- π Automatic parameter parsing and completion
- π Rich text output support (using rich library)
- β‘ Native async command support
- π Built-in command completion and shortcut keys
Install from PyPI:
pip install ptcmd
Or install from source:
git clone https://github.com/Visecy/ptcmd.git
cd ptcmd
make install
Create a simple command-line application:
import sys
from ptcmd import Cmd
class MyApp(Cmd):
def do_hello(self, argv: list[str]) -> None:
"""Hello World!"""
if argv:
name = argv[0]
else:
name = "World"
self.poutput(f"Hello, {name}!")
if __name__ == "__main__":
sys.exit(MyApp().cmdloop())
In this basic example:
- We create a
MyApp
class inheriting fromCmd
- Define a
do_hello
command method - The command accepts an optional name parameter
- Uses "World" if no parameter is provided
- Output greeting using
self.poutput()
- Start the CLI with
cmdloop()
This example demonstrates:
- Command definition syntax
- Parameter handling
- Output display
- Application startup process
Run the program and try the hello
command:
(Cmd) hello
Hello, World!
(Cmd) hello Alice
Hello, Alice!
For complex commands, use the auto_argument
decorator with type hints for automatic argument parsing:
from ptcmd import Cmd, Arg, auto_argument
class MathApp(Cmd):
@auto_argument
def do_add(
self,
x: float,
y: float,
*,
verbose: Arg[bool, "-v", "--verbose"] = False
) -> None:
"""Add two numbers"""
result = x + y
if verbose:
self.poutput(f"{x} + {y} = {result}")
else:
self.poutput(result)
This approach automatically generates equivalent argparse code:
- Converts positional parameters to required arguments
- Converts keyword parameters to optional flags
- Handles type conversion and validation
Leverage rich library for styled output:
class RichApp(Cmd):
def do_hello(self, argv: list[str]) -> None:
self.poutput(f"[bold blue]Hello, World![/bold blue]")
For advanced formatting, access the console directly:
class RichApp(Cmd):
def do_hello(self, argv: list[str]) -> None:
with self.console.pager(styles=True):
self.console.print("Hello, World!", style="bold blue")
For command functions that use the automatic parameter parsing feature, ptcmd
allows you to add any number of sub-commands to them in a simple way. The execution order of command functions is starting from the root command and then executing them one by one.
- Single-level subcommand example:
from ptcmd import Cmd, auto_argument
class App(Cmd):
@auto_argument
def do_math(self):
"""Math operations"""
@do_math.add_subcommand("add")
def add(self, x: float, y: float):
"""Addition"""
self.poutput(f"{x} + {y} = {x + y}")
Usage examples:
(Cmd) math add 5 3
5.0 + 3.0 = 8.0
(Cmd) math sub 5 3
5.0 - 3.0 = 2.0
- Multi-level subcommand example:
from ptcmd import Cmd, auto_argument
class App(Cmd):
@auto_argument
def do_server(self):
"""Server management"""
@do_server.add_subcommand("db")
def db(self):
"""Database management"""
@db.add_subcommand("migrate")
def migrate(self, version: str):
"""Execute database migration"""
self.poutput(f"Migrating to version {version}...")
@do_server.add_subcommand("cache")
def cache(self):
"""Cache management"""
@cache.add_subcommand("clear")
def clear(self, confirm: bool = False):
"""Clear cache"""
if confirm:
self.poutput("Cache cleared")
else:
self.poutput("Please add --confirm to proceed")
Usage examples:
(Cmd) server db migrate v1.2.0
Migrating to version v1.2.0...
(Cmd) server cache clear --confirm
Cache cleared
Native async/await support for I/O bound operations:
import aiohttp
from ptcmd import Cmd, auto_argument
class AsyncApp(Cmd):
@auto_argument
async def do_get(self, url: str):
"""Fetch URL content"""
async with aiohttp.ClientSession() as session:
async with session.get(url) as resp:
self.poutput(await resp.text(), markup=False)
Feature | cmd (stdlib) | cmd2 | ptcmd |
---|---|---|---|
Rich Output | No | Basic | Rich library support |
Auto Completion | No | Yes | Yes |
Argument Parsing | Manual | argparse | Automatic |
Async Support | No | No | Native |
Dependencies | None | Several | Most |
Learning Curve | Simple | Moderate | Moderate |
Use Case | Simple CLI | Traditional CLI | Modern Interactive CLI |
Key Advantages:
- cmd: Standard library, no dependencies
- cmd2: Feature-rich traditional CLI
- ptcmd: Modern interactive experience with best-in-class UX
- prompt_toolkit - Foundation for building powerful interactive command lines
- rich - Enables rich text formatting and beautiful output
- typer - Modern CLI framework with type hints
- cmd2 - Inspiration for many ptcmd features
- argparse - Python's standard argument parsing library
- cmd2 for inspiring the command completion system
- Cline for assisting with project documentation and test cases
Apache License 2.0 - See LICENSE