feat(cli::args): verbosity flags for log level

This commit is contained in:
Christoph J. Scherr 2024-06-28 00:05:54 +02:00
parent a92f5f308d
commit 798cb19865
4 changed files with 144 additions and 1 deletions

View File

@ -54,7 +54,7 @@ core = []
full = ["default", "core", "log", "bintols"]
log = ["dep:libpt-log"]
bintols = ["dep:libpt-bintols", "log"]
cli = ["dep:libpt-cli", "core"]
cli = ["dep:libpt-cli", "core", "log"]
# py = ["dep:libpt-py"]
[lib]

View File

@ -12,9 +12,15 @@ repository.workspace = true
keywords.workspace = true
categories.workspace = true
[features]
default = ["log"]
log = ["dep:libpt-log"]
[dependencies]
anyhow.workspace = true
clap = { version = "4.5.7", features = ["derive"] }
comfy-table = "7.1.1"
console = "0.15.8"
dialoguer = "0.11.0"
indicatif = "0.17.8"
libpt-log = {workspace = true, optional = true}

View File

@ -0,0 +1,135 @@
use clap::Parser;
use libpt_log::Level;
/// Custom help template for displaying command-line usage information
///
/// This template modifies the default template provided by Clap to include additional information
/// and customize the layout of the help message.
///
/// Differences from the default template:
/// - Includes the application version and author information at the end
///
/// Apply like this:
/// ```
/// # use libpt_cli::args::HELP_TEMPLATE;
/// use clap::Parser;
/// #[derive(Parser, Debug, Clone, PartialEq, Eq, Hash)]
/// #[command(help_template = HELP_TEMPLATE)]
/// pub struct MyArgs {
/// /// show more details
/// #[arg(short, long)]
/// pub verbose: bool,
/// }
/// ```
///
/// ## Example
///
/// Don't forget to set `authors` in your `Cargo.toml`!
///
/// ```bash
/// $ cargo run -- -h
/// about: short
///
/// Usage: aaa [OPTIONS]
///
/// Options:
/// -v, --verbose show more details
/// -h, --help Print help (see more with '--help')
/// -V, --version Print version
///
/// aaa: 0.1.0
/// Author: Christoph J. Scherr <software@cscherr.de>
///
/// ```
pub const HELP_TEMPLATE: &str = r#"{about-section}
{usage-heading} {usage}
{all-args}{tab}
{name}: {version}
Author: {author-with-newline}
"#;
#[derive(Parser, Debug, Clone, PartialEq, Eq, Hash)]
#[command(help_template = HELP_TEMPLATE)]
pub struct DefaultArguments {
/// get a [tracing] log level
///
/// set the verbosity with repeated '-q' and '-v' flags
#[command(flatten)]
verbose: VerbosityLevel,
}
#[derive(Parser, Clone, PartialEq, Eq, Hash)]
pub struct VerbosityLevel {
/// make the output more verbose
#[arg(
long,
short = 'v',
action = clap::ArgAction::Count,
global = true,
// help = L::verbose_help(),
// long_help = L::verbose_long_help(),
)]
verbose: u8,
/// make the output less verbose
///
/// ( -qqq for completely quiet)
#[arg(
long,
short = 'q',
action = clap::ArgAction::Count,
global = true,
conflicts_with = "verbose",
)]
quiet: u8,
}
impl VerbosityLevel {
/// true only if no verbose and no quiet was set (user is using defaults)
#[inline]
pub fn changed(&self) -> bool {
self.verbose != 0 || self.quiet != 0
}
#[inline]
fn value(&self) -> i8 {
let v = Self::level_value(Level::INFO) - (self.quiet as i8) + (self.verbose as i8);
if v > Self::level_value(Level::TRACE) {
Self::level_value(Level::TRACE)
} else {
v
}
}
/// get the [Level] for that VerbosityLevel
///
/// [None] means that absolutely no output is wanted (completely quiet)
#[inline]
pub fn level(&self) -> Option<Level> {
Some(match self.value() {
0 => Level::ERROR,
1 => Level::WARN,
2 => Level::INFO,
3 => Level::DEBUG,
4 => Level::TRACE,
_ => return None,
})
}
#[inline]
fn level_value(level: Level) -> i8 {
match level {
Level::TRACE => 4,
Level::DEBUG => 3,
Level::INFO => 2,
Level::WARN => 1,
Level::ERROR => 0,
}
}
}
impl std::fmt::Debug for VerbosityLevel {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?}", self.level())
}
}

View File

@ -1,7 +1,9 @@
pub mod printing;
pub mod repl;
pub mod args;
pub use comfy_table;
pub use console;
pub use dialoguer;
pub use indicatif;
pub use clap;