use std::io::IsTerminal;
#[derive(Debug, Clone)]
pub struct Environment {
pub is_ci: bool,
pub is_tty: bool,
pub stdin_is_tty: bool,
pub stderr_is_tty: bool,
pub width: Option<u16>,
pub height: Option<u16>,
}
impl Environment {
pub fn detect() -> Self {
let (width, height) = crossterm::terminal::size().ok().unzip();
Self {
is_ci: is_ci(),
is_tty: is_tty(),
stdin_is_tty: std::io::stdin().is_terminal(),
stderr_is_tty: std::io::stderr().is_terminal(),
width,
height,
}
}
pub fn should_disable_colors(&self) -> bool {
!self.is_tty
|| std::env::var("NO_COLOR").is_ok()
|| std::env::var("TERM").map(|t| t == "dumb").unwrap_or(false)
}
pub fn should_disable_interactive(&self) -> bool {
self.is_ci || !self.stdin_is_tty
}
}
impl Default for Environment {
fn default() -> Self {
Self::detect()
}
}
pub fn is_ci() -> bool {
std::env::var("CI").is_ok()
|| std::env::var("GITHUB_ACTIONS").is_ok()
|| std::env::var("GITLAB_CI").is_ok()
|| std::env::var("JENKINS_URL").is_ok()
|| std::env::var("BUILD_NUMBER").is_ok()
|| std::env::var("TRAVIS").is_ok()
|| std::env::var("CIRCLECI").is_ok()
|| std::env::var("TF_BUILD").is_ok()
|| std::env::var("BITBUCKET_BUILD_NUMBER").is_ok()
|| std::env::var("APPVEYOR").is_ok()
|| std::env::var("DRONE").is_ok()
|| std::env::var("BUILDKITE").is_ok()
|| std::env::var("TEAMCITY_VERSION").is_ok()
|| std::env::var("CI_NAME").map(|v| v == "codeship").unwrap_or(false)
}
pub fn is_tty() -> bool {
std::io::stdout().is_terminal()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_environment_detect() {
let env = Environment::detect();
let _ = env.is_ci;
let _ = env.is_tty;
}
#[test]
fn test_is_ci_returns_bool() {
let _ = is_ci();
}
#[test]
fn test_is_tty_returns_bool() {
let _ = is_tty();
}
#[test]
fn test_should_disable_colors() {
let env = Environment {
is_ci: false,
is_tty: false, stdin_is_tty: false,
stderr_is_tty: false,
width: None,
height: None,
};
assert!(env.should_disable_colors());
}
}