Source code for continuity.cli.commands

"""
Modular CLI commands for Continuity.
Routes commands to specialized modules for better organization.
"""

import sys
from typing import Any, List, Optional


[docs] class UserError(Exception): """User-friendly error with helpful suggestions.""" def __init__(self, message: str, suggestion: Optional[str] = None): self.message = message self.suggestion = suggestion super().__init__(message)
[docs] def parse_message_refs(ref: str, max_messages: int = 10) -> List[int]: """Parse message references supporting ranges, lists, and 'all'.""" refs: List[int] = [] if ref.lower() == "all": return list(range(1, max_messages + 1)) # Split by commas for list notation parts = [part.strip() for part in ref.split(",")] for part in parts: if "-" in part: # Range notation like "1-4" try: start_str, end_str = part.split("-", 1) start = int(start_str.strip()) end = int(end_str.strip()) if start < 1 or end > max_messages or start > end: raise UserError( f"Invalid range '{part}' (messages 1-{max_messages} available)", "Use ranges like '1-3' or lists like '1,3,5'", ) refs.extend(range(start, end + 1)) except ValueError as e: raise UserError( f"Invalid range format '{part}'", "Use ranges like '1-3' or single numbers like '2'", ) from e else: # Single number try: num = int(part) if 1 <= num <= max_messages: refs.append(num) else: raise UserError( f"Message {num} not found (only messages 1-{max_messages} available)", "Use 'continuity check' to see available messages", ) except ValueError as e: raise UserError( f"'{part}' is not a valid message number", "Message numbers are like 1, 2, 3... Use 'continuity check' to see messages", ) from e return sorted(set(refs)) # Remove duplicates and sort
[docs] def validate_message_ref(ref: str, max_messages: int = 10) -> int: """Validate and normalize message reference to number (legacy single reference).""" refs = parse_message_refs(ref, max_messages) if len(refs) != 1: raise UserError( f"Expected single message reference, got {len(refs)} messages", "Use a single number like '2' for this command", ) return refs[0]
[docs] def handle_user_error(func): """Decorator to handle UserError exceptions gracefully.""" import functools from rich.console import Console console = Console() @functools.wraps(func) def wrapper(*args, **kwargs): try: return func(*args, **kwargs) except UserError as e: console.print(f"[red]Error:[/red] {e.message}") if e.suggestion: console.print(f"[yellow]Tip:[/yellow] {e.suggestion}") sys.exit(1) except Exception as e: console.print(f"[red]Unexpected error:[/red] {e}") console.print("[dim]Use --help for usage information[/dim]") sys.exit(1) return wrapper
[docs] def register_commands(cli_group: Any) -> None: """Register all CLI commands by importing and calling modular registration functions.""" # Import and register message commands from .command_modules.message import register_message_commands register_message_commands(cli_group) # Import and register inbox commands from .command_modules.inbox import register_inbox_commands register_inbox_commands(cli_group) # Import and register project management commands from .command_modules.project import register_project_commands register_project_commands(cli_group) # Import and register user detection commands from .command_modules.user import register_user_commands register_user_commands(cli_group)