geronimo.cli.utils
CLI utility functions for consistent output formatting.
Provides styled output helpers, spinners, and common patterns used across all CLI commands.
1"""CLI utility functions for consistent output formatting. 2 3Provides styled output helpers, spinners, and common patterns used 4across all CLI commands. 5""" 6 7from contextlib import contextmanager 8from typing import Optional 9 10from rich.console import Console 11from rich.panel import Panel 12from rich.progress import Progress, SpinnerColumn, TextColumn 13from rich.table import Table 14 15# Shared console instance - use this instead of creating new Console() in each command 16console = Console() 17 18 19def success(message: str) -> None: 20 """Print a success message with green checkmark.""" 21 console.print(f"[green]✓[/green] {message}") 22 23 24def error(message: str, exit_code: Optional[int] = None) -> None: 25 """Print an error message with red X. 26 27 Args: 28 message: Error message to display. 29 exit_code: If provided, raises SystemExit with this code. 30 """ 31 console.print(f"[red]✗[/red] {message}") 32 if exit_code is not None: 33 import typer 34 raise typer.Exit(code=exit_code) 35 36 37def warning(message: str) -> None: 38 """Print a warning message with yellow icon.""" 39 console.print(f"[yellow]⚠[/yellow] {message}") 40 41 42def info(message: str) -> None: 43 """Print an info message with blue icon.""" 44 console.print(f"[blue]ℹ[/blue] {message}") 45 46 47def dim(message: str) -> None: 48 """Print dimmed text for secondary information.""" 49 console.print(f"[dim]{message}[/dim]") 50 51 52def styled_panel( 53 content: str, 54 title: Optional[str] = None, 55 style: str = "blue", 56 border_style: Optional[str] = None, 57) -> None: 58 """Print content in a styled panel. 59 60 Args: 61 content: Panel content (can include rich markup). 62 title: Optional panel title. 63 style: Style for the content (default: blue). 64 border_style: Border color (defaults to style). 65 """ 66 console.print(Panel( 67 content, 68 title=title, 69 border_style=border_style or style, 70 )) 71 72 73def create_table( 74 title: str, 75 columns: list[tuple[str, str]], 76) -> Table: 77 """Create a styled table with predefined column styles. 78 79 Args: 80 title: Table title. 81 columns: List of (name, style) tuples for columns. 82 83 Returns: 84 Configured Table instance (call table.add_row() to add data). 85 86 Example: 87 table = create_table("API Keys", [ 88 ("ID", "dim"), 89 ("Name", "cyan"), 90 ("Status", "green"), 91 ]) 92 table.add_row("key-1", "My Key", "active") 93 console.print(table) 94 """ 95 table = Table(title=title, show_header=True) 96 for name, style in columns: 97 table.add_column(name, style=style) 98 return table 99 100 101@contextmanager 102def status_spinner(message: str): 103 """Show a spinner while performing an operation. 104 105 Args: 106 message: Status message to display. 107 108 Example: 109 with status_spinner("Deploying project..."): 110 deploy_project() 111 """ 112 with Progress( 113 SpinnerColumn(), 114 TextColumn("[progress.description]{task.description}"), 115 console=console, 116 transient=True, 117 ) as progress: 118 progress.add_task(description=message, total=None) 119 yield 120 121 122def confirm_action( 123 message: str, 124 default: bool = False, 125) -> bool: 126 """Prompt user for confirmation. 127 128 Args: 129 message: Confirmation prompt. 130 default: Default value if user just presses Enter. 131 132 Returns: 133 True if user confirmed, False otherwise. 134 """ 135 import typer 136 return typer.confirm(message, default=default) 137 138 139def prompt( 140 message: str, 141 default: Optional[str] = None, 142 hide_input: bool = False, 143) -> str: 144 """Prompt user for input. 145 146 Args: 147 message: Input prompt. 148 default: Default value if user just presses Enter. 149 hide_input: If True, hide input (for passwords/tokens). 150 151 Returns: 152 User input string. 153 """ 154 import typer 155 return typer.prompt(message, default=default, hide_input=hide_input)
20def success(message: str) -> None: 21 """Print a success message with green checkmark.""" 22 console.print(f"[green]✓[/green] {message}")
Print a success message with green checkmark.
25def error(message: str, exit_code: Optional[int] = None) -> None: 26 """Print an error message with red X. 27 28 Args: 29 message: Error message to display. 30 exit_code: If provided, raises SystemExit with this code. 31 """ 32 console.print(f"[red]✗[/red] {message}") 33 if exit_code is not None: 34 import typer 35 raise typer.Exit(code=exit_code)
Print an error message with red X.
Args: message: Error message to display. exit_code: If provided, raises SystemExit with this code.
38def warning(message: str) -> None: 39 """Print a warning message with yellow icon.""" 40 console.print(f"[yellow]⚠[/yellow] {message}")
Print a warning message with yellow icon.
43def info(message: str) -> None: 44 """Print an info message with blue icon.""" 45 console.print(f"[blue]ℹ[/blue] {message}")
Print an info message with blue icon.
48def dim(message: str) -> None: 49 """Print dimmed text for secondary information.""" 50 console.print(f"[dim]{message}[/dim]")
Print dimmed text for secondary information.
53def styled_panel( 54 content: str, 55 title: Optional[str] = None, 56 style: str = "blue", 57 border_style: Optional[str] = None, 58) -> None: 59 """Print content in a styled panel. 60 61 Args: 62 content: Panel content (can include rich markup). 63 title: Optional panel title. 64 style: Style for the content (default: blue). 65 border_style: Border color (defaults to style). 66 """ 67 console.print(Panel( 68 content, 69 title=title, 70 border_style=border_style or style, 71 ))
Print content in a styled panel.
Args: content: Panel content (can include rich markup). title: Optional panel title. style: Style for the content (default: blue). border_style: Border color (defaults to style).
74def create_table( 75 title: str, 76 columns: list[tuple[str, str]], 77) -> Table: 78 """Create a styled table with predefined column styles. 79 80 Args: 81 title: Table title. 82 columns: List of (name, style) tuples for columns. 83 84 Returns: 85 Configured Table instance (call table.add_row() to add data). 86 87 Example: 88 table = create_table("API Keys", [ 89 ("ID", "dim"), 90 ("Name", "cyan"), 91 ("Status", "green"), 92 ]) 93 table.add_row("key-1", "My Key", "active") 94 console.print(table) 95 """ 96 table = Table(title=title, show_header=True) 97 for name, style in columns: 98 table.add_column(name, style=style) 99 return table
Create a styled table with predefined column styles.
Args: title: Table title. columns: List of (name, style) tuples for columns.
Returns: Configured Table instance (call table.add_row() to add data).
Example: table = create_table("API Keys", [ ("ID", "dim"), ("Name", "cyan"), ("Status", "green"), ]) table.add_row("key-1", "My Key", "active") console.print(table)
102@contextmanager 103def status_spinner(message: str): 104 """Show a spinner while performing an operation. 105 106 Args: 107 message: Status message to display. 108 109 Example: 110 with status_spinner("Deploying project..."): 111 deploy_project() 112 """ 113 with Progress( 114 SpinnerColumn(), 115 TextColumn("[progress.description]{task.description}"), 116 console=console, 117 transient=True, 118 ) as progress: 119 progress.add_task(description=message, total=None) 120 yield
Show a spinner while performing an operation.
Args: message: Status message to display.
Example: with status_spinner("Deploying project..."): deploy_project()
123def confirm_action( 124 message: str, 125 default: bool = False, 126) -> bool: 127 """Prompt user for confirmation. 128 129 Args: 130 message: Confirmation prompt. 131 default: Default value if user just presses Enter. 132 133 Returns: 134 True if user confirmed, False otherwise. 135 """ 136 import typer 137 return typer.confirm(message, default=default)
Prompt user for confirmation.
Args: message: Confirmation prompt. default: Default value if user just presses Enter.
Returns: True if user confirmed, False otherwise.
140def prompt( 141 message: str, 142 default: Optional[str] = None, 143 hide_input: bool = False, 144) -> str: 145 """Prompt user for input. 146 147 Args: 148 message: Input prompt. 149 default: Default value if user just presses Enter. 150 hide_input: If True, hide input (for passwords/tokens). 151 152 Returns: 153 User input string. 154 """ 155 import typer 156 return typer.prompt(message, default=default, hide_input=hide_input)
Prompt user for input.
Args: message: Input prompt. default: Default value if user just presses Enter. hide_input: If True, hide input (for passwords/tokens).
Returns: User input string.