"""UI utilities for dropkit - display functions and prompts.""" from collections.abc import Callable from typing import Any from rich.console import Console from rich.prompt import Prompt from rich.table import Table console = Console() def display_regions(regions: list[dict[str, Any]]) -> None: """Display available regions in a table, sorted alphabetically by slug.""" table = Table(title="Available Regions", show_header=True) table.add_column("Slug", style="cyan", no_wrap=True) table.add_column("Name", style="white") table.add_column("Features", style="dim") # Sort regions alphabetically by slug sorted_regions = sorted(regions, key=lambda r: r.get("slug", "")) for region in sorted_regions: slug = region.get("slug", "") name = region.get("name", "") features = ", ".join(region.get("features", [])[:3]) # Show first 3 features if len(region.get("features", [])) > 3: features += "..." table.add_row(slug, name, features) console.print(table) def display_sizes(sizes: list[dict[str, Any]]) -> None: """Display available droplet sizes in a table, sorted by price.""" table = Table(title="Available Droplet Sizes", show_header=True) table.add_column("Slug", style="cyan", no_wrap=True) table.add_column("Memory", style="white", justify="right") table.add_column("vCPUs", style="white", justify="right") table.add_column("Disk", style="white", justify="right") table.add_column("Transfer", style="white", justify="right") table.add_column("Price/mo", style="green", justify="right") # Sort sizes by price (monthly) ascending sorted_sizes = sorted(sizes, key=lambda s: s.get("price_monthly", 0)) for size in sorted_sizes: slug = size.get("slug", "") memory = f"{size.get('memory', 0)} MB" vcpus = str(size.get("vcpus", 0)) disk = f"{size.get('disk', 0)} GB" transfer = f"{size.get('transfer', 0)} TB" price = f"${size.get('price_monthly', 0):.2f}" table.add_row(slug, memory, vcpus, disk, transfer, price) console.print(table) def display_images(images: list[dict[str, Any]]) -> None: """Display available images in a table, sorted by distribution and name.""" table = Table(title="Available Images", show_header=True) table.add_column("Slug", style="cyan", no_wrap=True) table.add_column("Name", style="white") table.add_column("Distribution", style="dim") # Sort images by distribution, then by name sorted_images = sorted( images, key=lambda img: (img.get("distribution", ""), img.get("name", "")) ) for image in sorted_images: slug = image.get("slug", "") name = image.get("name", "") distribution = image.get("distribution", "") # Only show images with slugs (not snapshots) if slug: table.add_row(slug, name, distribution) console.print(table) def display_projects(projects: list[dict[str, Any]]) -> None: """Display available projects in a table, sorted alphabetically by name.""" table = Table(title="Available Projects", show_header=True) table.add_column("ID", style="dim", no_wrap=True) table.add_column("Name", style="cyan") table.add_column("Purpose", style="white") table.add_column("Description", style="dim") # Sort projects alphabetically by name sorted_projects = sorted(projects, key=lambda p: p.get("name", "").lower()) for project in sorted_projects: project_id = project.get("id", "") name = project.get("name", "") purpose = project.get("purpose", "") description = project.get("description", "") # Truncate description if too long if len(description) > 50: description = description[:47] + "..." table.add_row(project_id, name, purpose, description) console.print(table) def prompt_with_help( prompt_text: str, default: str, display_func: Callable[[list[dict[str, Any]]], None] | None = None, data: list[dict[str, Any]] | None = None, ) -> str: """ Prompt user for input with optional help via '?'. Args: prompt_text: The prompt to display (without the default/? part) default: Default value display_func: Function to call when user enters '?' data: Data to pass to display_func Returns: User's input value """ while True: value = Prompt.ask( f"[cyan]{prompt_text} (? for help)[/cyan]", default=default, ) if value == "?": if display_func and data is not None: console.print() display_func(data) console.print() else: console.print("[yellow]No help available[/yellow]") else: return value