Skip to content

Examples

Here's some basic usage examples to start off of.

Simple Command

The most basic command is a function with a context parameter:

tools/hello.py
from __future__ import annotations

from toolr import Context
from toolr import command_group

group = command_group("greeting", "Greeting Commands", "Commands for greeting users")


@group.command
def hello(ctx: Context, name: str = "World"):
    """Say hello.

    Args:
        name: The name of the person to greet.
    """
    ctx.info("Hello", name, "!")

Run with:

toolr greeting hello --name Alice
# Output: Hello, Alice!

Command with Multiple Arguments

tools/calculator.py
from __future__ import annotations

from toolr import Context
from toolr import command_group

group = command_group("math", "Math Commands", "Basic mathematical operations")


@group.command
def add(ctx: Context, a: int, b: int):
    """Add two numbers together.

    Args:
        a: First number.
        b: Second number.
    """
    result = a + b
    ctx.info(f"{a} + {b} = {result}")
    return result

Run with:

toolr math add 5 3
# Output: 5 + 3 = 8

Boolean Flags

tools/example.py
from __future__ import annotations

from toolr import Context
from toolr import command_group

group = command_group("example", "Example Commands", "Example command group")


@group.command
def process(ctx: Context, verbose: bool = False, dry_run: bool = False):
    """Process something with optional flags.

    Args:
        verbose: Whether to print verbose output.
        dry_run: Whether to perform a dry run (no changes will be made).
    """
    if verbose:
        ctx.info("Verbose mode enabled")

    if dry_run:
        ctx.info("Dry run mode - no changes will be made")
        return

    ctx.info("Processing...")

Run with:

toolr example process --verbose --dry-run
# Output: Verbose mode enabled
#         Dry run mode - no changes will be made

List Arguments

tools/files.py
from __future__ import annotations

from toolr import Context
from toolr import command_group

group = command_group("files", "File Commands", "File operations")


@group.command
def process_files(ctx: Context, files: list[str]):
    """Process multiple files.

    Args:
        files: The files to process.
    """
    for file in files:
        ctx.info(f"Processing {file}...")

Run with:

toolr files process-files file1.txt file2.txt file3.txt
# Output: Processing file1.txt...
#         Processing file2.txt...
#         Processing file3.txt...

The above command could also be defined like:

tools/files.py
from __future__ import annotations

from toolr import Context
from toolr import command_group

group = command_group("files", "File Commands", "File operations")


@group.command
def process_files(ctx: Context, *files: str):
    """Process multiple files.

    Args:
        files: The files to process.
    """
    for file in files:
        ctx.info(f"Processing {file}...")

Using the Context

The ctx parameter provides access to useful utilities:

tools/system.py
from __future__ import annotations

from toolr import Context
from toolr import command_group

group = command_group("system", "System Commands", "System operations")


@group.command
def info(ctx: Context) -> None:
    """Show system information.

    Displays repository root, Python version, and other system details.
    """
    # Access the repository root
    ctx.info(f"Repository root: {ctx.repo_root}")

    # Run a command
    result = ctx.run("python", "--version", capture_output=True, stream_output=False)
    ctx.info("Python version", result.stdout.read().strip())

    # Rich console output formatting available
    ctx.print("[bold green]System info retrieved successfully![/bold green]")


@group.command
def check_disk(ctx: Context, path: str = ".") -> None:
    """Check disk usage for a path.

    Args:
        path: The path to check disk usage for. Defaults to current directory.
    """
    # Run command with error handling
    try:
        result = ctx.run("du", "-sh", path, capture_output=True, stream_output=False)
        if result.returncode == 0:
            ctx.print(f"[green]Disk usage for {path}: {result.stdout.read().strip()}[/green]")
        else:
            ctx.error(f"Failed to check disk usage: {result.stderr.read().strip()}")
    except Exception as e:
        ctx.error(f"Error checking disk usage: {e}")


@group.command
def network_test(ctx: Context, host: str = "8.8.8.8", count: int = 3) -> None:
    """Test network connectivity to a host.

    Args:
        host: The host to test connectivity to. Defaults to Google's DNS (8.8.8.8).
        count: Number of ping packets to send. Defaults to 3.
    """
    ctx.info(f"Testing connectivity to {host}")

    result = ctx.run("ping", "-c", count, host, capture_output=True, stream_output=False)

    if result.returncode == 0:
        ctx.print(f"[green]Network connectivity to {host} is working[/green]")
        # Extract ping statistics
        lines = result.stdout.read().decode().split("\n")
        for line in lines:
            if "packets transmitted" in line:
                ctx.info(f"Ping statistics: {line.strip()}")
    else:
        ctx.error(f"Network connectivity to {host} failed")

Run with:

toolr system info

Function Name Conversion

ToolR automatically converts Python function names with underscores to command names with hyphens:

tools/function_names.py
"""Example demonstrating function name to command name conversion.

This example shows how function names with underscores are automatically converted
to command names with hyphens when using the @command decorator without specifying
a name.
"""

from __future__ import annotations

from toolr import Context
from toolr import command_group

# Create a command group
tools = command_group(
    "names",
    "Examples for function name to command name conversion",
    "Various examples for function name to command name conversion",
)


# Define commands using function names - they will be automatically converted
@tools.command
def simple_function(ctx: Context) -> None:  # -> simple-function
    """A simple function."""


@tools.command
def function_with_underscores(ctx: Context) -> None:  # -> function-with-underscores
    """A function with underscores in the name."""


@tools.command
def multiple_underscores_in_name(ctx: Context) -> None:  # -> multiple-underscores-in-name
    """A function with multiple underscores."""


@tools.command
def _leading_underscore(ctx: Context) -> None:  # -> -leading-underscore
    """A function with a leading underscore."""


@tools.command
def trailing_underscore_(ctx: Context) -> None:  # -> trailing-underscore-
    """A function with a trailing underscore."""


@tools.command
def _both_underscores_(ctx: Context) -> None:  # -> -both-underscores-
    """A function with both leading and trailing underscores."""

This example demonstrates how function names like function_with_underscores become command names like function-with-underscores in the CLI.

toolr names -h
Usage: toolr names [-h] {simple-function,function-with-underscores,multiple-underscores-in-name,-leading-underscore,trailing-underscore-,-both-underscores-} ...

Various examples for function name to command name conversion

Options:
  -h, --help            show this help message and exit

Examples For Function Name To Command Name Conversion:
  Various examples for function name to command name conversion

  {simple-function,function-with-underscores,multiple-underscores-in-name,-leading-underscore,trailing-underscore-,-both-underscores-}
    simple-function     A simple function.
    function-with-underscores
                        A function with underscores in the name.
    multiple-underscores-in-name
                        A function with multiple underscores.
    -leading-underscore
                        A function with a leading underscore.
    trailing-underscore-
                        A function with a trailing underscore.
    -both-underscores-  A function with both leading and trailing underscores.