File size: 4,419 Bytes
f14b4e9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
use clap::ValueEnum;
use console::Style;
use firm_core::{Entity, EntitySchema};
use indicatif::{ProgressBar, ProgressStyle};
use std::{fmt, time::Duration};

use super::logging;

/// Helpers to create consistent console UI styles.
pub struct UiStyle;

impl UiStyle {
    /// A regular message.
    pub fn normal() -> Style {
        Style::new()
    }

    /// A highlighted message.
    pub fn highlight() -> Style {
        Style::new().bold()
    }

    /// A dim message.
    pub fn dim() -> Style {
        Style::new().dim()
    }

    /// A warning message.
    pub fn warning() -> Style {
        Style::new().yellow().bold()
    }

    /// A success message.
    pub fn success() -> Style {
        Style::new().green().bold()
    }

    /// An error message
    pub fn error() -> Style {
        Style::new().red().bold()
    }
}

/// Prints a header message.
pub fn header(msg: &str) {
    eprintln!("{}", UiStyle::highlight().apply_to(msg));
}

/// Prints a debug message.
pub fn debug(msg: &str) {
    eprintln!("{}", UiStyle::dim().apply_to(msg));
}

/// Prints an info message.
pub fn info(msg: &str) {
    eprintln!("{}", UiStyle::normal().apply_to(msg));
}

/// Prints a warning message.
pub fn warning(msg: &str) {
    eprintln!("{}", UiStyle::warning().apply_to(msg));
}

/// Prints a success message.
pub fn success(msg: &str) {
    eprintln!("{}", UiStyle::success().apply_to(msg));
}

/// Prints an error message.
pub fn error(msg: &str) {
    eprintln!("{}", UiStyle::error().apply_to(msg));
}

/// Prints an error message with added details.
pub fn error_with_details(main_msg: &str, details: &str) {
    eprintln!("{}", UiStyle::error().apply_to(main_msg));
    eprintln!("   {}", UiStyle::dim().apply_to(details));
}

/// Selects the output format used by the CLI.
#[derive(Clone, Debug, ValueEnum, PartialEq, Default)]
pub enum OutputFormat {
    #[default]
    Pretty,
    Json,
}

impl fmt::Display for OutputFormat {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            OutputFormat::Pretty => write!(f, "pretty"),
            OutputFormat::Json => write!(f, "json"),
        }
    }
}

/// Outputs a single entity in pretty format.
pub fn pretty_output_entity_single(entity: &Entity) {
    println!("\n{}", entity);
}

/// Outputs a list of entities in pretty format.
pub fn pretty_output_entity_list(entities: &Vec<&Entity>) {
    for (i, entity) in entities.iter().enumerate() {
        pretty_output_entity_single(entity);

        // Add a separator after each entity, except for the last one.
        if i < entities.len() - 1 {
            println!("---------------------------------------");
        }
    }
}

/// Outputs a single entity schema in pretty format.
pub fn pretty_output_schema_single(schema: &EntitySchema) {
    println!("\n{}", schema);
}

/// Outputs a serde-serializable object in json format.
pub fn json_output<T: serde::Serialize>(data: &T) {
    if let Ok(json) = serde_json::to_string_pretty(data) {
        println!("{}", json);
    }
}

/// Outputs a list of strings (one per line for pretty, array for JSON).
pub fn list_output(items: &[&str], format: OutputFormat) {
    match format {
        OutputFormat::Pretty => {
            for item in items {
                println!("{}", item);
            }
        }
        OutputFormat::Json => json_output(&items),
    }
}

/// Outputs raw text (e.g., file paths, simple values).
pub fn raw_output(text: &str) {
    println!("{}", text);
}

/// Creates a spinner progress indicator.
pub fn spinner(msg: &str) -> ProgressBar {
    let pb = ProgressBar::new_spinner();
    pb.set_style(
        ProgressStyle::default_spinner()
            .template("{spinner} {msg}")
            .expect("Invalid template"),
    );
    pb.enable_steady_tick(Duration::from_millis(100));
    pb.set_message(msg.to_string());

    let tracker = logging::get_multi_progress();
    tracker.add(pb.clone());

    pb
}

/// Creates a progress bar indicator.
pub fn progress_bar(len: u64) -> ProgressBar {
    let pb = ProgressBar::new(len);
    pb.set_style(
        ProgressStyle::default_bar()
            .template("{spinner} {msg} [{bar}] {pos}/{len}")
            .expect("Invalid template")
            .progress_chars("# "),
    );
    pb.enable_steady_tick(Duration::from_millis(100));

    let tracker = logging::get_multi_progress();
    tracker.add(pb.clone());

    pb
}