leafslug_jnl 0.4.0

A personal journaling system that is not inteded to be used by others... yet.
Documentation
use crate::entry::Entry;
use crate::Error;
use comfy_table::{Cell, ContentArrangement};
use leafslug_effects::files::is_json;
use std::path::PathBuf;
use time::formatting::Formattable;

#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct EntryDescription {
    pub entry: Entry,
    pub file_name: String,
}

impl TryFrom<PathBuf> for EntryDescription {
    type Error = Error;

    fn try_from(value: PathBuf) -> Result<Self, Self::Error> {
        let file_name = value
            .file_name()
            .ok_or(Error::IsNotAFile)?
            .to_str()
            .ok_or(Error::FileNameHasInvalidCharacters)?
            .to_owned();
        Ok(Self {
            entry: Entry::try_from(value).map_err(|e| {
                Error::CouldNotDeserializeEntryFromJson(Box::new(e), file_name.clone())
            })?,
            file_name,
        })
    }
}
pub fn truncate_form(entry_description: &EntryDescription, truncate_at: usize) -> String {
    let mut truncated_body = entry_description.entry.body.to_string();
    truncated_body.truncate(truncate_at);
    format!("{} -> {} ... ", entry_description.file_name, truncated_body)
}

pub fn table_list(
    mut entry_list: impl Iterator<Item = EntryDescription>,
    time_format_descriptor: &(impl Formattable + ?Sized),
) -> Result<String, Error> {
    let mut table = comfy_table::Table::new();
    table.load_preset(comfy_table::presets::NOTHING);

    table.set_content_arrangement(ContentArrangement::Dynamic);
    entry_list.try_fold((), |(), entry_desc| -> Result<(), Error> {
        let bg_color = match entry_desc.entry.mood {
            super::Mood::Good => comfy_table::Color::Green,
            super::Mood::Bad => comfy_table::Color::Red,
            super::Mood::Neutral => comfy_table::Color::White,
        };
        table.add_row(vec![
            Cell::new((entry_desc.entry.at.format(time_format_descriptor)?).clone())
                .bg(bg_color)
                .fg(comfy_table::Color::Black),
            Cell::new(format!("{}", &entry_desc.entry.body)).fg(bg_color),
        ]);
        Ok(())
    })?;

    Ok(table.to_string())
}

pub fn book(value: &PathBuf) -> Result<impl Iterator<Item = EntryDescription>, Error> {
    Ok(fs_extra::dir::get_dir_content(value)
        .map_err(Error::DirCouldNotBeRead)?
        .files
        .into_iter()
        .map(PathBuf::from)
        .filter(is_json)
        .flat_map(EntryDescription::try_from))
}