Complete architectural separation of concerns implementing clean layered design: • Services Layer: Pure business logic isolated from presentation - WorkspaceService: TDD workspace operations - IssueService: Issue management and creation - ProjectService: Project management and milestones - ExportService: Unix-friendly data export • CLI Layer: Clean presentation with command/presenter separation - Commands delegate to services for all business operations - Presenters handle formatted output and error messaging - Framework provides unified interface • Benefits: - Eliminates mixed concerns in 943-line CLI monolith - Enables easier testing and maintenance - Preserves all existing functionality and Unix pipeline compatibility - Provides foundation for future CLI development Resolves issue #20: CLI separation from core logic 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
85 lines
2.2 KiB
Python
85 lines
2.2 KiB
Python
"""
|
|
Output formatting utilities for CLI presentation.
|
|
"""
|
|
|
|
import sys
|
|
from typing import Any, Dict, List
|
|
|
|
|
|
class OutputFormatter:
|
|
"""Handles output formatting and display."""
|
|
|
|
@staticmethod
|
|
def success(message: str) -> None:
|
|
"""Display success message."""
|
|
print(f"✅ {message}")
|
|
|
|
@staticmethod
|
|
def info(message: str) -> None:
|
|
"""Display info message."""
|
|
print(f"📋 {message}")
|
|
|
|
@staticmethod
|
|
def warning(message: str) -> None:
|
|
"""Display warning message."""
|
|
print(f"⚠️ {message}")
|
|
|
|
@staticmethod
|
|
def error(message: str) -> None:
|
|
"""Display error message."""
|
|
print(f"❌ {message}")
|
|
|
|
@staticmethod
|
|
def header(title: str, separator: str = "=") -> None:
|
|
"""Display section header."""
|
|
print(title)
|
|
print(separator * len(title))
|
|
print()
|
|
|
|
@staticmethod
|
|
def section(title: str) -> None:
|
|
"""Display section title."""
|
|
print(f"## {title}")
|
|
print()
|
|
|
|
@staticmethod
|
|
def bullet_point(text: str, indent: int = 0) -> None:
|
|
"""Display bullet point."""
|
|
prefix = " " * indent
|
|
print(f"{prefix}- {text}")
|
|
|
|
@staticmethod
|
|
def key_value(key: str, value: Any, indent: int = 0) -> None:
|
|
"""Display key-value pair."""
|
|
prefix = " " * indent
|
|
print(f"{prefix}{key}: {value}")
|
|
|
|
@staticmethod
|
|
def empty_line() -> None:
|
|
"""Display empty line."""
|
|
print()
|
|
|
|
@staticmethod
|
|
def exit_with_error(message: str, exit_code: int = 1) -> None:
|
|
"""Display error and exit."""
|
|
OutputFormatter.error(message)
|
|
sys.exit(exit_code)
|
|
|
|
@staticmethod
|
|
def format_file_list(files: List[str], title: str = "Files") -> None:
|
|
"""Format and display file list."""
|
|
print(f"📄 {title} ({len(files)}):")
|
|
if files:
|
|
for file in files:
|
|
print(f" - {file}")
|
|
else:
|
|
print(" - No files found")
|
|
print()
|
|
|
|
@staticmethod
|
|
def format_command_list(commands: List[str], title: str = "Commands") -> None:
|
|
"""Format and display command list."""
|
|
print(f"💡 {title}:")
|
|
for command in commands:
|
|
print(f" - {command}")
|
|
print() |