1use std::fmt;
2use std::process::Command;
3
4use colorsys::Rgb;
5
6use crate::common::{parse_colour_param, pct_value_hsl};
7
8#[derive(Debug, PartialEq)]
9pub enum PingAppletError {
10 PingMissingHost,
11 PingError,
12}
13
14impl std::error::Error for PingAppletError {}
15
16impl fmt::Display for PingAppletError {
17 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
18 write!(f, "PingAppletError: {:?}", self)
19 }
20}
21
22type Result<T> = std::result::Result<T, PingAppletError>;
23
24fn ping_host(host: &str) -> Result<()> {
25 match Command::new("ping").arg("-q").arg("-c").arg("1").arg("-w").arg("1").arg(host).output() {
26 Ok(output) if output.status.success() => Ok(()),
27 _ => Err(PingAppletError::PingError),
28 }
29}
30
31pub fn applet(args: &[String]) -> Result<()> {
32 let mut host: &str = "";
33 let mut colour_s: Option<f32> = None;
34 let mut colour_l: Option<f32> = None;
35
36 for arg in args {
37 if let Some(s) = parse_colour_param(arg, "s") {
38 if (0.0..=100.0).contains(&s) {
39 colour_s = Some(s);
40 } else {
41 eprintln!("Saturation {s} out of range [0, 100.0]");
42 }
43 continue;
44 };
45 if let Some(l) = parse_colour_param(arg, "l") {
46 if (0.0..=100.0).contains(&l) {
47 colour_l = Some(l);
48 } else {
49 eprintln!("Lightness {l} out of range [0, 100.0]");
50 }
51 continue;
52 }
53
54 if !host.is_empty() {
55 eprintln!("Ignoring extra argument: {arg}");
56 continue;
57 }
58
59 host = arg;
60 }
61
62 if host.is_empty() {
63 return Err(PingAppletError::PingMissingHost);
64 }
65
66 eprintln!("Saturation: {:?} Lightness: {:?}", colour_s, colour_l);
67 eprintln!("Pinging host: {host}");
68
69 let value = match ping_host(host) {
70 Ok(_) => 0.0,
72 Err(_) => 1.0,
73 };
74
75 let c = pct_value_hsl(value, colour_s, colour_l);
76 let rgb = Rgb::from(&c);
77
78 print!("#[bg={}] #[default]", rgb.to_hex_string());
79
80 Ok(())
81}