Coverage for src / monte_neo / cli / styles.py: 33%
57 statements
« prev ^ index » next coverage.py v7.13.1, created at 2026-01-28 16:27 +0200
« prev ^ index » next coverage.py v7.13.1, created at 2026-01-28 16:27 +0200
1"""CLI styles module.
3Terminal styling and formatting.
4"""
6from __future__ import annotations
8from questionary import Style
9from rich.console import Console
10from rich.panel import Panel
11from rich.text import Text
13from monte_neo._version import __version__
15console = Console()
17# Questionary custom style (matches cline/claude code aesthetic)
18CUSTOM_STYLE = Style(
19 [
20 ("qmark", "fg:cyan bold"),
21 ("question", "fg:white bold"),
22 ("answer", "fg:green bold"),
23 ("pointer", "fg:cyan bold"),
24 ("highlighted", "fg:cyan bold"),
25 ("selected", "fg:green"),
26 ("separator", "fg:white"),
27 ("instruction", "fg:white dim"),
28 ("text", "fg:white"),
29 ("disabled", "fg:white dim"),
30 ]
31)
34def press_any_key() -> None:
35 """Wait for user to press enter."""
36 import questionary
37 questionary.confirm("Press Enter to continue...", default=True, auto_enter=True, qmark="").ask()
39def print_banner() -> None:
40 """Print the application banner."""
41 banner = Text()
42 banner.append(
43 "╔══════════════════════════════════════════════════════════╗\n", style="cyan"
44 ) # noqa: E501
45 banner.append("║", style="cyan")
46 banner.append(
47 f" 🎲 Monte-Neo {__version__} ",
48 style="bold white",
49 ) # noqa: E501
50 banner.append("║\n", style="cyan")
51 banner.append("║", style="cyan")
52 banner.append(
53 " Monte Carlo Indicator Generator Framework ",
54 style="dim white",
55 ) # noqa: E501
56 banner.append("║\n", style="cyan")
57 banner.append(
58 "╚══════════════════════════════════════════════════════════╝", style="cyan"
59 ) # noqa: E501
61 console.print(banner)
62 console.print()
65def print_success(message: str) -> None:
66 """Print success message."""
67 console.print(f"[bold green]✓[/] {message}")
70def print_error(message: str) -> None:
71 """Print error message."""
72 console.print(f"[bold red]✗[/] {message}")
75def print_warning(message: str) -> None:
76 """Print warning message."""
77 console.print(f"[bold yellow]⚠[/] {message}")
80def print_info(message: str) -> None:
81 """Print info message."""
82 console.print(f"[bold cyan]ℹ[/] {message}")
85def print_section(title: str) -> None:
86 """Print section header."""
87 console.print(f"\n[bold cyan]━━━ {title} ━━━[/]\n")
90def print_metrics_panel(metrics: dict) -> None:
91 """Print metrics in a styled panel."""
92 lines = []
93 for key, value in metrics.items():
94 if isinstance(value, float):
95 lines.append(f"[cyan]{key}:[/] [green]{value:.4f}[/]")
96 else:
97 lines.append(f"[cyan]{key}:[/] [green]{value}[/]")
99 panel = Panel(
100 "\n".join(lines),
101 title="[bold]Metrics[/]",
102 border_style="cyan",
103 )
104 console.print(panel)
107def format_number(value: float, decimals: int = 2) -> str:
108 """Format number for display."""
109 if abs(value) >= 1_000_000:
110 return f"{value / 1_000_000:.{decimals}f}M"
111 elif abs(value) >= 1_000:
112 return f"{value / 1_000:.{decimals}f}K"
113 else:
114 return f"{value:.{decimals}f}"
117def format_percentage(value: float) -> str:
118 """Format as percentage."""
119 return f"{value * 100:.1f}%"
122def format_duration(seconds: float) -> str:
123 """Format duration for display."""
124 if seconds < 60:
125 return f"{seconds:.1f}s"
126 elif seconds < 3600:
127 minutes = seconds / 60
128 return f"{minutes:.1f}m"
129 else:
130 hours = seconds / 3600
131 return f"{hours:.1f}h"