use std::str::FromStr; use std::io::Write; use serde::{Serialize, Deserialize}; use crate::error; use crate::models::Entry; use crate::commands::Facts; pub mod text; pub mod csv; pub mod json; pub mod ids; pub mod ical; pub mod custom; pub mod chart; #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "lowercase")] pub enum Formatter { #[default] Text, Csv, Json, Ids, Ical, Chart, Custom(String), } impl Formatter { /// Prints the given entries to the specified output device. /// /// the current time is given as the `now` argument and the offset from UTC /// to the local timezone is given in `offset` to prevent this function from /// using a secondary effect to retrieve the time and conver dates. This /// also makes it easier to test. pub fn print_formatted(&self, entries: Vec, out: &mut O, err: &mut E, facts: &Facts, ids: bool) -> error::Result<()> where O: Write, E: Write, { match &self { Formatter::Text => text::print_formatted(entries, out, facts, ids)?, Formatter::Csv => csv::print_formatted(entries, out, ids)?, Formatter::Json => json::print_formatted(entries, out)?, Formatter::Ids => ids::print_formatted(entries, out)?, Formatter::Ical => ical::print_formatted(entries, out, facts.now)?, Formatter::Chart => chart::print_formatted(entries, out, facts)?, Formatter::Custom(name) => custom::print_formatted(name, entries, out, err, facts)?, } Ok(()) } } impl FromStr for Formatter { type Err = error::Error; fn from_str(s: &str) -> error::Result { Ok(match s.to_lowercase().as_str() { "text" => Formatter::Text, "csv" => Formatter::Csv, "json" => Formatter::Json, "ids" => Formatter::Ids, "ical" => Formatter::Ical, "chart" => Formatter::Chart, custom_format => Formatter::Custom(custom_format.into()), }) } }