diary_cli/
logger.rs

1use soulog::*;
2use crate::cli::VERBOSE;
3
4pub struct DynamicLogger {
5    verbose: Option<Verbose>,
6    quiet: Option<Quiet>,
7}
8
9macro_rules! one_or_other {
10    ($name:ident($one:expr, $two:expr) $code:block) => {'code: {
11        if let Some($name) = &mut $one {
12            break 'code ($code);
13        }
14        if let Some($name) = &mut $two {
15            break 'code ($code);
16        }
17
18        panic!("DynamicLogger of no logger type (should not happen)");
19    }}
20}
21
22impl Logger for DynamicLogger {
23    fn new() -> Self {
24        unsafe { if VERBOSE {
25            Self {
26                verbose: Some(Verbose::new()),
27                quiet: None,
28            }
29        } else {
30            Self {
31                verbose: None,
32                quiet: Some(Quiet::new()),
33            }
34        }}
35    }
36
37    fn hollow(&self) -> Self { Self::new() }
38
39    fn crash<T>(&mut self) -> T {one_or_other!(x(self.verbose, self.quiet) {
40        x.crash()
41    })}
42
43    fn verbose(&mut self, log: Log) {one_or_other!(x(self.verbose, self.quiet) {
44        x.verbose(log)
45    })}
46
47    fn vital(&mut self, log: Log) {one_or_other!(x(self.verbose, self.quiet) {
48        x.vital(log)
49    })}
50
51    fn error(&mut self, log: Log) -> ErrorResponse {one_or_other!(x(self.verbose, self.quiet) {
52        x.error(log)
53    })}
54}
55
56pub struct Verbose {
57    retry_count: u8,
58}
59
60impl Logger for Verbose {
61    fn new() -> Self { Self { retry_count: 2 } }
62    fn hollow(&self) -> Self { Self::new() }
63
64    fn crash<T>(&mut self) -> T {
65        let mut logger = Self::new();
66        log!((logger.vital) Diary("if the fatal error occurred during any writing to the archive, the archive may be corrupted! If so, then use `diary-cli rollback` to roll-back to the latest backup (that was made before any modification of the archive") as Warning);
67        std::process::exit(1)
68    }
69
70    fn verbose(&mut self, log: Log) {
71        self.retry_count = 2;
72        println!("{}", colour_format!(blue("["), cyan(log.origin), blue("] "), none(log.message)));
73    }
74
75    fn error(&mut self, log: Log) -> ErrorResponse {
76        let message = match log.log_type {
77            LogType::Failure => colour_format![blue("["), red(log.origin), blue("] "), red("Failure"), blue(": "), none(log.message)],
78            LogType::Fatal => colour_format![blue("["), red(log.origin), blue("] "), red("Fatal"), blue(": "), none(log.message)],
79            _ => panic!("meta error: invalid error log type '{:?}'", log.log_type),
80        }; println!("{message}");
81
82        if ErrorResponse::AskUser.allowed_in(&log) { return ErrorResponse::AskUser };
83        if ErrorResponse::Retry.allowed_in(&log) && self.retry_count > 0 {
84            self.retry_count -= 1;
85            // wait for a bit
86            std::thread::sleep(std::time::Duration::from_millis(800));
87            return ErrorResponse::Retry;
88        };
89
90        ErrorResponse::Crash
91    }
92
93    fn vital(&mut self, log: Log) {
94        let message = match log.log_type {
95            LogType::Inconvenience => colour_format![blue("["), yellow(log.origin), blue("] "), yellow("Inconvenience"), blue(": "), none(log.message)],
96            LogType::Warning => colour_format![blue("["), yellow(log.origin), blue("] "), yellow("Warning"), blue(": "), none(log.message)],
97            LogType::Result => colour_format![blue("["), green("Result"), blue("] "), green(log.origin), blue(": "), none(log.message)],
98            LogType::Log => colour_format!(blue("["), cyan(log.origin), blue("] "), none(log.message)),
99            _ => panic!("meta error: invalid error log type '{:?}'", log.log_type),
100        }; println!("{message}");
101    }
102}
103
104pub struct Quiet {
105    retry_count: u8,
106}
107
108impl Logger for Quiet {
109    fn new() -> Self { Self { retry_count: 2 } }
110    fn hollow(&self) -> Self { Self::new() }
111
112    fn crash<T>(&mut self) -> T {
113        let mut logger = Self::new();
114        log!((logger.vital) Diary("The archive may now be corrupted! Use `diary-cli rollback` to roll-back to the latest backup (that was made before any modification of the archive") as Warning);
115        std::process::exit(1)
116    }
117
118    fn verbose(&mut self, _: Log) {
119        self.retry_count = 2;
120    }
121
122    fn error(&mut self, log: Log) -> ErrorResponse {
123        let message = match log.log_type {
124            LogType::Failure => colour_format![blue("["), red(log.origin), blue("] "), red("Failure"), blue(": "), none(log.message)],
125            LogType::Fatal => colour_format![blue("["), red(log.origin), blue("] "), red("Fatal"), blue(": "), none(log.message)],
126            _ => panic!("meta error: invalid error log type '{:?}'", log.log_type),
127        }; println!("{message}");
128
129        if ErrorResponse::AskUser.allowed_in(&log) { return ErrorResponse::AskUser };
130        if ErrorResponse::Retry.allowed_in(&log) && self.retry_count > 0 {
131            self.retry_count -= 1;
132            // wait for a bit
133            std::thread::sleep(std::time::Duration::from_millis(800));
134            return ErrorResponse::Retry;
135        };
136
137        ErrorResponse::Crash
138    }
139
140    fn vital(&mut self, log: Log) {
141        let message = match log.log_type {
142            LogType::Inconvenience => colour_format![blue("["), yellow(log.origin), blue("] "), yellow("Inconvenience"), blue(": "), none(log.message)],
143            LogType::Warning => colour_format![blue("["), yellow(log.origin), blue("] "), yellow("Warning"), blue(": "), none(log.message)],
144            LogType::Result => colour_format![blue("["), green("Result"), blue("] "), green(log.origin), blue(": "), none(log.message)],
145            LogType::Log => colour_format!(blue("["), cyan(log.origin), blue("] "), none(log.message)),
146            _ => panic!("meta error: invalid error log type '{:?}'", log.log_type),
147        }; println!("{message}");
148    }
149}