cli: add color option

This commit is contained in:
Dmitriy Pleshevskiy 2022-11-12 16:25:35 +03:00
parent 4e9ea6c683
commit bbd1d47ba5
Signed by: pleshevskiy
GPG key ID: 1B59187B161C0215
4 changed files with 81 additions and 12 deletions

1
Cargo.lock generated
View file

@ -196,6 +196,7 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
name = "vnetod" name = "vnetod"
version = "0.3.3" version = "0.3.3"
dependencies = [ dependencies = [
"atty",
"clap", "clap",
"termcolor", "termcolor",
] ]

View file

@ -13,7 +13,8 @@ categories = ["command-line-interface", "config", "development-tools"]
[dependencies] [dependencies]
clap = { version = "3.2.15", default-features = false, features = ["std", "env", "derive"] } clap = { version = "3.2.15", default-features = false, features = ["std", "env", "derive"] }
atty = { version = "0.2.14", optional = true }
termcolor = { version = "1.1.3", optional = true } termcolor = { version = "1.1.3", optional = true }
[features] [features]
color = ["clap/color", "dep:termcolor"] color = ["clap/color", "dep:atty", "dep:termcolor"]

View file

@ -20,7 +20,7 @@ use std::path::PathBuf;
use clap::Parser; use clap::Parser;
#[derive(Parser)] #[derive(Parser, Debug)]
#[clap( #[clap(
author, author,
version, version,
@ -62,4 +62,63 @@ pub struct Args {
help = "Environment varible sections that will be enabled" help = "Environment varible sections that will be enabled"
)] )]
pub sections: Vec<String>, pub sections: Vec<String>,
#[cfg(feature = "color")]
#[clap(
long,
value_enum,
default_value = "auto",
long_help = "
This flag controls when to use colors. The default setting is 'auto', which
means vnetod will try to guess when to use colors. For example, if vnetod is
printing to a terminal, then it will use colors, but if it is redirected to a
file or a pipe, then it will suppress color output. vnetod will suppress color
output in some other circumstances as well. For example, if the TERM
environment variable is not set or set to 'dumb', then vnetod will not use
colors.
The possible values for this flag are:
never Colors will never be used.
auto The default. vnetod tries to be smart.
always Colors will always be used regardless of where output is sent.
ansi Like 'always', but emits ANSI escapes (even in a Windows console).
"
)]
pub color: ColorVariant,
}
#[cfg(feature = "color")]
#[derive(clap::ValueEnum, Clone, Debug)]
pub enum ColorVariant {
Auto,
Always,
Ansi,
Never,
}
#[cfg(feature = "color")]
impl From<ColorVariant> for termcolor::ColorChoice {
fn from(col: ColorVariant) -> Self {
match col {
ColorVariant::Never => Self::Never,
ColorVariant::Always => Self::Always,
ColorVariant::Ansi => Self::AlwaysAnsi,
ColorVariant::Auto => {
if atty::is(atty::Stream::Stdout) {
// Otherwise let's `termcolor` decide by inspecting the environment. From the [doc]:
// - If `NO_COLOR` is set to any value, then colors will be suppressed.
// - If `TERM` is set to dumb, then colors will be suppressed.
// - In non-Windows environments, if `TERM` is not set, then colors will be suppressed.
//
// [doc]: https://github.com/BurntSushi/termcolor#automatic-color-selection
Self::Auto
} else {
// Colors should be deactivated if the terminal is not a tty.
Self::Never
}
}
}
}
} }

View file

@ -15,7 +15,7 @@
//! //!
#[cfg(feature = "color")] #[cfg(feature = "color")]
use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor}; use termcolor::{Color, ColorSpec, StandardStream, WriteColor};
use crate::{cli::Args, domain}; use crate::{cli::Args, domain};
use std::fs::File; use std::fs::File;
@ -47,11 +47,24 @@ pub fn execute(args: &Args) -> Result<(), Error> {
}) })
.transpose()?; .transpose()?;
#[cfg(feature = "color")]
let color = args.color.clone();
println!();
let new_content = domain::switch::execute(domain::switch::Request { let new_content = domain::switch::execute(domain::switch::Request {
content: &content, content: &content.trim(),
sections: &args.sections, sections: &args.sections,
on_line: Some(Box::new(print_line)), on_line: Some(Box::new(move |line| {
#[cfg(feature = "color")]
print_line(line, color.clone());
#[cfg(not(feature = "color"))]
print!("{}", line)
})),
}); });
println!();
if let Some(mut fs_writer) = fs_writer { if let Some(mut fs_writer) = fs_writer {
fs_writer fs_writer
.write_all(new_content.as_bytes()) .write_all(new_content.as_bytes())
@ -62,8 +75,8 @@ pub fn execute(args: &Args) -> Result<(), Error> {
} }
#[cfg(feature = "color")] #[cfg(feature = "color")]
fn print_line(line: &String) { fn print_line(line: &String, color: crate::cli::ColorVariant) {
let mut stdout = StandardStream::stdout(ColorChoice::Always); let mut stdout = StandardStream::stdout(color.into());
let color = line let color = line
.starts_with("###") .starts_with("###")
.then_some(Color::Yellow) .then_some(Color::Yellow)
@ -72,8 +85,3 @@ fn print_line(line: &String) {
write!(&mut stdout, "{}", line).unwrap(); write!(&mut stdout, "{}", line).unwrap();
stdout.reset().ok(); stdout.reset().ok();
} }
#[cfg(not(feature = "color"))]
fn print_line(line: &String) {
print!("{}", line)
}