notebook_rs 0.5.3

CLI utility for plaintext notetaking.
Documentation
use crate::{text_from_editor, Args, Entry};
use clap::{Arg, ArgMatches, Command};

pub fn get_args() -> ArgMatches {
    Command::new("Notebook")
        .about("CLI utility for plaintext notetaking.")
        .subcommand_required(true)
        .arg_required_else_help(true)
        .subcommand(
            Command::new("new")
                .short_flag('n')
                .long_flag("new")
                .about("Create a new note")
                .arg(Arg::new("entry")),
        )
        .arg(
            Arg::new("notebook_name")
                .short('j')
                .long("notebook")
                .default_value("default")
                .help("Specify a notebook name"),
        )
        .subcommand(
            Command::new("list")
                .short_flag('l')
                .long_flag("list")
                .about("List entries")
                .arg(Arg::new("list").default_value("5")),
        )
        .arg(
            Arg::new("verbose")
                .short('v')
                .long("verbose")
                .help("Quantity of information")
                .action(clap::ArgAction::Count),
        )
        .subcommand(
            Command::new("edit")
                .short_flag('e')
                .long_flag("edit")
                .about("Edit specific entry")
                .arg(Arg::new("edit")),
        )
        .subcommand(
            Command::new("read")
                .short_flag('r')
                .long_flag("read")
                .about("Display specific entry")
                .arg(Arg::new("read")),
        )
        .subcommand(
            Command::new("delete")
                .short_flag('X')
                .long_flag("delete")
                .about("Delete specific entry")
                .arg(Arg::new("delete")),
        )
        .subcommand(
            Command::new("date search")
                .short_flag('d')
                .long_flag("date-search")
                .about("Search for entries around a date")
                .arg(Arg::new("datesearch")),
        )
        .subcommand(
            Command::new("search")
                .short_flag('s')
                .long_flag("search")
                .about("Query to search, enclosed in quotations")
                .arg(Arg::new("search"))
                .subcommand(
                    Command::new("date")
                        .short_flag('d')
                        .long_flag("date")
                        .about("Filter results by date range")
                        .arg(Arg::new("entry")),
                ),
        )
        .arg(
            Arg::new("config")
                .short('c')
                .long("config")
                .help("Path of config file to read"),
        )
        .get_matches()
}

pub fn parse_args(matches: ArgMatches, dt_format: &str) -> Args {
    let verbose = matches.get_count("verbose");

    match matches.subcommand() {
        Some(("new", input)) => {
            let text: String = match input.get_many::<String>("entry") {
                Some(t) => t.fold(String::new(), |mut a, b| {
                    a.reserve(b.len() + 1);
                    a.push_str(b);
                    a.push(' ');
                    a
                }),

                None => text_from_editor(None).unwrap(),
            };
            let e = Entry::new(text, dt_format);
            Args::New(e)
        }

        Some(("list", input)) => {
            let n: usize = input.get_one::<String>("list").unwrap().parse().unwrap();
            Args::List(n, verbose)
        }

        Some(("read", input)) => {
            let n: usize = input.get_one::<String>("read").unwrap().parse().unwrap();
            Args::Read(n)
        }

        Some(("edit", input)) => {
            let n: usize = input.get_one::<String>("edit").unwrap().parse().unwrap();
            Args::Edit(n)
        }

        Some(("delete", input)) => {
            let n: usize = input.get_one::<String>("delete").unwrap().parse().unwrap();
            Args::Delete(n, true)
        }

        Some(("search", input)) => {
            let mut q = String::new();
            let search_command = input.subcommand().unwrap_or(("search", input));
            match search_command {
                ("date", _sub_matches) => Args::DateFilter(q),
                ("search", _sub_matches) => {
                    q = input.get_one::<String>("search").unwrap().into();
                    Args::Search(q)
                }
                (name, _) => {
                    unreachable!("Unsupported subcommand `{name}`")
                }
            }
        }

        Some(("date search", input)) => {
            let date = input.get_one::<String>("search").unwrap().into();
            Args::DateSearch(date)
        }

        _ => unreachable!(),
    }
}