devjournal 0.1.0

A dev first cli journaling tool
Documentation
pub mod cli;
mod config;
pub mod domain;
pub mod mappers;
pub mod output;
pub mod persistence;
pub mod repositories;
pub mod services;
pub mod store;
pub mod utils;

use crate::repositories::repository::Repository;

use crate::cli::cli::Args;
use crate::domain::entry::Entry;
use crate::domain::journal::Journal;
use crate::output::renderer::render_page;
use crate::utils::date;
use anyhow::{Result, anyhow};

use chrono::Duration;

#[derive(Copy, Clone)]
pub enum ExitStatus {
    Success,
    Failure,
    Error,
}

impl From<ExitStatus> for std::process::ExitCode {
    fn from(status: ExitStatus) -> Self {
        match status {
            ExitStatus::Success => std::process::ExitCode::from(0),
            ExitStatus::Failure => std::process::ExitCode::from(1),
            ExitStatus::Error => std::process::ExitCode::from(2),
        }
    }
}

pub fn run(args: Args) -> Result<ExitStatus> {
    let journal_repository = repositories::JournalRepository::new(config::journal_path()?);
    let journal_service = services::JournalService::new(&journal_repository);
    let today = date::now();

    let mut journal: Journal;

    // Handle creation or specification of journal
    match (args.create, args.journal_name) {
        (Some(new_journal_name), None) => {
            journal = journal_service.create_journal(new_journal_name)?;
        }
        (None, Some(existing_journal_name)) => {
            journal = journal_service
                .get_journal_by_name(existing_journal_name.to_string())?
                .ok_or_else(|| anyhow!("No journal with the given name"))?;
        }
        (Some(_), Some(_)) => {
            panic!("cannot create a journal and specify a journal at the same time")
        }
        (None, None) => {
            journal = journal_service
                .get_journal_by_name(config::default_journal())?
                .ok_or_else(|| anyhow!("No journal with the given name"))?;
        }
    }

    // Handle entrys
    match (&args.entry, &args.from, &args.to) {
        (Some(entry), None, None) => {
            let input = entry.join(" ");
            let entry = Entry::new(&input, today);

            journal.add_entry(entry);
        }
        (Some(entry), Some(from), None) => {
            let from_date = date::parse_date_arg(from.as_str()).unwrap();

            let input = entry.join(" ");
            let entry = Entry::new(&input, from_date);

            journal.add_entry(entry);
        }
        (None, Some(from), None) => {
            let from_date = date::parse_date_arg(from.as_str()).unwrap();
            let pages = journal.get_page_in_date_range(from_date, None);

            for page in pages {
                render_page(page)?;
            }
        }
        (None, Some(from), Some(to)) => {
            let from_date = date::parse_date_arg(from.as_str()).unwrap();
            let to_date = date::parse_date_arg(to.as_str()).unwrap() + Duration::days(1);

            let pages = journal.get_page_in_date_range(from_date, Some(to_date));
            for page in pages {
                render_page(page)?;
            }
        }
        _ => {}
    }

    journal_repository.update(&journal)?;
    Ok(ExitStatus::Success)
}