use crate::daemon::{Answer, AnswerErr, Command as OtherCommand}; use crate::helper::run_path; use anyhow::{Context, Result}; use clap::{Parser, Subcommand}; use std::net::Shutdown; use std::os::unix::net::UnixStream; use std::time::Duration; #[derive(Parser)] #[command(name = "timers")] /// A simple timer daemon/cli. pub struct Cli { #[command(subcommand)] pub command: Command, #[arg(short, long)] #[clap(default_value_t = format!("{}/timers.socket", run_path()))] pub socket: String, } #[derive(Debug, Subcommand)] pub enum Command { /// Run as daemon #[clap(visible_alias = "d")] Daemon { /// do not send notifications #[arg(short, long)] no_notify: bool, #[arg(short, long)] #[clap(default_value_t = format!("{}/timers.pid", run_path()))] pid_file: String, }, /// Add a timer #[clap(visible_alias = "a")] Add { /// name of the timer name: String, /// duration of the timer duration: humantime::Duration, }, /// List timers #[clap(visible_alias = "l")] List, /// Toggle timer #[clap(visible_alias = "t")] Toggle { /// name of the timer to toggle name: String, }, /// Remove a timer #[clap(visible_alias = "r")] Remove { /// name of the timer to remove name: String, }, /// Pomodoro specific command #[command(subcommand)] #[clap(visible_alias = "p")] Pomodoro(PomodoroCommand), /// Shell completions Completions { #[arg(value_enum)] shell: clap_complete_command::Shell, } } #[derive(Debug, Subcommand)] pub enum PomodoroCommand { /// Start pomodoro #[clap(visible_alias = "s")] Start { /// duration to work for #[arg(long)] #[clap(default_value_t = Duration::from_secs(25 * 60).into())] work: humantime::Duration, /// duration for short pauses #[arg(long)] #[clap(default_value_t = Duration::from_secs(5 * 60).into())] pause: humantime::Duration, /// duration for long pauses #[arg(long)] #[clap(default_value_t = Duration::from_secs(10 * 60).into())] long_pause: humantime::Duration, /// number of short pauses till long pause #[arg(long)] #[clap(default_value_t = 3)] pauses_till_long: u64, }, /// Stop the pomodoro #[clap(visible_alias = "p")] Remove, /// List the pomodoro settings and remaining duration #[clap(visible_alias = "l")] List, /// Toggle pomodoro #[clap(visible_alias = "t")] Toggle, } pub fn send_command(socket_path: &String, command: OtherCommand) -> Result { let stream = UnixStream::connect(socket_path) .context(format!("Could not connect to socket {}!", socket_path))?; serde_cbor::to_writer(&stream, &command).context("Could not write command!")?; stream .shutdown(Shutdown::Write) .context("Could not shutdown write!")?; let answer: Result = serde_cbor::from_reader(&stream).context("Could not read answer!")?; Ok(answer?) }