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
25fn style(code: &str, text: &str) -> String {
26 if text.is_empty() || !COLORS_ENABLED.load(Ordering::Relaxed) {
27 return text.to_string();
28 }
29
30 format!("\x1b[{code}m{text}\x1b[0m")
31}
32
33pub fn bold(text: &str) -> String {
34 style("1", text)
35}
36
37pub fn muted(text: &str) -> String {
38 style("2", text)
39}
40
41pub fn accent(text: &str) -> String {
42 style("36", text)
43}
44
45pub fn success(text: &str) -> String {
46 style("32", text)
47}
48
49pub fn failure(text: &str) -> String {
50 style("31", text)
51}
52
53pub fn warning(text: &str) -> String {
54 style("33", text)
55}
56
57pub fn info(text: &str) -> String {
58 style("96", text)
59}
60
61pub fn command(text: &str) -> String {
62 style("96", text)
63}
64
65pub fn number(text: &str) -> String {
66 style("96", text)
67}
68
69pub fn bullet(text: &str) -> String {
70 style("94", text)
71}