use crate::config::Config;
use env_logger::Builder;
use indicatif::{ProgressBar, ProgressStyle};
use log::LevelFilter;
use std::fs::{self, File, OpenOptions};
use std::io::Write;
use std::sync::Mutex;
use std::sync::atomic::{AtomicBool, Ordering};
static QUIET_MODE: AtomicBool = AtomicBool::new(false);
static LOG_FILE: Mutex<Option<File>> = Mutex::new(None);
pub fn init(debug: bool, quiet: bool) {
QUIET_MODE.store(quiet, Ordering::Relaxed);
init_log_file();
let level = if quiet {
LevelFilter::Off
} else if debug {
LevelFilter::Debug
} else {
LevelFilter::Info
};
Builder::new()
.filter_level(level)
.format(|buf, record| {
write_to_log_file(&format!("[{}] {}", record.level(), record.args()));
match record.level() {
log::Level::Debug => writeln!(buf, "\x1b[90m*\x1b[0m {}", record.args()), log::Level::Info => writeln!(buf, "\x1b[33m>\x1b[0m {}", record.args()), log::Level::Warn => writeln!(buf, "\x1b[93m!\x1b[0m {}", record.args()), log::Level::Error => writeln!(buf, "\x1b[91m✗\x1b[0m {}", record.args()), log::Level::Trace => writeln!(buf, "\x1b[90m·\x1b[0m {}", record.args()), }
})
.init();
}
fn init_log_file() {
let logs_dir = Config::global_logs_dir();
if fs::create_dir_all(&logs_dir).is_err() {
return;
}
let timestamp = chrono::Local::now().format("%Y-%m-%dT%H-%M-%S");
let log_path = logs_dir.join(format!("zag-{timestamp}.log"));
if let Ok(file) = OpenOptions::new().create(true).append(true).open(&log_path)
&& let Ok(mut guard) = LOG_FILE.lock()
{
*guard = Some(file);
}
}
fn write_to_log_file(msg: &str) {
if let Ok(mut guard) = LOG_FILE.lock()
&& let Some(ref mut file) = *guard
{
let timestamp = chrono::Local::now().format("%Y-%m-%dT%H:%M:%S%.3f");
let _ = writeln!(file, "{timestamp} {msg}");
}
}
pub fn is_quiet() -> bool {
QUIET_MODE.load(Ordering::Relaxed)
}
pub fn spinner(msg: impl Into<String>) -> ProgressBar {
let pb = ProgressBar::new_spinner();
if is_quiet() {
pb.set_draw_target(indicatif::ProgressDrawTarget::hidden());
return pb;
}
pb.set_style(
ProgressStyle::default_spinner()
.tick_chars("⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏")
.template("{spinner:.cyan} {msg}")
.unwrap(),
);
pb.set_message(msg.into());
pb.enable_steady_tick(std::time::Duration::from_millis(80));
pb
}
pub fn finish_spinner_quiet(pb: &ProgressBar) {
pb.finish_and_clear();
}