birthday 0.2.0

🎂 CLI tool to remember birthdays of people you know
Documentation
mod output;
use anyhow::Result;
use chrono::{Datelike, Utc};
use clap::{Parser, Subcommand};

#[derive(Parser, Debug)]
#[command(version)]
#[command(about = "🎂 CLI tool to remember birthdays of people you know")]
struct Cli {
    #[command(subcommand)]
    command: Command,
}

#[derive(Subcommand, Debug)]
enum Command {
    #[command(about = "Add a person's birthday")]
    Add {
        name: String,
        day: u32,
        month: u32,
        #[arg(allow_negative_numbers = true)]
        year: i32,
    },
    #[command(about = "Show all birthdays")]
    All {},
    #[command(about = "Show the next birthday")]
    Next {},

    #[command(about = "Search for birthdays")]
    #[command(arg_required_else_help(true))]
    Search {
        #[arg(short, long, help = "match for names containing <NAME>")]
        name: Option<String>,
        #[arg(short, long, help = "match for a specific <YEAR>")]
        year: Option<i32>,
        #[arg(short, long, help = "match for a specific <MONTH>")]
        month: Option<u32>,
        #[arg(short, long, help = "match for a specific <DAY>")]
        day: Option<u32>,
    },
    #[command(about = "Show today's birthdays")]
    Today {},
    #[command(about = "Forget a birthday by ID")]
    Forget { id: i32 },
}

fn main() -> Result<()> {
    let cli = Cli::parse();
    let today = Utc::now().date_naive();
    match cli.command {
        Command::Add {
            name,
            day,
            month,
            year,
        } => birthday::add(name, day, month, year),
        Command::All {} => {
            let birthdays = birthday::get_all()?;
            output::output(birthdays, today);
            Ok(())
        }
        Command::Next {} => {
            let maybe_birthday = birthday::get_next(today)?;
            if let Some(birthday) = maybe_birthday {
                output::output(vec![birthday], today);
            }
            Ok(())
        }
        Command::Search {
            name,
            year,
            month,
            day,
        } => {
            let birthdays = birthday::search(name, year, month, day)?;
            output::output(birthdays, today);
            Ok(())
        }
        Command::Today {} => {
            let today = Utc::now().date_naive();
            let birthdays = birthday::search(
                None,
                Some(today.year()),
                Some(today.month()),
                Some(today.day()),
            )?;
            output::output(birthdays, today);
            Ok(())
        }
        Command::Forget { id } => {
            let maybe_birthday = birthday::forget(id)?;
            match maybe_birthday {
                Some(birthday) => output::birthday_forgotten(birthday),
                None => output::no_birthday_found(),
            }
            Ok(())
        }
    }
}