Skip to main content

git_same/output/
printer.rs

1use console::style;
2
3/// Output verbosity level.
4#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
5pub enum Verbosity {
6    /// No output except errors.
7    Quiet = 0,
8    /// Normal output.
9    Normal = 1,
10    /// Verbose output.
11    Verbose = 2,
12    /// Very verbose (debug) output.
13    Debug = 3,
14}
15
16impl From<u8> for Verbosity {
17    fn from(v: u8) -> Self {
18        match v {
19            0 => Verbosity::Quiet,
20            1 => Verbosity::Normal,
21            2 => Verbosity::Verbose,
22            _ => Verbosity::Debug,
23        }
24    }
25}
26
27/// Output handler for consistent formatting.
28#[derive(Debug, Clone)]
29pub struct Output {
30    verbosity: Verbosity,
31    json: bool,
32}
33
34impl Output {
35    /// Creates a new output handler.
36    pub fn new(verbosity: Verbosity, json: bool) -> Self {
37        Self { verbosity, json }
38    }
39
40    /// Creates a quiet output handler.
41    pub fn quiet() -> Self {
42        Self::new(Verbosity::Quiet, false)
43    }
44
45    /// Prints an info message.
46    pub fn info(&self, msg: &str) {
47        if !self.json && self.verbosity >= Verbosity::Normal {
48            println!("{} {}", style("→").cyan(), msg);
49        }
50    }
51
52    /// Prints a success message.
53    pub fn success(&self, msg: &str) {
54        if !self.json && self.verbosity >= Verbosity::Normal {
55            println!("{} {}", style("✓").green(), msg);
56        }
57    }
58
59    /// Prints a warning message.
60    pub fn warn(&self, msg: &str) {
61        if !self.json && self.verbosity >= Verbosity::Normal {
62            eprintln!("{} {}", style("⚠").yellow(), msg);
63        }
64    }
65
66    /// Prints an error message.
67    pub fn error(&self, msg: &str) {
68        if !self.json {
69            eprintln!("{} {}", style("✗").red(), msg);
70        }
71    }
72
73    /// Prints a plain stdout line (no prefix).
74    ///
75    /// Useful for tabular/list output that should still respect quiet/json modes.
76    pub fn plain(&self, msg: &str) {
77        if !self.json && self.verbosity >= Verbosity::Normal {
78            println!("{}", msg);
79        }
80    }
81
82    /// Prints a verbose message.
83    pub fn verbose(&self, msg: &str) {
84        if !self.json && self.verbosity >= Verbosity::Verbose {
85            println!("{} {}", style("·").dim(), msg);
86        }
87    }
88
89    /// Prints a debug message.
90    pub fn debug(&self, msg: &str) {
91        if !self.json && self.verbosity >= Verbosity::Debug {
92            println!("{} {}", style("⋅").dim(), style(msg).dim());
93        }
94    }
95
96    /// Returns true if output is in JSON mode.
97    pub fn is_json(&self) -> bool {
98        self.json
99    }
100
101    /// Returns the current verbosity level.
102    pub fn verbosity(&self) -> Verbosity {
103        self.verbosity
104    }
105}
106
107impl Default for Output {
108    fn default() -> Self {
109        Self::new(Verbosity::Normal, false)
110    }
111}
112
113/// Format a count with appropriate styling.
114pub fn format_count(count: usize, label: &str) -> String {
115    format!("{} {}", style(count).cyan().bold(), label)
116}
117
118/// Format a success message.
119pub fn format_success(msg: &str) -> String {
120    format!("{} {}", style("✓").green(), msg)
121}
122
123/// Format an error message.
124pub fn format_error(msg: &str) -> String {
125    format!("{} {}", style("✗").red(), msg)
126}
127
128/// Format a warning message.
129pub fn format_warning(msg: &str) -> String {
130    format!("{} {}", style("⚠").yellow(), msg)
131}
132
133#[cfg(test)]
134#[path = "printer_tests.rs"]
135mod tests;