use env_logger::{
fmt::{
Color,
Style,
StyledValue,
},
Builder,
};
use git_cliff_core::error::{
Error,
Result,
};
#[cfg(feature = "github")]
use git_cliff_core::github::{
FINISHED_FETCHING_MSG,
START_FETCHING_MSG,
};
#[cfg(feature = "github")]
use indicatif::{
ProgressBar,
ProgressStyle,
};
use log::Level;
use std::io::Write;
use std::sync::atomic::{
AtomicUsize,
Ordering,
};
use std::{
env,
fmt,
};
const LOGGER_ENV: &str = "RUST_LOG";
static MAX_MODULE_WIDTH: AtomicUsize = AtomicUsize::new(0);
struct Padded<T> {
value: T,
width: usize,
}
impl<T: fmt::Display> fmt::Display for Padded<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{: <width$}", self.value, width = self.width)
}
}
fn max_target_width(target: &str) -> usize {
let max_width = MAX_MODULE_WIDTH.load(Ordering::Relaxed);
if max_width < target.len() {
MAX_MODULE_WIDTH.store(target.len(), Ordering::Relaxed);
target.len()
} else {
max_width
}
}
fn colored_level(style: &mut Style, level: Level) -> StyledValue<'_, &'static str> {
match level {
Level::Trace => style.set_color(Color::Magenta).value("TRACE"),
Level::Debug => style.set_color(Color::Blue).value("DEBUG"),
Level::Info => style.set_color(Color::Green).value("INFO "),
Level::Warn => style.set_color(Color::Yellow).value("WARN "),
Level::Error => style.set_color(Color::Red).value("ERROR"),
}
}
#[cfg(feature = "github")]
lazy_static::lazy_static! {
pub static ref PROGRESS_BAR: ProgressBar = {
let progress_bar = ProgressBar::new_spinner();
progress_bar.set_style(
ProgressStyle::with_template("{spinner:.green} {msg}")
.unwrap()
.tick_strings(&[
"▹▹▹▹▹",
"▸▹▹▹▹",
"▹▸▹▹▹",
"▹▹▸▹▹",
"▹▹▹▸▹",
"▹▹▹▹▸",
"▪▪▪▪▪",
]),
);
progress_bar
};
}
pub fn init() -> Result<()> {
let mut builder = Builder::new();
builder.format(move |f, record| {
let target = record.target();
let max_width = max_target_width(target);
let mut style = f.style();
let level = colored_level(&mut style, record.level());
let mut style = f.style();
let target = style.set_bold(true).value(Padded {
value: target,
width: max_width,
});
#[cfg(feature = "github")]
{
let message = record.args().to_string();
if message.starts_with(START_FETCHING_MSG) {
PROGRESS_BAR
.enable_steady_tick(std::time::Duration::from_millis(80));
PROGRESS_BAR.set_message(message);
Ok(())
} else if message.starts_with(FINISHED_FETCHING_MSG) {
PROGRESS_BAR.finish_and_clear();
Ok(())
} else {
writeln!(f, " {} {} > {}", level, target, record.args(),)
}
}
#[cfg(not(feature = "github"))]
{
writeln!(f, " {} {} > {}", level, target, record.args(),)
}
});
if let Ok(var) = env::var(LOGGER_ENV) {
builder.parse_filters(&var);
}
builder
.try_init()
.map_err(|e| Error::LoggerError(e.to_string()))
}