Skip to content

Commit 5acc96e

Browse files
committed
iq-cli: Re-export the log crate and macros
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
1 parent e2d1ebb commit 5acc96e

File tree

5 files changed

+279
-1
lines changed

5 files changed

+279
-1
lines changed

Cargo.lock

+25
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

iq-cli/Cargo.toml

+4-1
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,17 @@ appveyor = { repository = "iqlusioninc/crates" }
1818
failure = { version = "0.1", default-features = false, features = ["std"] }
1919
iq-cli-derive = { version = "0", path = "../iq-cli-derive" }
2020
lazy_static = "1"
21+
log = { version = "0.4", optional = true }
22+
simplelog = { version = "0.5", optional = true }
2123
term = "0.5"
2224

2325
[dev-dependencies]
2426
assert_matches = "1"
2527

2628
[features]
27-
default = ["errors", "options", "status"]
29+
default = ["errors", "logging", "options", "status"]
2830
errors = []
31+
logging = ["log", "simplelog"]
2932
options = ["iq-cli-derive/options"]
3033
status = []
3134

iq-cli/src/lib.rs

+31
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,18 @@ extern crate failure;
4141
extern crate iq_cli_derive;
4242
#[macro_use]
4343
extern crate lazy_static;
44+
#[cfg(feature = "log")]
45+
pub extern crate log;
46+
#[cfg(feature = "simplelog")]
47+
extern crate simplelog;
4448
extern crate term;
4549

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

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

5258
mod error;
@@ -60,3 +66,28 @@ pub use error::Error;
6066
#[cfg(feature = "options")]
6167
pub use options::Options;
6268
pub use shell::{config, status, ColorConfig, Stream};
69+
70+
/// Initialize a command-line app with the given options
71+
// TODO: better API for this
72+
#[allow(unused_variables)]
73+
pub fn init(color_config: ColorConfig, verbose: bool) {
74+
config(color_config);
75+
#[cfg(feature = "simplelog")]
76+
init_logging(verbose);
77+
}
78+
79+
/// Initialize the logging subsystem (i.e. simplelog)
80+
#[cfg(feature = "simplelog")]
81+
fn init_logging(verbose: bool) {
82+
let level_filter = if verbose {
83+
LevelFilter::Debug
84+
} else {
85+
LevelFilter::Info
86+
};
87+
88+
let config = simplelog::Config::default();
89+
90+
if let Some(logger) = TermLogger::new(level_filter, config) {
91+
CombinedLogger::init(vec![logger]).unwrap()
92+
}
93+
}

iq-cli/src/macros/log.rs

+216
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
//
11+
// TODO: find a way to re-export the upstream macros rather than copypasta
12+
13+
//! Logging macros, originally from:
14+
//! <https://github.com/rust-lang-nursery/log/blob/master/src/macros.rs>
15+
16+
/// The standard logging macro.
17+
///
18+
/// This macro will generically log with the specified `Level` and `format!`
19+
/// based argument list.
20+
///
21+
/// # Examples
22+
///
23+
/// ```rust
24+
/// # #[macro_use]
25+
/// # extern crate log;
26+
/// use log::Level;
27+
///
28+
/// # fn main() {
29+
/// let data = (42, "Forty-two");
30+
/// let private_data = "private";
31+
///
32+
/// log!(Level::Error, "Received errors: {}, {}", data.0, data.1);
33+
/// log!(target: "app_events", Level::Warn, "App warning: {}, {}, {}",
34+
/// data.0, data.1, private_data);
35+
/// # }
36+
/// ```
37+
#[macro_export]
38+
macro_rules! log {
39+
(target: $target:expr, $lvl:expr, $($arg:tt)+) => ({
40+
let lvl = $lvl;
41+
if lvl <= $crate::log::STATIC_MAX_LEVEL && lvl <= $crate::log::max_level() {
42+
$crate::log::__private_api_log(
43+
format_args!($($arg)+),
44+
lvl,
45+
&($target, module_path!(), file!(), line!()),
46+
);
47+
}
48+
});
49+
($lvl:expr, $($arg:tt)+) => (log!(target: module_path!(), $lvl, $($arg)+))
50+
}
51+
52+
/// Logs a message at the error level.
53+
///
54+
/// # Examples
55+
///
56+
/// ```rust
57+
/// # #[macro_use]
58+
/// # extern crate log;
59+
/// # fn main() {
60+
/// let (err_info, port) = ("No connection", 22);
61+
///
62+
/// error!("Error: {} on port {}", err_info, port);
63+
/// error!(target: "app_events", "App Error: {}, Port: {}", err_info, 22);
64+
/// # }
65+
/// ```
66+
#[macro_export]
67+
macro_rules! error {
68+
(target: $target:expr, $($arg:tt)*) => (
69+
log!(target: $target, $crate::log::Level::Error, $($arg)*);
70+
);
71+
($($arg:tt)*) => (
72+
log!($crate::log::Level::Error, $($arg)*);
73+
)
74+
}
75+
76+
/// Logs a message at the warn level.
77+
///
78+
/// # Examples
79+
///
80+
/// ```rust
81+
/// # #[macro_use]
82+
/// # extern crate log;
83+
/// # fn main() {
84+
/// let warn_description = "Invalid Input";
85+
///
86+
/// warn!("Warning! {}!", warn_description);
87+
/// warn!(target: "input_events", "App received warning: {}", warn_description);
88+
/// # }
89+
/// ```
90+
#[macro_export]
91+
macro_rules! warn {
92+
(target: $target:expr, $($arg:tt)*) => (
93+
log!(target: $target, $crate::log::Level::Warn, $($arg)*);
94+
);
95+
($($arg:tt)*) => (
96+
log!($crate::log::Level::Warn, $($arg)*);
97+
)
98+
}
99+
100+
/// Logs a message at the info level.
101+
///
102+
/// # Examples
103+
///
104+
/// ```rust
105+
/// # #[macro_use]
106+
/// # extern crate log;
107+
/// # fn main() {
108+
/// # struct Connection { port: u32, speed: f32 }
109+
/// let conn_info = Connection { port: 40, speed: 3.20 };
110+
///
111+
/// info!("Connected to port {} at {} Mb/s", conn_info.port, conn_info.speed);
112+
/// info!(target: "connection_events", "Successfull connection, port: {}, speed: {}",
113+
/// conn_info.port, conn_info.speed);
114+
/// # }
115+
/// ```
116+
#[macro_export]
117+
macro_rules! info {
118+
(target: $target:expr, $($arg:tt)*) => (
119+
log!(target: $target, $crate::log::Level::Info, $($arg)*);
120+
);
121+
($($arg:tt)*) => (
122+
log!($crate::log::Level::Info, $($arg)*);
123+
)
124+
}
125+
126+
/// Logs a message at the debug level.
127+
///
128+
/// # Examples
129+
///
130+
/// ```rust
131+
/// # #[macro_use]
132+
/// # extern crate log;
133+
/// # fn main() {
134+
/// # struct Position { x: f32, y: f32 }
135+
/// let pos = Position { x: 3.234, y: -1.223 };
136+
///
137+
/// debug!("New position: x: {}, y: {}", pos.x, pos.y);
138+
/// debug!(target: "app_events", "New position: x: {}, y: {}", pos.x, pos.y);
139+
/// # }
140+
/// ```
141+
#[macro_export]
142+
macro_rules! debug {
143+
(target: $target:expr, $($arg:tt)*) => (
144+
log!(target: $target, $crate::log::Level::Debug, $($arg)*);
145+
);
146+
($($arg:tt)*) => (
147+
log!($crate::log::Level::Debug, $($arg)*);
148+
)
149+
}
150+
151+
/// Logs a message at the trace level.
152+
///
153+
/// # Examples
154+
///
155+
/// ```rust
156+
/// # #[macro_use]
157+
/// # extern crate log;
158+
/// # fn main() {
159+
/// # struct Position { x: f32, y: f32 }
160+
/// let pos = Position { x: 3.234, y: -1.223 };
161+
///
162+
/// trace!("Position is: x: {}, y: {}", pos.x, pos.y);
163+
/// trace!(target: "app_events", "x is {} and y is {}",
164+
/// if pos.x >= 0.0 { "positive" } else { "negative" },
165+
/// if pos.y >= 0.0 { "positive" } else { "negative" });
166+
/// # }
167+
/// ```
168+
#[macro_export]
169+
macro_rules! trace {
170+
(target: $target:expr, $($arg:tt)*) => (
171+
log!(target: $target, $crate::log::Level::Trace, $($arg)*);
172+
);
173+
($($arg:tt)*) => (
174+
log!($crate::log::Level::Trace, $($arg)*);
175+
)
176+
}
177+
178+
/// Determines if a message logged at the specified level in that module will
179+
/// be logged.
180+
///
181+
/// This can be used to avoid expensive computation of log message arguments if
182+
/// the message would be ignored anyway.
183+
///
184+
/// # Examples
185+
///
186+
/// ```rust
187+
/// # #[macro_use]
188+
/// # extern crate log;
189+
/// use log::Level::Debug;
190+
///
191+
/// # fn foo() {
192+
/// if log_enabled!(Debug) {
193+
/// let data = expensive_call();
194+
/// debug!("expensive debug data: {} {}", data.x, data.y);
195+
/// }
196+
/// if log_enabled!(target: "Global", Debug) {
197+
/// let data = expensive_call();
198+
/// debug!(target: "Global", "expensive debug data: {} {}", data.x, data.y);
199+
/// }
200+
/// # }
201+
/// # struct Data { x: u32, y: u32 }
202+
/// # fn expensive_call() -> Data { Data { x: 0, y: 0 } }
203+
/// # fn main() {}
204+
/// ```
205+
#[macro_export]
206+
macro_rules! log_enabled {
207+
(target: $target:expr, $lvl:expr) => {{
208+
let lvl = $lvl;
209+
lvl <= $crate::log::STATIC_MAX_LEVEL
210+
&& lvl <= $crate::log::max_level()
211+
&& $crate::log::__private_api_enabled(lvl, $target)
212+
}};
213+
($lvl:expr) => {
214+
log_enabled!(target: module_path!(), $lvl)
215+
};
216+
}

iq-cli/src/macros/mod.rs

+3
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,8 @@
33
#[cfg(feature = "errors")]
44
pub mod error;
55

6+
#[cfg(feature = "log")]
7+
pub mod log;
8+
69
#[cfg(feature = "status")]
710
pub mod status;

0 commit comments

Comments
 (0)