Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat!: Gate log crate behind feature flag #126

Merged
merged 1 commit into from
Nov 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,12 @@ pre-release-replacements = [
[badges]
codecov = { repository = "clap-rs/clap-verbosity-flag" }

[features]
default = ["log"]
log = ["dep:log"]

[dependencies]
log = "0.4.1"
log = { version = "0.4.1", optional = true }
clap = { version = "4.0.0", default-features = false, features = ["std", "derive"] }

[dev-dependencies]
Expand All @@ -126,3 +130,15 @@ tracing-log = "0.2"

[lints]
workspace = true

[[example]]
name = "log"
required-features = ["log"]

[[example]]
name = "log_level"
required-features = ["log"]

[[example]]
name = "tracing"
required-features = ["log"]
111 changes: 18 additions & 93 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
//! # verbose: Verbosity,
//! # }
//! let cli = Cli::parse();
//! # #[cfg(feature = "log")]
//! env_logger::Builder::new()
//! .filter_level(cli.verbose.log_level_filter())
//! .init();
Expand Down Expand Up @@ -63,8 +64,8 @@

use std::fmt;

pub use log::Level;
pub use log::LevelFilter;
#[cfg(feature = "log")]
pub mod log;

/// Logging flags to `#[command(flatten)]` into your CLI
#[derive(clap::Args, Debug, Clone, Default)]
Expand Down Expand Up @@ -111,18 +112,6 @@ impl<L: LogLevel> Verbosity<L> {
self.verbose != 0 || self.quiet != 0
}

/// Get the log level.
///
/// `None` means all output is disabled.
pub fn log_level(&self) -> Option<Level> {
self.filter().into()
}

/// Get the log level filter.
pub fn log_level_filter(&self) -> LevelFilter {
self.filter().into()
}

/// If the user requested complete silence (i.e. not just no-logging).
pub fn is_silent(&self) -> bool {
self.filter() == VerbosityFilter::Off
Expand All @@ -135,6 +124,21 @@ impl<L: LogLevel> Verbosity<L> {
}
}

#[cfg(feature = "log")]
impl<L: LogLevel> Verbosity<L> {
/// Get the log level.
///
/// `None` means all output is disabled.
pub fn log_level(&self) -> Option<log::Level> {
self.filter().into()
}

/// Get the log level filter.
pub fn log_level_filter(&self) -> log::LevelFilter {
self.filter().into()
}
}

impl<L: LogLevel> fmt::Display for Verbosity<L> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.filter().fmt(f)
Expand Down Expand Up @@ -217,58 +221,6 @@ impl fmt::Display for VerbosityFilter {
}
}

impl From<VerbosityFilter> for LevelFilter {
fn from(filter: VerbosityFilter) -> Self {
match filter {
VerbosityFilter::Off => LevelFilter::Off,
VerbosityFilter::Error => LevelFilter::Error,
VerbosityFilter::Warn => LevelFilter::Warn,
VerbosityFilter::Info => LevelFilter::Info,
VerbosityFilter::Debug => LevelFilter::Debug,
VerbosityFilter::Trace => LevelFilter::Trace,
}
}
}

impl From<LevelFilter> for VerbosityFilter {
fn from(level: LevelFilter) -> Self {
match level {
LevelFilter::Off => Self::Off,
LevelFilter::Error => Self::Error,
LevelFilter::Warn => Self::Warn,
LevelFilter::Info => Self::Info,
LevelFilter::Debug => Self::Debug,
LevelFilter::Trace => Self::Trace,
}
}
}

impl From<VerbosityFilter> for Option<Level> {
fn from(filter: VerbosityFilter) -> Self {
match filter {
VerbosityFilter::Off => None,
VerbosityFilter::Error => Some(Level::Error),
VerbosityFilter::Warn => Some(Level::Warn),
VerbosityFilter::Info => Some(Level::Info),
VerbosityFilter::Debug => Some(Level::Debug),
VerbosityFilter::Trace => Some(Level::Trace),
}
}
}

impl From<Option<Level>> for VerbosityFilter {
fn from(level: Option<Level>) -> Self {
match level {
None => Self::Off,
Some(Level::Error) => Self::Error,
Some(Level::Warn) => Self::Warn,
Some(Level::Info) => Self::Info,
Some(Level::Debug) => Self::Debug,
Some(Level::Trace) => Self::Trace,
}
}
}

/// Default to [`VerbosityFilter::Error`]
#[derive(Copy, Clone, Debug, Default)]
pub struct ErrorLevel;
Expand Down Expand Up @@ -345,33 +297,6 @@ mod test {
Cli::command().debug_assert();
}

#[test]
fn log_level() {
let v = Verbosity::<OffLevel>::default();
assert_eq!(v.log_level(), None);
assert_eq!(v.log_level_filter(), LevelFilter::Off);

let v = Verbosity::<ErrorLevel>::default();
assert_eq!(v.log_level(), Some(Level::Error));
assert_eq!(v.log_level_filter(), LevelFilter::Error);

let v = Verbosity::<WarnLevel>::default();
assert_eq!(v.log_level(), Some(Level::Warn));
assert_eq!(v.log_level_filter(), LevelFilter::Warn);

let v = Verbosity::<InfoLevel>::default();
assert_eq!(v.log_level(), Some(Level::Info));
assert_eq!(v.log_level_filter(), LevelFilter::Info);

let v = Verbosity::<DebugLevel>::default();
assert_eq!(v.log_level(), Some(Level::Debug));
assert_eq!(v.log_level_filter(), LevelFilter::Debug);

let v = Verbosity::<TraceLevel>::default();
assert_eq!(v.log_level(), Some(Level::Trace));
assert_eq!(v.log_level_filter(), LevelFilter::Trace);
}

/// Asserts that the filter is correct for the given verbosity and quiet values.
#[track_caller]
fn assert_filter<L: LogLevel>(verbose: u8, quiet: u8, expected: VerbosityFilter) {
Expand Down
91 changes: 91 additions & 0 deletions src/log.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// These re-exports of the log crate make it easy to use this crate without having to depend on the
// log crate directly. See <https://github.com/clap-rs/clap-verbosity-flag/issues/54> for more
// information.
pub use log::{Level, LevelFilter};

use crate::VerbosityFilter;

impl From<VerbosityFilter> for LevelFilter {
joshka marked this conversation as resolved.
Show resolved Hide resolved
fn from(filter: VerbosityFilter) -> Self {
match filter {
VerbosityFilter::Off => LevelFilter::Off,
VerbosityFilter::Error => LevelFilter::Error,
VerbosityFilter::Warn => LevelFilter::Warn,
VerbosityFilter::Info => LevelFilter::Info,
VerbosityFilter::Debug => LevelFilter::Debug,
VerbosityFilter::Trace => LevelFilter::Trace,
}
}
}

impl From<LevelFilter> for VerbosityFilter {
fn from(level: LevelFilter) -> Self {
match level {
LevelFilter::Off => Self::Off,
LevelFilter::Error => Self::Error,
LevelFilter::Warn => Self::Warn,
LevelFilter::Info => Self::Info,
LevelFilter::Debug => Self::Debug,
LevelFilter::Trace => Self::Trace,
}
}
}

impl From<VerbosityFilter> for Option<Level> {
fn from(filter: VerbosityFilter) -> Self {
match filter {
VerbosityFilter::Off => None,
VerbosityFilter::Error => Some(Level::Error),
VerbosityFilter::Warn => Some(Level::Warn),
VerbosityFilter::Info => Some(Level::Info),
VerbosityFilter::Debug => Some(Level::Debug),
VerbosityFilter::Trace => Some(Level::Trace),
}
}
}

impl From<Option<Level>> for VerbosityFilter {
fn from(level: Option<Level>) -> Self {
match level {
None => Self::Off,
Some(Level::Error) => Self::Error,
Some(Level::Warn) => Self::Warn,
Some(Level::Info) => Self::Info,
Some(Level::Debug) => Self::Debug,
Some(Level::Trace) => Self::Trace,
}
}
}

#[cfg(test)]
mod tests {
use super::*;
use crate::{DebugLevel, ErrorLevel, InfoLevel, OffLevel, TraceLevel, Verbosity, WarnLevel};

#[test]
fn log_level() {
let v = Verbosity::<OffLevel>::default();
assert_eq!(v.log_level(), None);
assert_eq!(v.log_level_filter(), LevelFilter::Off);

let v = Verbosity::<ErrorLevel>::default();
assert_eq!(v.log_level(), Some(Level::Error));
assert_eq!(v.log_level_filter(), LevelFilter::Error);

let v = Verbosity::<WarnLevel>::default();
assert_eq!(v.log_level(), Some(Level::Warn));
assert_eq!(v.log_level_filter(), LevelFilter::Warn);

let v = Verbosity::<InfoLevel>::default();
assert_eq!(v.log_level(), Some(Level::Info));
assert_eq!(v.log_level_filter(), LevelFilter::Info);

let v = Verbosity::<DebugLevel>::default();
assert_eq!(v.log_level(), Some(Level::Debug));
assert_eq!(v.log_level_filter(), LevelFilter::Debug);

let v = Verbosity::<TraceLevel>::default();
assert_eq!(v.log_level(), Some(Level::Trace));
assert_eq!(v.log_level_filter(), LevelFilter::Trace);
}
}
Loading