hst_cli/
lib.rs

1//! Opinionated helpers for building consistent command-line interfaces with [`clap`][clap] and [`simplelog`][simplelog].
2//!
3//! ## Example
4//!
5//! The [`prelude`] module exports a minimal subset of these two crates.
6//!
7//! ```rust,no_run
8//! use hst_cli::prelude::*;
9//!
10//! #[derive(Debug, Parser)]
11//! #[clap(name = "demo", version, author)]
12//! struct Opts {
13//!     #[clap(flatten)]
14//!     verbose: Verbosity,
15//! }
16//!
17//! fn main() -> Result<(), log::SetLoggerError> {
18//!     let opts: Opts = Opts::parse();
19//!     opts.verbose.init_logging()?;
20//!     Ok(())
21//! }
22//! ```
23//!
24//! [clap]: https://docs.rs/clap/latest/clap/
25//! [simplelog]: https://docs.rs/simplelog/latest/simplelog/
26
27use simplelog::LevelFilter;
28
29fn select_log_level_filter(verbosity: i8) -> LevelFilter {
30    match verbosity {
31        0 => LevelFilter::Off,
32        1 => LevelFilter::Error,
33        2 => LevelFilter::Warn,
34        3 => LevelFilter::Info,
35        4 => LevelFilter::Debug,
36        _ => LevelFilter::Trace,
37    }
38}
39
40#[derive(clap::Args, Debug, Clone)]
41pub struct Verbosity {
42    /// Level of verbosity
43    #[clap(long, short = 'v', parse(from_occurrences), global = true)]
44    verbose: i8,
45}
46
47impl Verbosity {
48    pub fn new(verbose: i8) -> Self {
49        Self { verbose }
50    }
51
52    /// Initialize a default terminal logger with the indicated log level.
53    pub fn init_logging(&self) -> Result<(), log::SetLoggerError> {
54        simplelog::TermLogger::init(
55            select_log_level_filter(self.verbose),
56            simplelog::Config::default(),
57            simplelog::TerminalMode::Stderr,
58            simplelog::ColorChoice::Auto,
59        )
60    }
61}
62
63pub mod prelude {
64    pub use super::Verbosity;
65    pub use ::clap::Parser;
66    pub mod clap {
67        pub use clap::{
68            builder, AppSettings, Arg, ArgAction, ArgMatches, Args, Command, CommandFactory, Error,
69            ErrorKind, FromArgMatches, Parser, Subcommand,
70        };
71    }
72    pub mod log {
73        pub use log::{error, info, warn, SetLoggerError};
74    }
75}