use std::fmt::Display;
use std::fs;
use std::path::Path;
use crate::blocks::LogBlock;
use crate::printer::{Printable, Printer, PrinterFormat};
use crate::{LogContent, LogLevel};
#[derive(Debug, Clone)]
pub struct Log<'a> {
pub level: LogLevel,
pub content: LogContent<'a>,
pub cause: Option<Box<Log<'a>>>,
}
impl<'a> Log<'a> {
pub fn new(level: LogLevel) -> Log<'a> {
Log {
level,
content: LogContent::new(),
cause: None,
}
}
pub fn trace() -> Log<'a> {
Self::new(LogLevel::trace())
}
pub fn debug() -> Log<'a> {
Self::new(LogLevel::debug())
}
pub fn info() -> Log<'a> {
Self::new(LogLevel::info())
}
pub fn warn() -> Log<'a> {
Self::new(LogLevel::warn())
}
pub fn error() -> Log<'a> {
Self::new(LogLevel::error())
}
pub fn set_cause<F>(mut self, builder: F) -> Self
where
F: FnOnce(Log) -> Log,
{
let new_log = Log::new(self.level);
let new_log = builder(new_log);
self.cause = Some(Box::new(new_log));
self
}
pub fn add_block(mut self, block: impl Into<LogBlock<'a>>) -> Self {
self.content = self.content.add_block(block.into());
self
}
pub fn log_plain_text(&self) {
println!("{}", self.to_plain_text());
}
pub fn log_styled_text(&self) {
println!("{}", self.to_styled_text());
}
pub fn log(&self) {
println!("{}", self.to_text());
}
pub fn append_plain_to_file(&self, file: &Path) -> std::io::Result<()> {
let content = self.to_plain_text();
fs::write(file, content)
}
pub fn append_styled_to_file(&self, file: &Path) -> std::io::Result<()> {
let content = self.to_plain_text();
fs::write(file, content)
}
pub fn to_plain_text(&self) -> String {
self.print_to_string(self.level, PrinterFormat::Plain)
}
pub fn to_styled_text(&self) -> String {
self.print_to_string(self.level, PrinterFormat::Styled)
}
pub fn to_text(&self) -> String {
self.print_to_string(self.level, PrinterFormat::Default)
}
pub fn make_owned(self) -> Log<'static> {
Log {
level: self.level,
content: self.content.make_owned(),
cause: self.cause.map(|v| Box::new(v.make_owned())),
}
}
}
impl<'a> Printable<'a> for Log<'a> {
fn print<'s>(&'s self, printer: &mut Printer<'a>)
where
'a: 's,
{
self.content.print(printer);
if let Some(cause) = &self.cause {
printer.push_plain_text("\n");
cause.print(printer);
}
}
}
impl<'a> Display for Log<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut printer = Printer::new(self.level, PrinterFormat::Plain);
self.print(&mut printer);
printer.fmt(f, PrinterFormat::Plain)
}
}
#[cfg(test)]
mod tests {
use crate::Log;
#[test]
fn test_display() {
println!("{}", Log::error());
}
}