Format click help output nicely with rich
—
Rich-Click CLI tool for enhancing external Click applications with rich formatting without modifying their source code. The CLI tool allows you to run any Click-based command-line application with Rich-Click's enhanced formatting by prefixing the command with rich-click.
The primary entry point for the Rich-Click command-line interface tool.
def main(
ctx: RichContext,
script_and_args: List[str],
output: Literal[None, "html", "svg"],
errors_in_output_format: bool,
suppress_warnings: bool,
rich_config: Optional[RichHelpConfiguration],
show_help: bool,
) -> None:
"""
Rich-click CLI command entry point.
The rich-click CLI provides attractive help output from any tool using click,
formatted with rich. The command line tool can be prepended before any Python
package using native click to provide attractive richified click help output.
Parameters:
- ctx (RichContext): Rich context object
- script_and_args (List[str]): Script name and arguments to execute
- output (Literal[None, "html", "svg"], optional): Output format for help text (html/svg)
- errors_in_output_format (bool): Whether to format errors in output format
- suppress_warnings (bool): Whether to suppress entry point warnings
- rich_config (RichHelpConfiguration, optional): Rich configuration to apply
- show_help (bool): Whether to show help message
Examples:
- rich-click my_package --help
- rich-click my_module:my_function --version
- rich-click --output html my_app --help > help.html
"""Command-line options and configuration for the Rich-Click CLI tool.
The CLI tool is configured with the following options:
# Basic usage
rich-click [OPTIONS] [SCRIPT | MODULE:CLICK_COMMAND] [-- SCRIPT_ARGS...]
# Options:
--rich-config, -c JSON # Rich configuration (JSON or @file.json)
--output, -o [html|svg] # Output format (html or svg)
--errors-in-output-format # Format errors in output format
--suppress-warnings # Suppress entry point warnings
--help, -h # Show help messageFunctions for resolving and executing Click commands from various sources.
def entry_points(*, group: str) -> "metadata.EntryPoints":
"""
Entry points function compatible with Python 3.7+.
Provides consistent entry point access across Python versions,
handling differences in the importlib.metadata API.
Parameters:
- group (str): Entry point group name (e.g., 'console_scripts')
Returns:
metadata.EntryPoints: Collection of entry points for the group
"""
def _get_module_path_and_function_name(script: str, suppress_warnings: bool) -> Tuple[str, str]:
"""
Parse script reference to module path and function name.
Resolves script names to module paths and function names, handling
both console_scripts entry points and direct module:function references.
Parameters:
- script (str): Script name or module:function reference
- suppress_warnings (bool): Whether to suppress duplicate warnings
Returns:
Tuple[str, str]: Module path and function name
Raises:
- ClickException: If script cannot be resolved
Examples:
- "mypackage" -> ("mypackage.cli", "main")
- "mymodule:myfunc" -> ("mymodule", "myfunc")
"""Custom Click parameter types used by the CLI tool.
class _RichHelpConfigurationParamType(click.ParamType):
"""
Click parameter type for RichHelpConfiguration.
Handles JSON configuration input from command line arguments,
supporting both inline JSON and file references (@file.json).
Attributes:
- name: str = "JSON"
"""
def convert(
self,
value: Optional[Union[RichHelpConfiguration, str]],
param: Optional[click.Parameter],
ctx: Optional[click.Context],
) -> Optional[RichHelpConfiguration]:
"""
Convert parameter value to RichHelpConfiguration.
Parameters:
- value (Union[RichHelpConfiguration, str, None]): Input value
- param (click.Parameter, optional): Parameter object
- ctx (click.Context, optional): Click context
Returns:
Optional[RichHelpConfiguration]: Parsed configuration
Supports:
- Direct JSON: '{"style_option": "bold red"}'
- File reference: '@config.json'
- None value: Returns None
- Existing RichHelpConfiguration: Returns as-is
Raises:
- Exception: If JSON parsing fails or file not found
"""Common usage patterns for the Rich-Click CLI tool:
# Enhance any Click-based tool
rich-click mypackage --help
# Run specific module function
rich-click mymodule:main --version
# Pass arguments to the target command
rich-click myapp -- --config config.json --verbose# Export help as HTML
rich-click --output html myapp --help > help.html
# Export help as SVG
rich-click --output svg myapp --help > help.svg
# Include errors in output format
rich-click --output html --errors-in-output-format myapp --invalid-option# Use inline JSON configuration
rich-click --rich-config '{"style_option": "bold red"}' myapp --help
# Use configuration file
rich-click --rich-config @rich_config.json myapp --help
# Configuration file example (rich_config.json):
{
"style_option": "bold blue",
"style_command": "bold green",
"show_arguments": true,
"options_panel_title": "Available Options"
}# Suppress duplicate entry point warnings
rich-click --suppress-warnings myapp --help
# Chain with other commands
rich-click myapp --help | less
# Use in scripts
#!/bin/bash
if command -v rich-click >/dev/null 2>&1; then
rich-click myapp "$@"
else
myapp "$@"
fiThe CLI tool provides comprehensive error handling for various scenarios:
# Entry point resolution errors
try:
module_path, function_name = _get_module_path_and_function_name(script, suppress_warnings)
module = import_module(module_path)
except (ModuleNotFoundError, ClickException):
# Fallback: add current directory to Python path and retry
sys.path.append(os.path.abspath("."))
module_path, function_name = _get_module_path_and_function_name(script, suppress_warnings)
module = import_module(module_path)
# Configuration errors
try:
data = json.loads(config_string)
if not isinstance(data, dict):
raise ValueError("Configuration must be a JSON object")
return RichHelpConfiguration.load_from_globals(**data)
except Exception as e:
if ctx and ctx.params.get("show_help", False):
# Show help if configuration fails during help display
click.echo(ctx.get_help(), color=ctx.color)
ctx.exit()
else:
raise eThe CLI tool is designed to work seamlessly with existing Click applications:
# In your setup.py or pyproject.toml
[project.scripts]
myapp = "mypackage.cli:main"
myapp-rich = "rich_click.cli:main mypackage.cli:main"#!/usr/bin/env python3
"""Rich wrapper for existing Click app."""
import sys
from rich_click.cli import main as rich_main
from rich_click import RichContext
if __name__ == '__main__':
# Configure Rich-Click
ctx = RichContext()
sys.argv = ['rich-click', 'mypackage.cli:main'] + sys.argv[1:]
rich_main()"""Application that optionally uses Rich-Click."""
import sys
try:
import rich_click as click
# Patch for enhanced formatting
click.patch()
except ImportError:
import click
@click.command()
@click.option('--name', help='Your name')
def hello(name):
"""Say hello with optional rich formatting."""
click.echo(f'Hello, {name}!')
if __name__ == '__main__':
hello()The CLI tool is available as a console script after installing Rich-Click:
# From pyproject.toml
[project.scripts]
rich-click = "rich_click.cli:main"This enables direct usage from the command line:
pip install rich-click
rich-click --help
rich-click myapp --helpInstall with Tessl CLI
npx tessl i tessl/pypi-rich-click