use std::path::PathBuf;
use clap::{Parser, Subcommand};
#[derive(Parser)]
#[command(
name = "oxiline",
version,
about = "OxiLine — manage the flow of your day, not a calendar of appointments"
)]
pub struct Cli {
#[arg(long, global = true)]
pub json: bool,
#[arg(long, global = true, value_name = "PATH")]
pub db: Option<PathBuf>,
#[arg(long, global = true, value_name = "LANG")]
pub lang: Option<String>,
#[arg(long, global = true)]
pub dry_run: bool,
#[arg(short = 'q', long, global = true)]
pub quiet: bool,
#[command(subcommand)]
pub cmd: Command,
}
#[derive(Subcommand)]
pub enum Command {
Now,
Category {
#[command(subcommand)]
action: CategoryAction,
},
Activity {
#[command(subcommand)]
action: ActivityAction,
},
Settings {
#[command(subcommand)]
action: SettingsAction,
},
Hud {
#[command(subcommand)]
action: HudAction,
},
Report {
#[arg(long)]
week: bool,
#[arg(long, value_name = "N")]
last: Option<u32>,
#[arg(long, value_name = "FROM:TO")]
range: Option<String>,
},
Record {
#[command(subcommand)]
action: Option<RecordAction>,
},
Plan {
#[command(subcommand)]
action: PlanAction,
},
Doctor,
}
#[derive(Subcommand)]
pub enum HudAction {
Show,
}
#[derive(Subcommand)]
pub enum CategoryAction {
Add {
name: String,
#[arg(long, value_name = "0-360", default_value_t = 250.0)]
hue: f64,
#[arg(long, value_name = "NAME")]
icon: Option<String>,
},
List,
Rm { id: String },
}
#[derive(Subcommand)]
pub enum SettingsAction {
Get { key: Option<String> },
Set { key: String, value: String },
}
#[derive(Clone, Copy, Debug)]
pub struct MinuteBudget(pub Option<u32>);
impl std::str::FromStr for MinuteBudget {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let n: u32 = s
.parse()
.map_err(|e| format!("invalid minute budget '{s}': {e}"))?;
Ok(MinuteBudget(if n == 0 { None } else { Some(n) }))
}
}
#[derive(Subcommand)]
pub enum ActivityAction {
Add {
name: String,
#[arg(long, value_name = "MIN")]
daily: Option<MinuteBudget>,
#[arg(long, value_name = "MIN")]
weekly: Option<MinuteBudget>,
#[arg(long, value_name = "LABEL")]
hue: Option<String>,
#[arg(long, value_name = "NAME")]
icon: Option<String>,
#[arg(long, value_name = "ID|NAME")]
category: Option<String>,
},
List {
#[arg(long)]
active_only: bool,
},
Show { id: String },
Edit {
id: String,
#[arg(long, value_name = "TEXT")]
name: Option<String>,
#[arg(long, value_name = "MIN")]
daily: Option<MinuteBudget>,
#[arg(long, value_name = "MIN")]
weekly: Option<MinuteBudget>,
#[arg(long, value_name = "LABEL")]
hue: Option<String>,
#[arg(long, value_name = "NAME")]
icon: Option<String>,
},
Toggle {
id: String,
#[arg(long, conflicts_with = "off")]
on: bool,
#[arg(long, conflicts_with = "on")]
off: bool,
},
Rm {
id: String,
#[arg(long)]
force: bool,
},
}
#[derive(Subcommand)]
pub enum RecordAction {
State,
Start {
activity: String,
#[arg(long, value_name = "ISO")]
at: Option<String>,
},
Stop,
Log {
#[arg(long, value_name = "ID|NAME")]
activity: Option<String>,
#[arg(long, value_name = "YYYY-MM-DD")]
date: Option<String>,
#[arg(long, value_name = "FROM:TO")]
range: Option<String>,
},
}
#[derive(Subcommand)]
pub enum PlanAction {
Add {
#[arg(long, value_name = "HH:MM")]
at: Option<String>,
#[arg(long, value_name = "MIN", default_value_t = 60)]
duration: u32,
#[arg(long, value_name = "DAYS")]
days: Option<String>,
#[arg(long, value_name = "DATE", conflicts_with = "days")]
date: Option<String>,
#[arg(long, value_name = "TEXT")]
title: Option<String>,
#[arg(long, value_name = "A,B,C")]
options: String,
},
List {
#[arg(long, value_name = "DATE")]
date: Option<String>,
#[arg(long)]
recurring: bool,
},
Edit {
id: String,
#[arg(long, value_name = "HH:MM")]
at: Option<String>,
#[arg(long, value_name = "MIN")]
duration: Option<u32>,
#[arg(long, value_name = "DAYS")]
days: Option<String>,
#[arg(long, value_name = "DATE")]
date: Option<String>,
#[arg(long, value_name = "TEXT")]
title: Option<String>,
#[arg(long, value_name = "A,B,C")]
options: Option<String>,
},
Rm { id: String },
}