From b62d50095ebd4d61631540ffda3f6553623359c0 Mon Sep 17 00:00:00 2001 From: Jamie Mason Date: Fri, 25 Oct 2024 16:13:23 +0100 Subject: [PATCH] [WIP] expose cli option for log levels --- src/cli.rs | 49 ++++++++++++++++++++++++++++++-------- src/logger.rs | 43 +++++++++++++++++---------------- src/main.rs | 5 ++-- src/test/mock.rs | 3 ++- src/visit_packages_test.rs | 2 +- 5 files changed, 68 insertions(+), 34 deletions(-) diff --git a/src/cli.rs b/src/cli.rs index 097b1acc..08674049 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -1,4 +1,5 @@ use clap::{builder::ValueParser, crate_description, crate_name, crate_version, Arg, ArgMatches, Command}; +use log::LevelFilter; use regex::Regex; #[derive(Debug)] @@ -66,6 +67,14 @@ fn create() -> Command { .action(clap::ArgAction::Set) .value_parser(ValueParser::new(validate_filter)) .help("only include dependencies whose name matches this regex"), + ) + .arg( + Arg::new("logLevels") + .long("logLevels") + .value_delimiter(',') + .value_parser(["off", "error", "warn", "info", "debug"]) + .default_values(["error", "warn", "info"]) + .help("control how detailed log output should be"), ), ) .subcommand( @@ -99,6 +108,14 @@ fn create() -> Command { .action(clap::ArgAction::Set) .value_parser(ValueParser::new(validate_filter)) .help("only include dependencies whose name matches this regex"), + ) + .arg( + Arg::new("logLevels") + .long("logLevels") + .value_delimiter(',') + .value_parser(["off", "error", "warn", "info", "debug"]) + .default_values(["error", "warn", "info"]) + .help("control how detailed log output should be"), ), ) } @@ -122,11 +139,13 @@ pub struct CliOptions { /// `true` when `--format` is passed or if none of `--format`, `--ranges` /// or `--versions` are passed pub format: bool, + /// How detailed the terminal output should be + pub log_levels: Vec, + /// Optional glob patterns to package.json files + pub source: Vec, /// `true` when `--versions` is passed or if none of `--format`, `--ranges` /// or `--versions` are passed pub versions: bool, - /// Optional glob patterns to package.json files - pub source: Vec, } impl CliOptions { @@ -137,18 +156,28 @@ impl CliOptions { let use_format = matches.get_flag("format"); let use_versions = matches.get_flag("versions"); let use_all = !use_format && !use_versions; - let source = matches - .get_many::("source") - .unwrap_or_default() - .map(|source| source.to_owned()) - .collect::>(); - let filter = matches.get_one::("filter").map(|filter| filter.to_owned()); CliOptions { - filter, + filter: matches.get_one::("filter").map(|filter| Regex::new(filter).unwrap()), format: use_all || use_format, + log_levels: matches + .get_many::("logLevels") + .unwrap() + .map(|level| match level.as_str() { + "off" => LevelFilter::Off, + "error" => LevelFilter::Error, + "warn" => LevelFilter::Warn, + "info" => LevelFilter::Info, + "debug" => LevelFilter::Debug, + _ => unreachable!(), + }) + .collect(), + source: matches + .get_many::("source") + .unwrap_or_default() + .map(|source| source.to_owned()) + .collect::>(), versions: use_all || use_versions, - source, } } } diff --git a/src/logger.rs b/src/logger.rs index 4e067364..087fe969 100644 --- a/src/logger.rs +++ b/src/logger.rs @@ -3,29 +3,32 @@ use env_logger::Builder; use log::{Level, LevelFilter}; use std::io::Write; -pub fn init() { - Builder::new() - // @TODO expose cli and rcfile options for log level - .filter_level(LevelFilter::Debug) - .format(|buf, record| { - match record.level() { - // Normal output shown to users - Level::Info => { - writeln!(buf, "{}", record.args()) - } - Level::Error => { +/// Initialize the logger with the given log level +pub fn init(log_levels: &[LevelFilter]) { + if !log_levels.contains(&LevelFilter::Off) { + let error_enabled = log_levels.contains(&LevelFilter::Error); + let warn_enabled = log_levels.contains(&LevelFilter::Warn); + let info_enabled = log_levels.contains(&LevelFilter::Info); + let debug_enabled = log_levels.contains(&LevelFilter::Debug); + let trace_enabled = log_levels.contains(&LevelFilter::Trace); + Builder::new() + .filter_level(LevelFilter::Debug) + .format(move |buf, record| { + let level = record.level(); + if level == Level::Error && error_enabled { writeln!(buf, "{}", format!("✗ {}", record.args()).red()) - } - Level::Warn => { + } else if level == Level::Warn && warn_enabled { writeln!(buf, "{}", format!("! {}", record.args()).yellow()) - } - Level::Debug => { + } else if level == Level::Info && info_enabled { + writeln!(buf, "{}", record.args()) + } else if level == Level::Debug && debug_enabled { writeln!(buf, "{}", format!("? {}", record.args()).cyan()) - } - Level::Trace => { + } else if level == Level::Trace && trace_enabled { writeln!(buf, "{}", record.args()) + } else { + write!(buf, "") } - } - }) - .init(); + }) + .init(); + } } diff --git a/src/main.rs b/src/main.rs index e88862ad..06bd2df2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -35,10 +35,11 @@ mod version_group; mod visit_packages; fn main() { - logger::init(); + let cli = Cli::parse(); + + logger::init(&cli.options.log_levels); let cwd = current_dir().unwrap(); - let cli = Cli::parse(); let config = Config::from_cli(cwd, cli); let packages = Packages::from_config(&config); diff --git a/src/test/mock.rs b/src/test/mock.rs index 9d09c293..48cdf19d 100644 --- a/src/test/mock.rs +++ b/src/test/mock.rs @@ -15,8 +15,9 @@ pub fn cli() -> Cli { options: CliOptions { filter: None, format: false, - versions: true, + log_levels: vec![], source: vec![], + versions: true, }, } } diff --git a/src/visit_packages_test.rs b/src/visit_packages_test.rs index 22989b75..7dd63f32 100644 --- a/src/visit_packages_test.rs +++ b/src/visit_packages_test.rs @@ -13,7 +13,7 @@ use super::*; #[ctor::ctor] fn init() { use crate::logger; - logger::init(); + logger::init(&[]); } // = Standard Version Group: Local =============================================