1
0
Fork 0
forked from wry/wry

autocommit 2022-04-17 17:08:31 CEST

This commit is contained in:
Julian Orth 2022-04-17 17:08:31 +02:00
parent 50b792db78
commit a30306e3d5
23 changed files with 390 additions and 42 deletions

138
src/cli/idle.rs Normal file
View file

@ -0,0 +1,138 @@
use std::cell::Cell;
use std::collections::VecDeque;
use std::rc::Rc;
use std::str::FromStr;
use crate::cli::{GlobalArgs, IdleArgs, IdleCmd, IdleSetArgs};
use crate::tools::tool_client::{Handle, ToolClient};
use crate::utils::errorfmt::ErrorFmt;
use crate::wire::{jay_compositor, jay_idle, JayIdleId};
pub fn main(global: GlobalArgs, args: IdleArgs) {
let tc = ToolClient::new(global.log_level.into());
let idle = Idle {
tc: tc.clone(),
};
tc.run(idle.run(args));
}
struct Idle {
tc: Rc<ToolClient>,
}
impl Idle {
async fn run(self, args: IdleArgs) {
let tc = &self.tc;
let comp = tc.jay_compositor().await;
let idle = tc.id();
tc.send(jay_compositor::GetIdle {
self_id: comp,
id: idle,
});
match args.command.unwrap_or_default() {
IdleCmd::Status => self.status(idle).await,
IdleCmd::Set(args) => self.set(idle, args).await,
}
}
async fn status(self, idle: JayIdleId) {
let tc = &self.tc;
tc.send(jay_idle::GetStatus {
self_id: idle,
});
let interval = Rc::new(Cell::new(0u64));
jay_idle::Interval::handle(tc, idle, interval.clone(), |iv, msg| {
iv.set(msg.interval);
});
tc.round_trip().await;
let minutes = interval.get() / 60;
let seconds = interval.get() % 60;
if minutes == 0 && seconds == 0 {
println!("Interval: disabled");
} else {
println!("Interval: {} minutes {} seconds", minutes, seconds);
}
}
async fn set(self, idle: JayIdleId, args: IdleSetArgs) {
let tc = &self.tc;
let interval;
if args.interval.len() == 1 && args.interval[0] == "disabled" {
interval = 0;
} else {
let comp = parse_components(&args.interval);
let mut minutes = None;
let mut seconds = None;
let mut pending_num = None;
for comp in comp {
match comp {
Component::Number(_) if pending_num.is_some() => fatal!("missing number unit after {}", pending_num.unwrap()),
Component::Number(n) => pending_num = Some(n),
Component::Minutes(n) if pending_num.is_none() => fatal!("`{}` must be preceded by a number", n),
Component::Minutes(_) if minutes.is_some() => fatal!("minutes specified multiple times"),
Component::Minutes(_) => minutes = pending_num.take(),
Component::Seconds(n) if pending_num.is_none() => fatal!("`{}` must be preceded by a number", n),
Component::Seconds(_) if seconds.is_some() => fatal!("seconds specified multiple times"),
Component::Seconds(_) => seconds = pending_num.take(),
}
}
if pending_num.is_some() {
fatal!("missing number unit after {}", pending_num.unwrap());
}
if minutes.is_none() && seconds.is_none() {
fatal!("minutes and/or numbers must be specified");
}
interval = minutes.unwrap_or(0) * 60 + seconds.unwrap_or(0);
}
tc.send(jay_idle::SetInterval {
self_id: idle,
interval,
});
tc.round_trip().await;
}
}
#[derive(Debug)]
enum Component {
Number(u64),
Minutes(String),
Seconds(String),
}
fn parse_components(args: &[String]) -> Vec<Component> {
let mut args = VecDeque::from_iter(args.iter().map(|s| s.to_ascii_lowercase()));
let mut res = vec![];
while let Some(arg) = args.pop_front() {
if arg.is_empty() {
continue;
}
let mut arg = &arg[..];
if is_num(arg.as_bytes()[0]) {
if let Some(pos) = arg.as_bytes().iter().position(|&a| !is_num(a)) {
args.push_front(arg[pos..].to_string());
arg = &arg[..pos];
}
match u64::from_str(arg) {
Ok(n) => res.push(Component::Number(n)),
Err(e) => fatal!("Could not parse `{}` as a number: {}", arg, ErrorFmt(e)),
}
} else {
if let Some(pos) = arg.as_bytes().iter().position(|&a| is_num(a)) {
args.push_front(arg[pos..].to_string());
arg = &arg[..pos];
}
let comp = match &arg[..] {
"minutes" | "minute" | "min" | "m" => Component::Minutes(arg.to_string()),
"seconds" | "second" | "sec" | "s" => Component::Seconds(arg.to_string()),
_ => fatal!("Could not parse `{}`", arg),
};
res.push(comp);
}
}
res
}
fn is_num(b: u8) -> bool {
matches!(b, b'0'..=b'9')
}