use crate::daemon::{Answer, AnswerErr, Command as OtherCommand}; 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 advanced timer daemon/cli. pub struct Cli { #[command(subcommand)] pub command: Command, #[arg(short, long)] #[clap(default_value = "/tmp/timers.socket")] 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, }, /// 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, /// 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) } #[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, } fn get_stream(socket_path: &String) -> Result { UnixStream::connect(socket_path) .context(format!("Could not connect to socket {}!", socket_path)) } pub fn send_command(socket_path: &String, command: OtherCommand) -> Result<()> { let stream = get_stream(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!")?; match answer { Ok(answer) => println!("{}", answer), Err(err) => println!("Error: {}", err), } Ok(()) }