diff --git a/Cargo.toml b/Cargo.toml index 6dfccdb..71d9091 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,6 +30,7 @@ libc = "0.2.47" term_size = { version = "0.3.1", optional = true } crossbeam-channel = "0.3.6" lazy_static = "1.2.0" +chrono = "0.4.6" [dependencies.num] default-features = false diff --git a/examples/logger.rs b/examples/logger.rs index 81ab03d..fa9722a 100644 --- a/examples/logger.rs +++ b/examples/logger.rs @@ -10,7 +10,7 @@ fn main() { let mut siv = cursive::Cursive::default(); siv.add_global_callback('q', cursive::Cursive::quit); siv.add_global_callback('~', cursive::Cursive::toggle_debug_view); - siv.add_global_callback('l', |_| debug!("Wooo")); + siv.add_global_callback('l', |_| warn!("Wooo")); error!("BAD!!!"); siv.run(); diff --git a/src/cursive.rs b/src/cursive.rs index 093404e..e3881ad 100644 --- a/src/cursive.rs +++ b/src/cursive.rs @@ -188,7 +188,6 @@ impl Cursive { let stack = self.screen_mut(); if let Some(pos) = stack.find_layer_from_id(DEBUG_VIEW_ID) { - info!("Foundit"); stack.remove_layer(pos); } else { stack.add_layer( diff --git a/src/lib.rs b/src/lib.rs index 94c8cc5..aa05d81 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -81,6 +81,7 @@ extern crate maplit; #[cfg(unix)] extern crate signal_hook; +extern crate chrono; extern crate libc; extern crate num; extern crate owning_ref; diff --git a/src/logger.rs b/src/logger.rs index e6beb32..63347f2 100644 --- a/src/logger.rs +++ b/src/logger.rs @@ -10,9 +10,19 @@ struct CursiveLogger; static LOGGER: CursiveLogger = CursiveLogger; +/// A log record. +pub struct Record { + /// Log level used for this record + pub level: log::Level, + /// Time this message was logged + pub time: chrono::DateTime, + /// Message content + pub message: String, +} + lazy_static! { /// Circular buffer for logs. Use it to implement `DebugView`. - pub static ref LOGS: Mutex> = + pub static ref LOGS: Mutex> = Mutex::new(VecDeque::new()); } @@ -27,7 +37,11 @@ impl log::Log for CursiveLogger { if logs.len() == logs.capacity() { logs.pop_front(); } - logs.push_back((record.level(), format!("{}", record.args()))); + logs.push_back(Record { + level: record.level(), + message: format!("{}", record.args()), + time: chrono::Utc::now(), + }); } fn flush(&self) {} diff --git a/src/theme/color.rs b/src/theme/color.rs index 9c84543..e71d006 100644 --- a/src/theme/color.rs +++ b/src/theme/color.rs @@ -121,7 +121,7 @@ impl Color { /// * `"light green"` becomes `Color::Light(BaseColor::Green)` /// * `"default"` becomes `Color::TerminalDefault` /// * `"#123456"` becomes `Color::Rgb(0x12, 0x34, 0x56)` - pub(crate) fn parse(value: &str) -> Option { + pub fn parse(value: &str) -> Option { Some(match value { "black" => Color::Dark(BaseColor::Black), "red" => Color::Dark(BaseColor::Red), diff --git a/src/theme/color_style.rs b/src/theme/color_style.rs index 52e17a1..bac3582 100644 --- a/src/theme/color_style.rs +++ b/src/theme/color_style.rs @@ -1,4 +1,4 @@ -use super::{Color, ColorPair, Palette, PaletteColor}; +use super::{BaseColor, Color, ColorPair, Palette, PaletteColor}; /// Possible color style for a cell. /// @@ -91,6 +91,12 @@ impl From for ColorStyle { } } +impl From for ColorStyle { + fn from(color: BaseColor) -> Self { + Self::new(Color::Dark(color), PaletteColor::View) + } +} + impl From for ColorStyle { fn from(color: PaletteColor) -> Self { Self::new(color, PaletteColor::View) diff --git a/src/views/debug_view.rs b/src/views/debug_view.rs index 159f78f..f4305fe 100644 --- a/src/views/debug_view.rs +++ b/src/views/debug_view.rs @@ -1,4 +1,5 @@ use logger; +use theme; use vec::Vec2; use view::View; use Printer; @@ -24,8 +25,26 @@ impl View for DebugView { // Only print the last logs, so skip what doesn't fit let skipped = logs.len().saturating_sub(printer.size.y); - for (i, &(level, ref text)) in logs.iter().skip(skipped).enumerate() { - printer.print((0, i), &format!("[{}] {}", level, text)); + for (i, record) in logs.iter().skip(skipped).enumerate() { + // TODO: Apply style to message? (Ex: errors in bold?) + printer.print( + (0, i), + &format!( + "{} | [ ] {}", + record.time.with_timezone(&chrono::Local).format("%T%.3f"), + record.message + ), + ); + let color = match record.level { + log::Level::Error => theme::BaseColor::Red, + log::Level::Warn => theme::BaseColor::Yellow, + log::Level::Info => theme::BaseColor::Black, + log::Level::Debug => theme::BaseColor::Green, + log::Level::Trace => theme::BaseColor::Blue, + }; + printer.with_color(color.into(), |printer| { + printer.print((16, i), &format!("{:5}", record.level)) + }); } } @@ -33,10 +52,12 @@ impl View for DebugView { // TODO: read the logs, and compute the required size to print it. let logs = logger::LOGS.lock().unwrap(); - // The longest line sets the width + let level_width = 8; // Width of "[ERROR] " + let time_width = 16; // Width of "23:59:59.123 | " + // The longest line sets the width let w = logs .iter() - .map(|&(_, ref content)| content.width() + "[ERROR] ".width()) + .map(|record| record.message.width() + level_width + time_width) .max() .unwrap_or(1); let h = logs.len();