diff --git a/Cargo.lock b/Cargo.lock index 31b9b91..fbc84bf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -231,6 +231,33 @@ dependencies = [ "unicase", ] +[[package]] +name = "concolor-clap" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4eb23c99e877c098e60ba3e84410153bfc311ac91b6ac7eabc0da0414ffa12e4" +dependencies = [ + "concolor-control", + "structopt", +] + +[[package]] +name = "concolor-control" +version = "0.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7104119c2f80d887239879d0c50e033cd40eac9a3f3561e0684ba7d5d654f4da" +dependencies = [ + "atty", + "bitflags", + "concolor-query", +] + +[[package]] +name = "concolor-query" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad159cc964ac8f9d407cbc0aa44b02436c054b541f2b4b5f06972e1efdc54bc7" + [[package]] name = "content_inspector" version = "0.2.4" @@ -1454,6 +1481,8 @@ dependencies = [ "bstr", "clap", "clap-verbosity-flag", + "concolor-clap", + "concolor-control", "content_inspector", "criterion", "derive_more", diff --git a/Cargo.toml b/Cargo.toml index a854198..47422a9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -70,6 +70,8 @@ log = "0.4" env_logger = { version = "0.9", default-features = false, features = ["termcolor"] } atty = "0.2.14" yansi = "0.5.0" +concolor-control = { version = "0.0.7" } +concolor-clap = { version = "0.0.6", features = ["api_unstable"] } bstr = "0.2" once_cell = "1.2.0" ahash = "0.7" diff --git a/src/bin/typos-cli/args.rs b/src/bin/typos-cli/args.rs index ce49f23..59b7dc8 100644 --- a/src/bin/typos-cli/args.rs +++ b/src/bin/typos-cli/args.rs @@ -44,7 +44,8 @@ impl Default for Format { #[structopt( setting = structopt::clap::AppSettings::UnifiedHelpMessage, setting = structopt::clap::AppSettings::DeriveDisplayOrder, - setting = structopt::clap::AppSettings::DontCollapseArgsInUsage + setting = structopt::clap::AppSettings::DontCollapseArgsInUsage, + setting = concolor_clap::color_choice(), )] #[structopt(group = structopt::clap::ArgGroup::with_name("mode").multiple(false))] pub(crate) struct Args { @@ -104,7 +105,7 @@ pub(crate) struct Args { pub(crate) config: ConfigArgs, #[structopt(flatten)] - pub(crate) color: crate::color::ColorArgs, + pub(crate) color: concolor_clap::Color, #[structopt(flatten)] pub(crate) verbose: clap_verbosity_flag::Verbosity, diff --git a/src/bin/typos-cli/color.rs b/src/bin/typos-cli/color.rs deleted file mode 100644 index 2a3aa97..0000000 --- a/src/bin/typos-cli/color.rs +++ /dev/null @@ -1,100 +0,0 @@ -use structopt::StructOpt; - -#[derive(Debug, StructOpt)] -#[structopt(rename_all = "kebab-case")] -pub struct ColorArgs { - /// "Specify when to use colored output. The automatic mode - /// only enables colors if an interactive terminal is detected - - /// colors are automatically disabled if the output goes to a pipe. - /// - /// Possible values: *auto*, never, always. - #[structopt( - long, - value_name="when", - possible_values(&ColorValue::variants()), - case_insensitive(true), - default_value("auto"), - hide_possible_values(true), - hide_default_value(true), - help="When to use colors (*auto*, never, always).")] - color: ColorValue, -} - -impl ColorArgs { - pub fn colored(&self) -> Option { - self.color.colored() - } -} - -arg_enum! { - #[derive(Debug, Copy, Clone, PartialEq, Eq)] - pub enum ColorValue { - Always, - Never, - Auto, - } -} - -impl ColorValue { - fn colored(self) -> Option { - match self { - ColorValue::Always => Some(true), - ColorValue::Never => Some(false), - ColorValue::Auto => None, - } - } -} - -impl Default for ColorValue { - fn default() -> Self { - ColorValue::Auto - } -} - -pub fn colored_stdout() -> Option { - if atty::is(atty::Stream::Stdout) { - None - } else { - Some(false) - } -} - -pub fn colored_stderr() -> Option { - if atty::is(atty::Stream::Stderr) { - None - } else { - Some(false) - } -} - -pub fn colored_env() -> Option { - match std::env::var_os("TERM") { - None => noterm_colored(), - Some(k) => { - if k == "dumb" { - Some(false) - } else { - None - } - } - } - .or_else(|| { - // See https://no-color.org/ - std::env::var_os("NO_COLOR").map(|_| true) - }) -} - -#[cfg(not(windows))] -fn noterm_colored() -> Option { - // If TERM isn't set, then we are in a weird environment that - // probably doesn't support colors. - Some(false) -} - -#[cfg(windows)] -fn noterm_colored() -> Option { - // On Windows, if TERM isn't set, then we shouldn't automatically - // assume that colors aren't allowed. This is unlike Unix environments - // where TERM is more rigorously set. - None -} diff --git a/src/bin/typos-cli/main.rs b/src/bin/typos-cli/main.rs index ecbdfdd..cb2c636 100644 --- a/src/bin/typos-cli/main.rs +++ b/src/bin/typos-cli/main.rs @@ -7,7 +7,6 @@ use std::io::Write; use structopt::StructOpt; mod args; -mod color; mod report; use proc_exit::WithCodeResultExt; @@ -31,22 +30,16 @@ fn run() -> proc_exit::ExitResult { } }; - let colored = args.color.colored().or_else(color::colored_env); - let mut colored_stdout = colored.or_else(color::colored_stdout).unwrap_or(true); - let mut colored_stderr = colored.or_else(color::colored_stderr).unwrap_or(true); - if (colored_stdout || colored_stderr) && !yansi::Paint::enable_windows_ascii() { - colored_stdout = false; - colored_stderr = false; - } + args.color.apply(); - init_logging(args.verbose.log_level(), colored_stderr); + init_logging(args.verbose.log_level()); - let stdout_palette = if colored_stdout { + let stdout_palette = if concolor_control::get(concolor_control::Stream::Stdout).ansi_color() { report::Palette::colored() } else { report::Palette::plain() }; - let stderr_palette = if colored_stderr { + let stderr_palette = if concolor_control::get(concolor_control::Stream::Stderr).ansi_color() { report::Palette::colored() } else { report::Palette::plain() @@ -272,9 +265,11 @@ fn run_checks( } } -fn init_logging(level: Option, colored: bool) { +fn init_logging(level: Option) { if let Some(level) = level { let mut builder = env_logger::Builder::new(); + + let colored = concolor_control::get(concolor_control::Stream::Stderr).ansi_color(); builder.write_style(if colored { env_logger::WriteStyle::Always } else {