updt 0.1.35

Cross-platform update helper for npm, cargo, rustup, fnm, scoop, Homebrew, paru, flatpak, pacman, and pkg.
use crossterm::style::{Attribute, Color as TermColor, Stylize};
use std::io::{self, IsTerminal};
use std::sync::OnceLock;

#[derive(Clone, Copy)]
pub enum MsgKind {
    Info,
    Ok,
    Warn,
}

fn color_enabled() -> bool {
    static CACHE: OnceLock<bool> = OnceLock::new();
    *CACHE.get_or_init(|| io::stdout().is_terminal())
}

pub fn color(text: &str, c: TermColor) -> String {
    if color_enabled() {
        format!("{}", text.with(c))
    } else {
        text.to_string()
    }
}

pub fn color_bold(text: &str, c: TermColor) -> String {
    if color_enabled() {
        format!("{}", text.with(c).attribute(Attribute::Bold))
    } else {
        text.to_string()
    }
}

pub fn ok_text(text: &str) -> String {
    color(text, TermColor::Green)
}

pub fn warn_text(text: &str) -> String {
    color(text, TermColor::Yellow)
}

pub fn err_text(text: &str) -> String {
    color(text, TermColor::Red)
}

fn pkg_color(pkg: &str) -> TermColor {
    let _ = pkg;
    TermColor::Cyan
}

pub fn log_pkg_line(pkg: &str, msg: &str, kind: MsgKind) -> String {
    let prefix = color_bold(&format!("[{pkg}]"), pkg_color(pkg));
    let body = match kind {
        MsgKind::Info => color(msg, TermColor::White),
        MsgKind::Ok => ok_text(msg),
        MsgKind::Warn => warn_text(msg),
    };
    format!("{prefix} {body}")
}

pub fn print_section(title: &str) {
    println!();
    println!(
        "{}",
        color_bold(&format!("==== {title} ===="), TermColor::Cyan)
    );
}

pub fn print_exit_signal_message() {
    println!(
        "{}",
        warn_text("检测到中断信号 (Ctrl+C/Ctrl+D), 程序已安全退出.")
    );
}