cascade_cli/cli/
output.rs

1use console::{style, Emoji};
2use std::fmt::Display;
3
4/// Centralized output formatting utilities for consistent CLI presentation
5pub struct Output;
6
7impl Output {
8    /// Print a success message with checkmark
9    pub fn success<T: Display>(message: T) {
10        println!("{} {}", style("✓").green(), message);
11    }
12
13    /// Print an error message with X mark
14    pub fn error<T: Display>(message: T) {
15        println!("{} {}", style("✗").red(), message);
16    }
17
18    /// Print a warning message with warning emoji
19    pub fn warning<T: Display>(message: T) {
20        println!("{} {}", style("⚠").yellow(), message);
21    }
22
23    /// Print an info message with info emoji
24    pub fn info<T: Display>(message: T) {
25        println!("{} {}", style("ℹ").cyan(), message);
26    }
27
28    /// Print a sub-item with arrow prefix
29    pub fn sub_item<T: Display>(message: T) {
30        println!("  {} {}", style("→").dim(), message);
31    }
32
33    /// Print a bullet point
34    pub fn bullet<T: Display>(message: T) {
35        println!("  {} {}", style("•").dim(), message);
36    }
37
38    /// Print a section header
39    pub fn section<T: Display>(title: T) {
40        println!("\n{}", style(title).bold().underlined());
41    }
42
43    /// Print a tip/suggestion
44    pub fn tip<T: Display>(message: T) {
45        println!("{} {}", style("💡").bright(), style(message).dim());
46    }
47
48    /// Print progress indicator
49    pub fn progress<T: Display>(message: T) {
50        println!("{} {}", style("→").cyan(), message);
51    }
52
53    /// Print a divider line
54    pub fn divider() {
55        println!("{}", style("─".repeat(50)).dim());
56    }
57
58    /// Print stack information in a formatted way
59    pub fn stack_info(
60        name: &str,
61        id: &str,
62        base_branch: &str,
63        working_branch: Option<&str>,
64        is_active: bool,
65    ) {
66        Self::success(format!("Created stack '{name}'"));
67        Self::sub_item(format!("Stack ID: {}", style(id).dim()));
68        Self::sub_item(format!("Base branch: {}", style(base_branch).cyan()));
69
70        if let Some(working) = working_branch {
71            Self::sub_item(format!("Working branch: {}", style(working).cyan()));
72        }
73
74        if is_active {
75            Self::sub_item(format!("Status: {}", style("Active").green()));
76        }
77    }
78
79    /// Print next steps guidance
80    pub fn next_steps(steps: &[&str]) {
81        println!();
82        Self::tip("Next steps:");
83        for step in steps {
84            Self::bullet(step);
85        }
86    }
87
88    /// Print a command example
89    pub fn command_example<T: Display>(command: T) {
90        println!("  {}", style(command).yellow());
91    }
92
93    /// Print a check start message
94    pub fn check_start<T: Display>(message: T) {
95        println!("\n{} {}", style("🔍").bright(), style(message).bold());
96    }
97
98    /// Print a solution message
99    pub fn solution<T: Display>(message: T) {
100        println!("     {}: {}", style("Solution").yellow(), message);
101    }
102
103    /// Print a numbered item
104    pub fn numbered_item<T: Display>(number: usize, message: T) {
105        println!("  {}. {}", style(number).cyan(), message);
106    }
107}
108
109/// Emojis for different contexts
110pub struct Emojis;
111
112impl Emojis {
113    pub const SUCCESS: Emoji<'_, '_> = Emoji("✓", "OK");
114    pub const ERROR: Emoji<'_, '_> = Emoji("✗", "ERROR");
115    pub const WARNING: Emoji<'_, '_> = Emoji("⚠", "WARNING");
116    pub const INFO: Emoji<'_, '_> = Emoji("ℹ", "INFO");
117    pub const TIP: Emoji<'_, '_> = Emoji("💡", "TIP");
118    pub const ROCKET: Emoji<'_, '_> = Emoji("🚀", "ROCKET");
119    pub const SEARCH: Emoji<'_, '_> = Emoji("🔍", "SEARCH");
120    pub const UPLOAD: Emoji<'_, '_> = Emoji("📤", "UPLOAD");
121    pub const STACK: Emoji<'_, '_> = Emoji("📊", "STACK");
122}