use clap::{App, AppSettings, Arg, ArgGroup, SubCommand};
use crate::core::JustDate;
const PKG_NAME: &'static str = env!("CARGO_PKG_NAME");
const PKG_DESCRIPTION: &'static str = env!("CARGO_PKG_DESCRIPTION");
const PKG_VERSION: &'static str = env!("CARGO_PKG_VERSION");
const PKG_AUTHORS: &'static str = env!("CARGO_PKG_AUTHORS");
pub fn app<'a>() -> App<'a, 'a> {
App::new(PKG_NAME)
.version(PKG_VERSION)
.author(PKG_AUTHORS)
.long_about(PKG_DESCRIPTION)
.settings(&[AppSettings::DeriveDisplayOrder])
.arg(
Arg::with_name("config")
.short("c")
.long("config")
.value_name("FILE")
.help("Sets a custom config file")
.takes_value(true)
)
.subcommand(completion_subcommand())
.subcommand(init_subcommand())
.subcommand(ideas_subcommand())
.subcommand(journals_subcommand())
.subcommand(notes_subcommand())
.subcommand(tasks_subcommand())
}
fn completion_subcommand<'a>() -> App<'a, 'a> {
SubCommand::with_name("completion")
.about("Generates completion scripts for various shells")
.settings(&[AppSettings::DeriveDisplayOrder])
.arg(
Arg::with_name("SHELL")
.index(1)
.required(true)
.possible_values(&["bash", "fish", "zsh", "powershell", "elvish"])
)
}
fn init_subcommand<'a>() -> App<'a, 'a> {
SubCommand::with_name("init")
.about("Initializes new journal repository")
.settings(&[AppSettings::DeriveDisplayOrder])
.arg(
Arg::with_name("PATH")
.index(1)
.required(true)
)
}
fn ideas_subcommand<'a>() -> App<'a, 'a> {
SubCommand::with_name("ideas")
.alias("idea")
.alias("i")
.about("Manages ideas")
.settings(&[AppSettings::DeriveDisplayOrder])
.subcommand(ideas_edit_subcommand())
.subcommand(ideas_remove_subcommand())
.subcommand(ideas_list_subcommand())
}
fn ideas_edit_subcommand<'a>() -> App<'a, 'a> {
SubCommand::with_name("edit")
.alias("e")
.about("Creates a new idea record or modifies existing one")
.arg(
Arg::with_name("NAME")
.index(1)
.required(true)
.help("Name of an idea")
)
}
fn ideas_remove_subcommand<'a>() -> App<'a, 'a> {
SubCommand::with_name("remove")
.alias("r")
.about("Removes existing idea record")
.arg(
Arg::with_name("NAME")
.index(1)
.required(true)
.help("Name of an idea")
)
}
fn ideas_list_subcommand<'a>() -> App<'a, 'a> {
SubCommand::with_name("list")
.alias("ls")
.about("Lists existing ideas")
}
fn journals_subcommand<'a>() -> App<'a, 'a> {
SubCommand::with_name("journals")
.alias("journal")
.alias("j")
.about("Manages journals")
.settings(&[AppSettings::DeriveDisplayOrder])
.subcommand(journals_edit_subcommand())
.subcommand(journals_remove_subcommand())
.subcommand(journals_list_subcommand())
}
fn journals_edit_subcommand<'a>() -> App<'a, 'a> {
SubCommand::with_name("edit")
.alias("e")
.about("Creates a new journal or modifies existing one")
.arg(
Arg::with_name("DATE")
.index(1)
.required(true)
.default_value("today")
.validator(is_valid_date)
.help("Date of a journal")
)
}
fn journals_remove_subcommand<'a>() -> App<'a, 'a> {
SubCommand::with_name("remove")
.alias("r")
.about("Removes existing journal")
.arg(
Arg::with_name("DATE")
.index(1)
.required(true)
.default_value("today")
.validator(is_valid_date)
.help("Date of a journal")
)
}
fn is_valid_date(input: String) -> Result<(), String> {
match JustDate::parse(&input) {
Some(_) => Ok(()),
None => Err(String::from("cannot parse date, should be e.g. 2019-10-03 or 3d"))
}
}
fn journals_list_subcommand<'a>() -> App<'a, 'a> {
SubCommand::with_name("list")
.alias("ls")
.about("Lists existing journals")
}
fn notes_subcommand<'a>() -> App<'a, 'a> {
SubCommand::with_name("notes")
.alias("note")
.alias("n")
.about("Manages notes")
.settings(&[AppSettings::DeriveDisplayOrder])
.subcommand(notes_edit_subcommand())
.subcommand(notes_remove_subcommand())
.subcommand(notes_list_subcommand())
}
fn notes_edit_subcommand<'a>() -> App<'a, 'a> {
SubCommand::with_name("edit")
.alias("e")
.about("Creates a new note or modifies existing one")
.arg(
Arg::with_name("CATEGORY")
.index(1)
.required(true)
.help("Category of a note")
)
.arg(
Arg::with_name("NAME")
.index(2)
.required(true)
.help("Name of a note")
)
}
fn notes_remove_subcommand<'a>() -> App<'a, 'a> {
SubCommand::with_name("remove")
.alias("r")
.about("Removes a note or all notes in a category")
.arg(
Arg::with_name("CATEGORY")
.index(1)
.required(true)
.help("Category of a note")
)
.arg(
Arg::with_name("NAME")
.index(2)
.help("Name of a note")
)
}
fn notes_list_subcommand<'a>() -> App<'a, 'a> {
SubCommand::with_name("list")
.alias("ls")
.about("Lists existing notes and categories")
.arg(
Arg::with_name("CATEGORIES")
.long("categories")
)
.arg(
Arg::with_name("CATEGORY")
.index(1)
.help("Category name")
)
.group(
ArgGroup::with_name("flags")
.args(&["CATEGORIES", "CATEGORY"]),
)
}
fn tasks_subcommand<'a>() -> App<'a, 'a> {
SubCommand::with_name("tasks")
.alias("task")
.alias("t")
.about("Manages tasks")
.settings(&[AppSettings::DeriveDisplayOrder])
.subcommand(tasks_edit_subcommand())
.subcommand(tasks_remove_subcommand())
.subcommand(tasks_list_subcommand())
}
fn tasks_edit_subcommand<'a>() -> App<'a, 'a> {
SubCommand::with_name("edit")
.alias("e")
.about("Edit tasks for a project")
.arg(
Arg::with_name("PROJECT")
.index(1)
.required(true)
.help("Project name")
)
}
fn tasks_remove_subcommand<'a>() -> App<'a, 'a> {
SubCommand::with_name("remove")
.alias("r")
.about("Removes tasks for a category")
.arg(
Arg::with_name("PROJECT")
.index(1)
.required(true)
.help("Project name")
)
}
fn tasks_list_subcommand<'a>() -> App<'a, 'a> {
SubCommand::with_name("list")
.alias("ls")
.about("Lists tasks for projects")
.arg(
Arg::with_name("PROJECTS")
.long("projects")
)
.arg(
Arg::with_name("PROJECT")
.index(1)
.help("Project name")
)
.group(
ArgGroup::with_name("flags")
.args(&["PROJECTS", "PROJECT"]),
)
}