Skip to content

Commit

Permalink
iq-cli: Re-export the log crate and macros
Browse files Browse the repository at this point in the history
This is a bit hax: it uses the macros directly from the upstream crate
rather than a more elegant way of re-exporting them.

Doing it better seems blocked on this issue, which isn't likely to
happen:

rust-lang/rust#29638
  • Loading branch information
tony-iqlusion committed Aug 10, 2018
1 parent e2d1ebb commit 5acc96e
Show file tree
Hide file tree
Showing 5 changed files with 279 additions and 1 deletion.
25 changes: 25 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion iq-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,17 @@ appveyor = { repository = "iqlusioninc/crates" }
failure = { version = "0.1", default-features = false, features = ["std"] }
iq-cli-derive = { version = "0", path = "../iq-cli-derive" }
lazy_static = "1"
log = { version = "0.4", optional = true }
simplelog = { version = "0.5", optional = true }
term = "0.5"

[dev-dependencies]
assert_matches = "1"

[features]
default = ["errors", "options", "status"]
default = ["errors", "logging", "options", "status"]
errors = []
logging = ["log", "simplelog"]
options = ["iq-cli-derive/options"]
status = []

Expand Down
31 changes: 31 additions & 0 deletions iq-cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,18 @@ extern crate failure;
extern crate iq_cli_derive;
#[macro_use]
extern crate lazy_static;
#[cfg(feature = "log")]
pub extern crate log;
#[cfg(feature = "simplelog")]
extern crate simplelog;
extern crate term;

#[cfg(all(test, feature = "options"))]
#[macro_use]
extern crate assert_matches;

#[cfg(feature = "simplelog")]
use simplelog::{CombinedLogger, LevelFilter, TermLogger};
pub use term::color::{self, Color};

mod error;
Expand All @@ -60,3 +66,28 @@ pub use error::Error;
#[cfg(feature = "options")]
pub use options::Options;
pub use shell::{config, status, ColorConfig, Stream};

/// Initialize a command-line app with the given options
// TODO: better API for this
#[allow(unused_variables)]
pub fn init(color_config: ColorConfig, verbose: bool) {
config(color_config);
#[cfg(feature = "simplelog")]
init_logging(verbose);
}

/// Initialize the logging subsystem (i.e. simplelog)
#[cfg(feature = "simplelog")]
fn init_logging(verbose: bool) {
let level_filter = if verbose {
LevelFilter::Debug
} else {
LevelFilter::Info
};

let config = simplelog::Config::default();

if let Some(logger) = TermLogger::new(level_filter, config) {
CombinedLogger::init(vec![logger]).unwrap()
}
}
216 changes: 216 additions & 0 deletions iq-cli/src/macros/log.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//
// TODO: find a way to re-export the upstream macros rather than copypasta

//! Logging macros, originally from:
//! <https://github.com/rust-lang-nursery/log/blob/master/src/macros.rs>
/// The standard logging macro.
///
/// This macro will generically log with the specified `Level` and `format!`
/// based argument list.
///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate log;
/// use log::Level;
///
/// # fn main() {
/// let data = (42, "Forty-two");
/// let private_data = "private";
///
/// log!(Level::Error, "Received errors: {}, {}", data.0, data.1);
/// log!(target: "app_events", Level::Warn, "App warning: {}, {}, {}",
/// data.0, data.1, private_data);
/// # }
/// ```
#[macro_export]
macro_rules! log {
(target: $target:expr, $lvl:expr, $($arg:tt)+) => ({
let lvl = $lvl;
if lvl <= $crate::log::STATIC_MAX_LEVEL && lvl <= $crate::log::max_level() {
$crate::log::__private_api_log(
format_args!($($arg)+),
lvl,
&($target, module_path!(), file!(), line!()),
);
}
});
($lvl:expr, $($arg:tt)+) => (log!(target: module_path!(), $lvl, $($arg)+))
}

/// Logs a message at the error level.
///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate log;
/// # fn main() {
/// let (err_info, port) = ("No connection", 22);
///
/// error!("Error: {} on port {}", err_info, port);
/// error!(target: "app_events", "App Error: {}, Port: {}", err_info, 22);
/// # }
/// ```
#[macro_export]
macro_rules! error {
(target: $target:expr, $($arg:tt)*) => (
log!(target: $target, $crate::log::Level::Error, $($arg)*);
);
($($arg:tt)*) => (
log!($crate::log::Level::Error, $($arg)*);
)
}

/// Logs a message at the warn level.
///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate log;
/// # fn main() {
/// let warn_description = "Invalid Input";
///
/// warn!("Warning! {}!", warn_description);
/// warn!(target: "input_events", "App received warning: {}", warn_description);
/// # }
/// ```
#[macro_export]
macro_rules! warn {
(target: $target:expr, $($arg:tt)*) => (
log!(target: $target, $crate::log::Level::Warn, $($arg)*);
);
($($arg:tt)*) => (
log!($crate::log::Level::Warn, $($arg)*);
)
}

/// Logs a message at the info level.
///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate log;
/// # fn main() {
/// # struct Connection { port: u32, speed: f32 }
/// let conn_info = Connection { port: 40, speed: 3.20 };
///
/// info!("Connected to port {} at {} Mb/s", conn_info.port, conn_info.speed);
/// info!(target: "connection_events", "Successfull connection, port: {}, speed: {}",
/// conn_info.port, conn_info.speed);
/// # }
/// ```
#[macro_export]
macro_rules! info {
(target: $target:expr, $($arg:tt)*) => (
log!(target: $target, $crate::log::Level::Info, $($arg)*);
);
($($arg:tt)*) => (
log!($crate::log::Level::Info, $($arg)*);
)
}

/// Logs a message at the debug level.
///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate log;
/// # fn main() {
/// # struct Position { x: f32, y: f32 }
/// let pos = Position { x: 3.234, y: -1.223 };
///
/// debug!("New position: x: {}, y: {}", pos.x, pos.y);
/// debug!(target: "app_events", "New position: x: {}, y: {}", pos.x, pos.y);
/// # }
/// ```
#[macro_export]
macro_rules! debug {
(target: $target:expr, $($arg:tt)*) => (
log!(target: $target, $crate::log::Level::Debug, $($arg)*);
);
($($arg:tt)*) => (
log!($crate::log::Level::Debug, $($arg)*);
)
}

/// Logs a message at the trace level.
///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate log;
/// # fn main() {
/// # struct Position { x: f32, y: f32 }
/// let pos = Position { x: 3.234, y: -1.223 };
///
/// trace!("Position is: x: {}, y: {}", pos.x, pos.y);
/// trace!(target: "app_events", "x is {} and y is {}",
/// if pos.x >= 0.0 { "positive" } else { "negative" },
/// if pos.y >= 0.0 { "positive" } else { "negative" });
/// # }
/// ```
#[macro_export]
macro_rules! trace {
(target: $target:expr, $($arg:tt)*) => (
log!(target: $target, $crate::log::Level::Trace, $($arg)*);
);
($($arg:tt)*) => (
log!($crate::log::Level::Trace, $($arg)*);
)
}

/// Determines if a message logged at the specified level in that module will
/// be logged.
///
/// This can be used to avoid expensive computation of log message arguments if
/// the message would be ignored anyway.
///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate log;
/// use log::Level::Debug;
///
/// # fn foo() {
/// if log_enabled!(Debug) {
/// let data = expensive_call();
/// debug!("expensive debug data: {} {}", data.x, data.y);
/// }
/// if log_enabled!(target: "Global", Debug) {
/// let data = expensive_call();
/// debug!(target: "Global", "expensive debug data: {} {}", data.x, data.y);
/// }
/// # }
/// # struct Data { x: u32, y: u32 }
/// # fn expensive_call() -> Data { Data { x: 0, y: 0 } }
/// # fn main() {}
/// ```
#[macro_export]
macro_rules! log_enabled {
(target: $target:expr, $lvl:expr) => {{
let lvl = $lvl;
lvl <= $crate::log::STATIC_MAX_LEVEL
&& lvl <= $crate::log::max_level()
&& $crate::log::__private_api_enabled(lvl, $target)
}};
($lvl:expr) => {
log_enabled!(target: module_path!(), $lvl)
};
}
3 changes: 3 additions & 0 deletions iq-cli/src/macros/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,8 @@
#[cfg(feature = "errors")]
pub mod error;

#[cfg(feature = "log")]
pub mod log;

#[cfg(feature = "status")]
pub mod status;

0 comments on commit 5acc96e

Please sign in to comment.