use clap::{Args, Parser, Subcommand};
#[derive(Parser)]
#[command(version, about, long_about = None)]
#[command(propagate_version = true)]
pub struct Cli {
pub search: Option<String>,
#[arg(short, long)]
pub task: bool,
#[arg(short, long)]
pub project: bool,
#[arg(short, long)]
pub verbose: bool,
#[command(subcommand)]
pub command: Option<Commands>,
#[arg(short, long, value_name = "PATH")]
pub file: Option<String>,
#[arg(short, long, value_name = "PATH")]
pub config: Option<String>,
}
#[derive(Subcommand)]
pub enum Commands {
Search(SearchArgs),
Add(AddArgs),
Delete(DeleteArgs),
Update(UpdateArgs),
Ls(ListArgs),
Check(CheckArgs),
Assign(AssignArgs),
}
#[derive(Args)]
pub struct SearchArgs {
pub term: String,
#[arg(short, long)]
pub task: bool,
#[arg(short, long)]
pub project: bool,
#[arg(short, long)]
pub verbose: bool,
}
#[derive(Args)]
pub struct AddArgs {
#[arg(short, long)]
pub task: bool,
#[arg(short, long)]
pub project: bool,
pub name: Option<String>,
#[arg(short, long)]
pub item_priority: Option<u64>,
#[arg(short, long)]
pub start_time: Option<String>,
#[arg(short, long)]
pub end_time: Option<String>,
#[arg(short, long)]
pub notes: Option<String>,
#[arg(short, long)]
pub repeat: Option<String>,
#[arg(short, long)]
pub optional: bool,
}
#[derive(Args)]
pub struct DeleteArgs {
pub term: Option<String>,
#[arg(short, long)]
pub task: bool,
#[arg(short, long)]
pub project: bool,
}
#[derive(Args)]
pub struct UpdateArgs {
pub term: Option<String>,
#[arg(short, long)]
pub task: bool,
#[arg(short, long)]
pub project: bool,
#[arg(short, long)]
pub name: Option<String>,
#[arg(short, long, value_name = "PRIORITY")]
pub item_priority: Option<u64>,
#[arg(short, long, value_name = "TIME|NULL")]
pub start_time: Option<NullableString>,
#[arg(short, long, value_name = "TIME|NULL")]
pub end_time: Option<NullableString>,
#[arg(long, value_name = "NOTES|NULL")]
pub notes: Option<NullableString>,
#[arg(short, long, value_name = "REPEAT|NULL")]
pub repeat: Option<NullableString>,
}
impl UpdateArgs {
pub fn has_task_update_values(&self) -> bool {
self.name.is_some()
|| self.item_priority.is_some()
|| self.start_time.is_some()
|| self.end_time.is_some()
|| self.notes.is_some()
|| self.repeat.is_some()
}
#[allow(dead_code)]
pub fn has_project_update_values(&self) -> bool {
self.name.is_some()
|| self.item_priority.is_some()
|| self.start_time.is_some()
|| self.end_time.is_some()
|| self.notes.is_some()
}
}
#[derive(Args)]
pub struct ListArgs {
pub order_by: Option<toado::OrderBy>,
#[arg(short, long)]
pub task: bool,
#[arg(short, long)]
pub project: bool,
#[arg(short, long)]
pub verbose: bool,
#[arg(short, long)]
pub asc: bool,
#[arg(short, long)]
pub desc: bool,
#[arg(short, long)]
pub limit: Option<usize>,
#[arg(short, long)]
pub offset: Option<usize>,
#[arg(short, long)]
pub full: bool,
}
#[derive(Args)]
pub struct CheckArgs {
pub term: Option<String>,
#[arg(short, long)]
pub incomplete: bool,
}
#[derive(Args)]
pub struct AssignArgs {
#[arg(conflicts_with = "task_term", group = "task_search")]
pub task: Option<String>,
#[arg(conflicts_with = "project_term", group = "project_search")]
pub project: Option<String>,
#[arg(
short,
long,
conflicts_with = "task",
value_name = "NAME|ID",
group = "task_search"
)]
pub task_term: Option<String>,
#[arg(
short,
long,
conflicts_with = "project",
value_name = "NAME|ID",
group = "project_search"
)]
pub project_term: Option<String>,
#[arg(short, long)]
pub unassign: bool,
#[arg(short, long, requires = "task_search", requires = "project_search")]
pub no_select: bool,
}
pub enum NullableString {
Some(String),
Null,
}
impl Clone for NullableString {
fn clone(&self) -> Self {
match self {
Self::Some(value) => Self::Some(value.to_string()),
Self::Null => Self::Null,
}
}
}
impl std::str::FromStr for NullableString {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let s = s.to_lowercase();
if s == "null" {
Ok(Self::Null)
} else {
Ok(Self::Some(s.to_string()))
}
}
}