1use console::{Alignment, StyledObject, pad_str, style};
4use std::sync::LazyLock;
5use std::{
6 fmt::Display,
7 io::{IsTerminal, stdout},
8};
9
10pub static PAD_OUTPUT: LazyLock<bool> = LazyLock::new(|| stdout().is_terminal());
12
13pub const LABEL_WIDTH: usize = 12;
15
16#[derive(Default)]
18pub enum OutputLabel<'a> {
19 Error(&'a str),
21 Warning(&'a str),
23 Info(&'a str),
25 Success(&'a str),
27 Custom(StyledObject<&'a str>),
29 #[default]
31 None,
32}
33
34pub fn println_label<M: AsRef<str> + Display>(label: OutputLabel, message: M) {
36 match label {
37 OutputLabel::Error(_) => {
38 eprintln!("{}", pretty_output(label, message));
39 }
40 _ => {
41 println!("{}", pretty_output(label, message));
42 }
43 }
44}
45
46pub fn pretty_output<M: AsRef<str> + Display>(out_label: OutputLabel, message: M) -> String {
52 let (label, label_is_empty) = match out_label {
53 OutputLabel::Error(error) => (style(error).bold().red(), false),
54 OutputLabel::Warning(warn) => (style(warn).bold().yellow(), false),
55 OutputLabel::Info(info) => (style(info).bold().cyan(), false),
56 OutputLabel::Success(success) => (style(success).bold().green(), false),
57 OutputLabel::Custom(custom) => (custom, false),
58 OutputLabel::None => (style(""), true),
59 };
60
61 if *PAD_OUTPUT {
63 format!(
64 "{} {}",
65 pad_str(
66 label.to_string().as_str(),
67 LABEL_WIDTH,
68 Alignment::Right,
69 None
70 ),
71 message
72 )
73 } else {
74 if label_is_empty {
76 format!("\t{message}")
77 } else {
78 format!("{label} {message}")
79 }
80 }
81}