use anyhow::Result;
use std::sync::OnceLock;
use termcolor::ColorChoice;
static COR_CACHE: OnceLock<ColorChoice> = OnceLock::new();
pub fn inicializar(sem_cor: bool) -> Result<()> {
let escolha = determinar_cor(sem_cor);
let _ = COR_CACHE.set(escolha);
tracing::debug!("configuração de cor do terminal: {:?}", escolha);
Ok(())
}
#[must_use]
pub fn cor_escolha() -> ColorChoice {
*COR_CACHE.get().unwrap_or(&ColorChoice::Never)
}
#[must_use]
pub fn e_interativo() -> bool {
use std::io::IsTerminal;
if std::env::var("TERM").as_deref() == Ok("dumb") {
return false;
}
std::io::stdout().is_terminal()
}
fn determinar_cor(sem_cor_cli: bool) -> ColorChoice {
if sem_cor_cli {
return ColorChoice::Never;
}
if std::env::var("NO_COLOR").is_ok() {
return ColorChoice::Never;
}
if std::env::var("CLICOLOR_FORCE").as_deref() == Ok("1") {
return ColorChoice::Always;
}
if e_interativo() {
ColorChoice::Auto
} else {
ColorChoice::Never
}
}
#[cfg(test)]
mod testes {
use super::*;
#[test]
fn sem_cor_cli_retorna_never() {
let escolha = determinar_cor(true);
assert!(matches!(escolha, ColorChoice::Never));
}
#[test]
fn no_color_env_retorna_never() {
let anterior = std::env::var("NO_COLOR").ok();
let anterior_force = std::env::var("CLICOLOR_FORCE").ok();
std::env::set_var("NO_COLOR", "1");
std::env::remove_var("CLICOLOR_FORCE");
let escolha = determinar_cor(false);
assert!(matches!(escolha, ColorChoice::Never));
match anterior {
Some(v) => std::env::set_var("NO_COLOR", v),
None => std::env::remove_var("NO_COLOR"),
}
match anterior_force {
Some(v) => std::env::set_var("CLICOLOR_FORCE", v),
None => std::env::remove_var("CLICOLOR_FORCE"),
}
}
#[test]
fn clicolor_force_retorna_always() {
let anterior = std::env::var("NO_COLOR").ok();
let anterior_force = std::env::var("CLICOLOR_FORCE").ok();
std::env::remove_var("NO_COLOR");
std::env::set_var("CLICOLOR_FORCE", "1");
let escolha = determinar_cor(false);
assert!(matches!(escolha, ColorChoice::Always));
match anterior {
Some(v) => std::env::set_var("NO_COLOR", v),
None => std::env::remove_var("NO_COLOR"),
}
match anterior_force {
Some(v) => std::env::set_var("CLICOLOR_FORCE", v),
None => std::env::remove_var("CLICOLOR_FORCE"),
}
}
#[test]
fn cor_escolha_retorna_never_sem_inicializar() {
let _ = cor_escolha();
}
#[test]
fn e_interativo_retorna_bool() {
let _ = e_interativo();
}
}