A Python CLI framework with self-spacing components and Rich theming
Project description
Clicycle
A Python CLI framework with self-spacing components and Rich theming
Clicycle is a modern Python CLI framework that provides a simple functional API and powerful component-based system for building beautiful command-line interfaces.
It features automatic spacing, Rich theming, and an intuitive API that lets you focus on your application's logic instead of its presentation.
Features
- Simple Functional API - Import and use functions directly (e.g.,
clicycle.info()). - Rich theming - Comprehensive styling with icons, typography, and layout controls.
- Automatic spacing - Components manage their own spacing like HTML elements.
- Customizable indentation - Per-component indentation control for perfect alignment.
- Component-based - Familiar React/HTML-like API with composable components.
- Type-safe - Full type hints and IDE support.
- Smart tables - Automatically sized columns with intelligent formatting.
- Code highlighting - Syntax-highlighted code blocks with line numbers.
- Progress tracking - Built-in progress bars and spinners.
- Interactive prompts - Properly spaced input prompts and confirmations.
- 100% test coverage - Thoroughly tested for reliability.
Installation
pip install clicycle
Quick Start
Get started in seconds with Clicycle's functional API.
import clicycle
import time
# (Optional) Configure the app name and theme once
clicycle.configure(app_name="MyApp")
# Display a header
clicycle.header("Welcome", "Getting started with Clicycle")
# Show different message types
clicycle.info("This is an info message")
clicycle.success("Operation completed successfully!")
clicycle.warning("This is a warning")
clicycle.error("Something went wrong")
# Display a table
data = [
{"Name": "Alice", "Age": 30, "City": "New York"},
{"Name": "Bob", "Age": 25, "City": "San Francisco"},
]
clicycle.table(data, title="User Information")
# Show code with syntax highlighting
code_snippet = '''
def hello_world():
print("Hello, Clicycle!")
'''
clicycle.code(code_snippet, language="python", title="Example Code")
# Use a spinner for long-running operations
with clicycle.spinner("Processing..."):
time.sleep(2)
# Interactive prompts
name = clicycle.prompt("What's your name?")
if clicycle.confirm("Do you want to continue?"):
clicycle.success(f"Great, let's proceed, {name}!")
How to Use Clicycle
Clicycle offers two ways to build your CLI: a simple functional API for most use cases and an object-oriented API for advanced scenarios.
1. Functional API (Recommended)
This is the easiest way to use Clicycle. Simply import the functions you need and call them. A global Clicycle instance is managed for you.
Configuration
Call clicycle.configure() at the start of your app to set a global app name or theme.
import clicycle
from clicycle import Theme
# Set a custom app name to appear in headers
clicycle.configure(app_name="My Awesome App")
# Or configure a full theme
custom_theme = Theme() # Fill with your theme options
clicycle.configure(theme=custom_theme)
Usage
import clicycle
clicycle.header("My App")
clicycle.info("Starting process...")
2. Object-Oriented API
For advanced use cases, such as managing multiple, separate CLI outputs with different themes, you can instantiate the Clicycle class directly.
from clicycle import Clicycle, Theme
# Create a custom instance for a specific task
reporter_theme = Theme() # Fill with your theme options
reporter_cli = Clicycle(theme=reporter_theme)
reporter_cli.info("Reporting task status...")
# Use the default API for other tasks
clicycle.info("This uses the default global instance.")
Components
All components are available through the functional API.
Headers and Sections
import clicycle
# Main header with optional app branding
clicycle.header("Main Title", "Optional subtitle")
# Section dividers
clicycle.section("Configuration")
Text Messages
import clicycle
# Different message types with automatic icons
clicycle.info("Information message")
clicycle.success("Success message")
clicycle.warning("Warning message")
clicycle.error("Error message")
clicycle.debug("Debug message") # Only shown in verbose mode
# List items
clicycle.list_item("First item")
clicycle.list_item("Second item")
Tables
import clicycle
data = [
{"Name": "Alice", "Score": 95},
{"Name": "Bob", "Score": 87},
]
# Simple table
clicycle.table(data)
# Table with title
clicycle.table(data, title="Test Results")
Code Display
import clicycle
# Python code with line numbers
clicycle.code('''
def fibonacci(n):
if n <= 1:
return n
return fibonacci(n-1) + fibonacci(n-2)
''', language="python", title="Fibonacci Function")
# JSON data
clicycle.json({"name": "Alice", "age": 30}, title="User Data")
Progress and Spinners
import clicycle
import time
# Simple spinner
with clicycle.spinner("Loading data..."):
time.sleep(2)
# Progress bar
with clicycle.progress("Processing files") as p:
for i in range(100):
p.update_progress(i, f"Processing file {i}")
time.sleep(0.02)
Interactive Prompts
import clicycle
from clicycle import select_from_list
# Basic prompts
name = clicycle.prompt("Enter your name")
age = clicycle.prompt("Enter your age", type=int)
confirmed = clicycle.confirm("Are you sure?")
# Selection from a list
option = select_from_list(
item_name="environment",
options=["development", "staging", "production"],
default="development",
)
Grouping with Blocks
import clicycle
# Group related content
clicycle.section("User Information")
with clicycle.block():
clicycle.info("Processing user data...")
clicycle.success("User validated")
clicycle.info("Creating profile...")
Summary Data
import clicycle
# Key-value summaries
summary_data = [
{"label": "Total Files", "value": 1250},
{"label": "Success Rate", "value": "96%"},
]
clicycle.summary(summary_data)
Theming
Clicycle's theming is highly customizable. You can pass a Theme object to clicycle.configure() or a Clicycle instance.
from clicycle import Theme, Icons, Typography, ComponentIndentation, configure
# Create a custom theme
custom_theme = Theme(
icons=Icons(
success="✅",
error="❌",
),
typography=Typography(
header_style="bold magenta",
info_style="bold blue",
),
indentation=ComponentIndentation(
list=4, # 4 spaces for list items
success=2, # 2 spaces for success messages
error=0, # No indentation for errors
)
)
# Apply the theme globally
configure(theme=custom_theme)
# Now all functional calls will use the new theme
clicycle.success("Theme updated successfully!")
clicycle.list_item("This will be indented 4 spaces")
Advanced Usage
Integration with Click
Clicycle works seamlessly with Click. The debug function automatically respects Click's verbose flag.
import click
import clicycle
@click.command()
@click.option('--verbose', '-v', is_flag=True, help="Enable verbose output.")
def main(verbose):
# This is a basic example. For robust integration,
# you might pass the verbose flag through the click context object.
if verbose:
# A simple way to let clicycle know about verbosity
# is to configure it or handle it in your logic.
# For this example, we'll just print a warning message.
clicycle.warning("Verbose mode enabled.")
clicycle.configure(app_name="MyApp")
clicycle.header("My Application", "Version 1.0")
clicycle.info("Application started")
clicycle.debug("This will only show if --verbose is used.")
if __name__ == '__main__':
main()
You can access the verbose flag in your Click command by using the click.get_current_context() function.
import click
@click.command()
@click.option('--verbose', '-v', is_flag=True, help="Enable verbose output.")
def main(verbose):
context = click.get_current_context()
if context.params.get('verbose'):
clicycle.warning("Verbose mode enabled.")
# more logic here
API Reference
Top-Level Functions
These functions are available for direct import from clicycle.
configure(app_name: str, theme: Theme)- Configure the global instance.header(title: str, subtitle: str, app_name: str)- Display header.section(title: str)- Display section divider.info/success/warning/error/debug(message: str)- Display styled messages.table(data: list[dict], title: str)- Display data table.code(code: str, language: str, title: str)- Display code.json(data: dict, title: str)- Display JSON data.summary(data: list[dict])- Display key-value summary.list_item(item: str)- Display list item.prompt(text: str, **kwargs)- Interactive prompt.confirm(text: str, **kwargs)- Interactive confirmation.spinner(message: str)- Context manager for spinner.progress(description: str)- Context manager for progress bar.block()- Context manager for grouping components.clear()- Clear terminal and reset.
Clicycle Class
For advanced use, you can create separate instances.
from clicycle import Clicycle
cli = Clicycle(width: int = 100, theme: Theme | None = None, app_name: str | None = None)
The methods on the Clicycle class instance mirror the top-level functions.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file clicycle-1.1.2.tar.gz.
File metadata
- Download URL: clicycle-1.1.2.tar.gz
- Upload date:
- Size: 29.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bb8adf683e2cfde39341b6ff78c8417b96f48dbd659b51e3151311f5ed766f2a
|
|
| MD5 |
835b1410ab737883cedf21e8e9275065
|
|
| BLAKE2b-256 |
903e195441be53fb38accf43edcdafbe77f491e3f50d98efbaf1610c50670b8b
|
Provenance
The following attestation bundles were made for clicycle-1.1.2.tar.gz:
Publisher:
publish.yml on Living-Content/clicycle
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
clicycle-1.1.2.tar.gz -
Subject digest:
bb8adf683e2cfde39341b6ff78c8417b96f48dbd659b51e3151311f5ed766f2a - Sigstore transparency entry: 345366796
- Sigstore integration time:
-
Permalink:
Living-Content/clicycle@60c0e757458a7f831b4a410de85714c0da431423 -
Branch / Tag:
refs/tags/v1.1.2 - Owner: https://github.com/Living-Content
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@60c0e757458a7f831b4a410de85714c0da431423 -
Trigger Event:
release
-
Statement type:
File details
Details for the file clicycle-1.1.2-py3-none-any.whl.
File metadata
- Download URL: clicycle-1.1.2-py3-none-any.whl
- Upload date:
- Size: 15.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c98e899886e6b8d3d5893b7d5bfbc80e6fca5e8b5bcfddc46d32162e0be63790
|
|
| MD5 |
c9e76a5fa024d8fea9fff3c3025c3492
|
|
| BLAKE2b-256 |
1eee39c6be7a9d5de8f433de38d9c1e33f18fc1f4ae80a08e9b8fbd004bc089d
|
Provenance
The following attestation bundles were made for clicycle-1.1.2-py3-none-any.whl:
Publisher:
publish.yml on Living-Content/clicycle
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
clicycle-1.1.2-py3-none-any.whl -
Subject digest:
c98e899886e6b8d3d5893b7d5bfbc80e6fca5e8b5bcfddc46d32162e0be63790 - Sigstore transparency entry: 345366798
- Sigstore integration time:
-
Permalink:
Living-Content/clicycle@60c0e757458a7f831b4a410de85714c0da431423 -
Branch / Tag:
refs/tags/v1.1.2 - Owner: https://github.com/Living-Content
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@60c0e757458a7f831b4a410de85714c0da431423 -
Trigger Event:
release
-
Statement type: