Skip to main content

otto_cli/output/
style.rs

1use std::sync::atomic::{AtomicBool, Ordering};
2
3static COLORS_ENABLED: AtomicBool = AtomicBool::new(true);
4
5pub fn configure(no_color: bool) {
6    let mut enabled = !no_color;
7
8    if std::env::var_os("NO_COLOR").is_some() {
9        enabled = false;
10    }
11
12    if let Ok(term) = std::env::var("TERM")
13        && term.eq_ignore_ascii_case("dumb")
14    {
15        enabled = false;
16    }
17
18    if std::env::var("CLICOLOR_FORCE").ok().as_deref() == Some("1") {
19        enabled = true;
20    }
21
22    COLORS_ENABLED.store(enabled, Ordering::Relaxed);
23}
24
25#[cfg(test)]
26pub fn set_color_enabled(enabled: bool) {
27    COLORS_ENABLED.store(enabled, Ordering::Relaxed);
28}
29
30fn style(code: &str, text: &str) -> String {
31    if text.is_empty() || !COLORS_ENABLED.load(Ordering::Relaxed) {
32        return text.to_string();
33    }
34
35    format!("\x1b[{code}m{text}\x1b[0m")
36}
37
38pub fn bold(text: &str) -> String {
39    style("1", text)
40}
41
42pub fn muted(text: &str) -> String {
43    style("2", text)
44}
45
46pub fn accent(text: &str) -> String {
47    style("36", text)
48}
49
50pub fn success(text: &str) -> String {
51    style("32", text)
52}
53
54pub fn failure(text: &str) -> String {
55    style("31", text)
56}
57
58pub fn warning(text: &str) -> String {
59    style("33", text)
60}
61
62pub fn info(text: &str) -> String {
63    style("96", text)
64}
65
66pub fn command(text: &str) -> String {
67    style("96", text)
68}
69
70pub fn number(text: &str) -> String {
71    style("96", text)
72}
73
74pub fn bullet(text: &str) -> String {
75    style("94", text)
76}