easy_log/
lib.rs

1use chrono::{Datelike, Timelike, Utc};
2use colored::Colorize;
3pub mod map;
4pub use map::Map;
5
6/// The Logger object.
7#[derive(Default, Clone)]
8pub struct Logger {
9    pub action: Option<String>,
10    pub input: Option<String>,
11    pub output: Option<String>,
12}
13
14fn time_now() -> String {
15    let now = Utc::now();
16    format!(
17        "{:02}-{:02}-{:02} {:02}:{:02}:{:02}.{:03}",
18        now.year() % 100,
19        now.month(),
20        now.day(),
21        now.hour(),
22        now.minute(),
23        now.second(),
24        now.nanosecond() / 1_000_000,
25    )
26}
27
28impl Logger {
29    /// Create a logger
30    pub fn new() -> Self {
31        Logger::default()
32    }
33
34    pub fn action<T: std::fmt::Display>(mut self, action: T) -> Self {
35        self.action = Some(action.to_string());
36        self
37    }
38    pub fn input<T: std::fmt::Display>(mut self, input: T) -> Self {
39        self.input = Some(input.to_string());
40        self
41    }
42    pub fn output<T: std::fmt::Display>(mut self, output: T) -> Self {
43        self.output = Some(output.to_string());
44        self
45    }
46
47    pub fn print(self, color: &str) -> Self {
48        if let Some(action) = self.action.clone() {
49            eprintln!(
50                "{} [{}]",
51                action.to_uppercase().color(color).bold(),
52                time_now(),
53            );
54        }
55        if let Some(input) = self.input.clone() {
56            eprintln!(" >>> {}", input);
57        }
58        if let Some(output) = self.output.clone() {
59            eprintln!(" <<< {}", output);
60        }
61        self
62    }
63    pub fn ok(self) -> Self {
64        self.print("green")
65    }
66    pub fn warn(self) -> Self {
67        self.print("yellow")
68    }
69    pub fn err(self) -> Self {
70        self.print("red")
71    }
72}
73
74#[cfg(test)]
75mod tests {
76    use super::*;
77    #[test]
78    fn ok() {
79        Logger::new()
80            .action("ok_test")
81            .input(map![test1: "test1str"])
82            .output(map![test2: 345345, test3: "sussy baka"])
83            .ok();
84    }
85    #[test]
86    fn le_grande_test() {
87        use super::{map, Logger, Map};
88
89        let default = Logger::new(); // empty
90        let default2 = Logger::default(); // same as the above
91
92        let default = default.ok(); // does nothing
93        let default = default.action("test").ok(); // prints TEST: in green
94        let default = default.ok();
95
96        assert_eq!(
97            map![test1: 234],
98            Map(&[("test1".to_string(), "234".to_string())]) // auto conversion to String
99        );
100
101        let test2 = "This is a test.";
102        assert_eq!(
103            map![test2],
104            Map(&[("test2".to_string(), "This is a test.".to_string())]) // auto expansion
105        );
106
107        // you can chain methods
108        default
109            .action("test2")
110            .input(map![test2])
111            .output(36) // not only maps
112            .warn(); // prints the action in yellow
113
114        default2
115            .action("test")
116            .action("third") // you can override the preferences set before
117            .err();
118
119        let really = true;
120        Logger::new()
121            .action("final")
122            .input(map![what: "test"])
123            .output(map![of_what: "of this lib", really])
124            .print("purple");
125    }
126}