openlatch-provider 0.2.1

Self-service onboarding CLI + runtime daemon for OpenLatch Editors and Providers
//! Terminal color helpers — verbatim clone of openlatch-client `src/cli/color.rs`.
//!
//! Priority order: `--no-color` flag > `NO_COLOR` env > TTY auto-detect.

use std::io::IsTerminal;

/// Common Unicode glyphs used throughout CLI output. Centralised so themes
/// can be tweaked in one place.
pub const ARROW: &str = "\u{2192}"; //pub const KEY: &str = "\u{1F511}"; // 🔑
pub const WARNING: &str = "\u{26A0}"; //pub const INFO: &str = "\u{2139}"; //
/// Resolve the color toggle. `--no-color` flag and `NO_COLOR` env force off;
/// `FORCE_COLOR` env forces on; otherwise stdout TTY detection.
pub fn is_color_enabled(no_color_flag: bool) -> bool {
    if no_color_flag {
        return false;
    }
    if std::env::var_os("NO_COLOR").is_some() {
        return false;
    }
    if std::env::var_os("FORCE_COLOR").is_some() {
        return true;
    }
    std::io::stdout().is_terminal()
}

pub fn green(text: &str, enabled: bool) -> String {
    if enabled {
        format!("\x1b[32m{text}\x1b[0m")
    } else {
        text.to_string()
    }
}

pub fn red(text: &str, enabled: bool) -> String {
    if enabled {
        format!("\x1b[31m{text}\x1b[0m")
    } else {
        text.to_string()
    }
}

pub fn yellow(text: &str, enabled: bool) -> String {
    if enabled {
        format!("\x1b[33m{text}\x1b[0m")
    } else {
        text.to_string()
    }
}

pub fn cyan(text: &str, enabled: bool) -> String {
    if enabled {
        format!("\x1b[36m{text}\x1b[0m")
    } else {
        text.to_string()
    }
}

pub fn dim(text: &str, enabled: bool) -> String {
    if enabled {
        format!("\x1b[2m{text}\x1b[0m")
    } else {
        text.to_string()
    }
}

pub fn bold(text: &str, enabled: bool) -> String {
    if enabled {
        format!("\x1b[1m{text}\x1b[0m")
    } else {
        text.to_string()
    }
}

pub fn checkmark(color_enabled: bool) -> &'static str {
    if color_enabled {
        "\x1b[32m\u{2713}\x1b[0m"
    } else {
        "OK"
    }
}

pub fn cross(color_enabled: bool) -> &'static str {
    if color_enabled {
        "\x1b[31m\u{2717}\x1b[0m"
    } else {
        "ERR"
    }
}

pub fn bullet(color_enabled: bool) -> &'static str {
    if color_enabled {
        "  \u{00b7}"
    } else {
        "  -"
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn no_color_flag_overrides_tty() {
        assert!(!is_color_enabled(true));
    }

    #[test]
    fn checkmark_returns_ok_when_color_disabled() {
        assert_eq!(checkmark(false), "OK");
    }

    #[test]
    fn cross_returns_err_when_color_disabled() {
        assert_eq!(cross(false), "ERR");
    }

    #[test]
    fn bullet_returns_hyphen_when_color_disabled() {
        assert_eq!(bullet(false), "  -");
    }

    #[test]
    fn green_wraps_ansi_when_enabled() {
        let result = green("hello", true);
        assert!(result.contains("\x1b[32m"));
        assert!(result.contains("hello"));
    }

    #[test]
    fn dim_passthrough_when_disabled() {
        assert_eq!(dim("info", false), "info");
    }
}