tiempo-rs/src/formatters.rs

122 lines
3.4 KiB
Rust
Raw Normal View History

2021-06-21 17:38:51 -05:00
use std::str::FromStr;
use std::io::Write;
2021-06-18 11:27:19 -05:00
use serde::{Serialize, Deserialize};
2021-06-21 17:38:51 -05:00
use crate::error;
use crate::models::Entry;
use crate::commands::Facts;
2021-06-21 17:38:51 -05:00
2023-03-15 13:22:55 -06:00
use strum_macros::{EnumVariantNames};
use strum::VariantNames;
pub mod text;
2021-06-30 18:51:34 -05:00
pub mod csv;
2021-07-26 20:32:13 -05:00
pub mod json;
2021-07-28 21:16:03 -05:00
pub mod ids;
2021-07-29 11:02:00 -05:00
pub mod ical;
pub mod custom;
2022-08-28 15:48:47 -05:00
pub mod chart;
2021-06-28 19:32:29 -05:00
2023-03-15 13:22:55 -06:00
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, EnumVariantNames)]
2021-06-18 11:27:19 -05:00
#[serde(rename_all = "lowercase")]
2023-03-15 13:22:55 -06:00
#[strum(serialize_all = "kebab_case")]
2021-06-18 11:27:19 -05:00
pub enum Formatter {
Text,
2021-06-30 18:51:34 -05:00
Csv,
2021-07-26 20:32:13 -05:00
Json,
2021-07-28 21:16:03 -05:00
Ids,
2021-07-29 11:02:00 -05:00
Ical,
2022-08-28 15:48:47 -05:00
Chart,
2021-06-21 17:38:51 -05:00
Custom(String),
}
2021-06-29 12:04:54 -05:00
impl Default for Formatter {
fn default() -> Formatter {
Formatter::Text
}
}
2021-06-21 17:38:51 -05:00
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<O, E>(&self, entries: Vec<Entry>, out: &mut O, err: &mut E, facts: &Facts, ids: bool) -> error::Result<()>
where
O: Write,
E: Write,
{
2021-06-21 17:38:51 -05:00
match &self {
Formatter::Text => text::print_formatted(entries, out, facts, ids)?,
2021-06-30 18:51:34 -05:00
Formatter::Csv => csv::print_formatted(entries, out, ids)?,
2021-07-26 20:32:13 -05:00
Formatter::Json => json::print_formatted(entries, out)?,
2021-07-28 21:16:03 -05:00
Formatter::Ids => ids::print_formatted(entries, out)?,
Formatter::Ical => ical::print_formatted(entries, out, facts.now)?,
2022-08-28 15:48:47 -05:00
Formatter::Chart => chart::print_formatted(entries, out, facts)?,
Formatter::Custom(name) => custom::print_formatted(name, entries, out, err, facts)?,
2021-06-21 17:38:51 -05:00
}
Ok(())
}
2023-03-15 13:22:55 -06:00
/// Gets Formatter from prefix
///
/// from Formatter variants try to match with starts_with.
/// Returns error if it doesn't match.
pub fn autocomplete(s: &str) -> error::Result<Formatter> {
if s.len() > 0 {
for formatter in Formatter::VARIANTS {
if formatter.starts_with(s) {
return Formatter::from_str(formatter)
}
}
}
Err(error::Error::InvalidAutocompleteFormatter(s.to_string()))
}
2021-06-21 17:38:51 -05:00
}
impl FromStr for Formatter {
type Err = error::Error;
fn from_str(s: &str) -> error::Result<Formatter> {
2021-08-14 11:09:37 -05:00
Ok(match s.to_lowercase().as_str() {
2021-06-21 17:38:51 -05:00
"text" => Formatter::Text,
2021-06-30 19:36:08 -05:00
"csv" => Formatter::Csv,
2021-07-26 20:32:13 -05:00
"json" => Formatter::Json,
2021-07-28 21:16:03 -05:00
"ids" => Formatter::Ids,
2021-07-29 11:02:00 -05:00
"ical" => Formatter::Ical,
2022-08-28 15:48:47 -05:00
"chart" => Formatter::Chart,
2021-06-21 17:38:51 -05:00
custom_format => Formatter::Custom(custom_format.into()),
})
}
2021-06-18 11:27:19 -05:00
}
2023-03-14 13:17:27 -06:00
#[cfg(test)]
mod tests {
use super::*;
#[test]
2023-03-15 13:22:55 -06:00
fn valid_autocomplete() {
let format = Formatter::autocomplete("t");
assert_eq!(format.unwrap(), Formatter::Text);
2023-03-14 13:17:27 -06:00
}
#[test]
2023-03-15 13:22:55 -06:00
fn invalid_autocomplete() {
let format = Formatter::autocomplete("fail");
assert!(matches!(format, Err(error::Error::InvalidAutocompleteFormatter(_))));
2023-03-14 13:17:27 -06:00
}
#[test]
2023-03-15 13:22:55 -06:00
fn invalid_autocomplete_empty() {
let format = Formatter::autocomplete("");
assert!(matches!(format, Err(error::Error::InvalidAutocompleteFormatter(_))));
2023-03-14 13:17:27 -06:00
}
// TODO: autocomplete for custom formatter
}