use std::fmt::Write;
use colored::{Color, Colorize};
use smallstr::SmallString;
use smallvec::SmallVec;
use tracing::Level;
use super::{Fields, LogLevelExt};
const CALL_INDENTATION: &str = " ";
const ARGUMENT_INDENTATION: &str = " ";
pub(crate) fn short_path(
file: &str,
keep_count: usize,
) -> String {
let parts: SmallVec<[&str; 8]> = file.split(['/', '\\'])
.filter(|s| !s.is_empty()).collect();
if parts.len() <= keep_count {
file.to_string()
} else {
format!(
".../{}",
parts[parts.len() - keep_count..].join("/")
)
}
}
pub(crate) fn now_string() -> SmallString<[u8; 64]> {
let now_date_time = chrono::Local::now();
let subsec_nanoseconds = now_date_time.timestamp_subsec_nanos();
let mut now_string = SmallString::new();
write!(
&mut now_string,
"{}.{:03}_{:03}_{:03}",
now_date_time.format("%Y-%m-%d %H:%M:%S"),
subsec_nanoseconds / 1_000_000,
(subsec_nanoseconds / 1_000) % 1_000,
subsec_nanoseconds % 1_000
);
now_string
}
pub(crate) fn write_fields(
out: &mut String,
level: &Level,
fields: &Fields,
) {
if fields.is_empty() {
return;
}
let longest_field_name_width = fields.iter().map(|(name, _)| {
name.chars().count()
}).max().unwrap_or(0);
for (
name,
value,
) in fields.iter() {
let mut lines = value.lines();
let Some(
first_line,
) = lines.next() else {
continue;
};
let _ = writeln!(
out,
"{}{ARGUMENT_INDENTATION}{name:<longest_field_name_width$} {} {first_line}",
"|".color(level.color()),
"=".color(Color::Blue),
);
let hang = " ".repeat(ARGUMENT_INDENTATION.len() + longest_field_name_width + 3);
for line in lines {
let _ = writeln!(out, "{}{hang}{line}", "|".color(level.color()));
}
}
}
pub(crate) fn write_call(
out: &mut String,
level: &Level,
name: &'static str,
file: &str,
line_number: u32,
fields: Option<&Fields>,
) {
let mut line: SmallString<[u8; 8]> = SmallString::new();
let _ = write!(&mut line, "{}", line_number);
let _ = writeln!(
out,
"{}{CALL_INDENTATION}{} {} {}{}{}",
"|".color(level.color()),
name.color(Color::White).bold(),
"at".color(Color::Blue),
file.color(Color::BrightBlack),
":".color(Color::BrightBlack),
line.color(Color::BrightBlack),
);
if let Some(
fields,
) = &fields {
write_fields(out, level, fields);
}
}