1use anyhow::Result;
11use std::sync::OnceLock;
12use termcolor::ColorChoice;
13
14static COR_CACHE: OnceLock<ColorChoice> = OnceLock::new();
16
17pub fn inicializar(sem_cor: bool) -> Result<()> {
22 let escolha = determinar_cor(sem_cor);
23 let _ = COR_CACHE.set(escolha);
24 tracing::debug!("configuração de cor do terminal: {:?}", escolha);
25 Ok(())
26}
27
28#[must_use]
33pub fn cor_escolha() -> ColorChoice {
34 *COR_CACHE.get().unwrap_or(&ColorChoice::Never)
35}
36
37#[must_use]
42pub fn e_interativo() -> bool {
43 use std::io::IsTerminal;
44
45 if std::env::var("TERM").as_deref() == Ok("dumb") {
47 return false;
48 }
49
50 std::io::stdout().is_terminal()
51}
52
53fn determinar_cor(sem_cor_cli: bool) -> ColorChoice {
55 if sem_cor_cli {
57 return ColorChoice::Never;
58 }
59
60 if std::env::var("NO_COLOR").is_ok() {
62 return ColorChoice::Never;
63 }
64
65 if std::env::var("CLICOLOR_FORCE").as_deref() == Ok("1") {
67 return ColorChoice::Always;
68 }
69
70 if e_interativo() {
72 ColorChoice::Auto
73 } else {
74 ColorChoice::Never
75 }
76}
77
78#[cfg(test)]
79mod testes {
80 use super::*;
81
82 #[test]
83 fn sem_cor_cli_retorna_never() {
84 let escolha = determinar_cor(true);
85 assert!(matches!(escolha, ColorChoice::Never));
86 }
87
88 #[test]
89 fn no_color_env_retorna_never() {
90 let anterior = std::env::var("NO_COLOR").ok();
92 let anterior_force = std::env::var("CLICOLOR_FORCE").ok();
93
94 std::env::set_var("NO_COLOR", "1");
95 std::env::remove_var("CLICOLOR_FORCE");
96
97 let escolha = determinar_cor(false);
98 assert!(matches!(escolha, ColorChoice::Never));
99
100 match anterior {
102 Some(v) => std::env::set_var("NO_COLOR", v),
103 None => std::env::remove_var("NO_COLOR"),
104 }
105 match anterior_force {
106 Some(v) => std::env::set_var("CLICOLOR_FORCE", v),
107 None => std::env::remove_var("CLICOLOR_FORCE"),
108 }
109 }
110
111 #[test]
112 fn clicolor_force_retorna_always() {
113 let anterior = std::env::var("NO_COLOR").ok();
114 let anterior_force = std::env::var("CLICOLOR_FORCE").ok();
115
116 std::env::remove_var("NO_COLOR");
117 std::env::set_var("CLICOLOR_FORCE", "1");
118
119 let escolha = determinar_cor(false);
120 assert!(matches!(escolha, ColorChoice::Always));
121
122 match anterior {
124 Some(v) => std::env::set_var("NO_COLOR", v),
125 None => std::env::remove_var("NO_COLOR"),
126 }
127 match anterior_force {
128 Some(v) => std::env::set_var("CLICOLOR_FORCE", v),
129 None => std::env::remove_var("CLICOLOR_FORCE"),
130 }
131 }
132
133 #[test]
134 fn cor_escolha_retorna_never_sem_inicializar() {
135 let _ = cor_escolha();
139 }
140
141 #[test]
142 fn e_interativo_retorna_bool() {
143 let _ = e_interativo();
145 }
146}