mirror of
https://github.com/crate-ci/typos.git
synced 2024-11-28 12:01:06 -05:00
feat(cli): Smarter color control
This commit is contained in:
parent
a5d06c5a65
commit
b17b811ec1
5 changed files with 41 additions and 114 deletions
29
Cargo.lock
generated
29
Cargo.lock
generated
|
@ -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",
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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<bool> {
|
||||
self.color.colored()
|
||||
}
|
||||
}
|
||||
|
||||
arg_enum! {
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub enum ColorValue {
|
||||
Always,
|
||||
Never,
|
||||
Auto,
|
||||
}
|
||||
}
|
||||
|
||||
impl ColorValue {
|
||||
fn colored(self) -> Option<bool> {
|
||||
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<bool> {
|
||||
if atty::is(atty::Stream::Stdout) {
|
||||
None
|
||||
} else {
|
||||
Some(false)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn colored_stderr() -> Option<bool> {
|
||||
if atty::is(atty::Stream::Stderr) {
|
||||
None
|
||||
} else {
|
||||
Some(false)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn colored_env() -> Option<bool> {
|
||||
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<bool> {
|
||||
// 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<bool> {
|
||||
// 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
|
||||
}
|
|
@ -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<log::Level>, colored: bool) {
|
||||
fn init_logging(level: Option<log::Level>) {
|
||||
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 {
|
||||
|
|
Loading…
Reference in a new issue