Add tests and an example
This commit is contained in:
parent
625e2355b9
commit
640e6dd6bf
@ -8,4 +8,4 @@ edition = "2018"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
battery = "0.7.6"
|
battery = "0.7.6"
|
||||||
simple-osd-common = { version = "0.1", path = "../common" }
|
simple-osd-common = { version = "0.1", path = "../common" }
|
||||||
|
@ -11,7 +11,7 @@ use std::time::Duration;
|
|||||||
use osd::notify::{OSD, Urgency};
|
use osd::notify::{OSD, Urgency};
|
||||||
use osd::config::Config;
|
use osd::config::Config;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Eq, PartialEq)]
|
||||||
enum Threshold {
|
enum Threshold {
|
||||||
Percentage(i32),
|
Percentage(i32),
|
||||||
Minutes(i32)
|
Minutes(i32)
|
||||||
@ -25,18 +25,133 @@ enum State {
|
|||||||
Normal
|
Normal
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn threshold_sane(thresh: Threshold) -> Option<Threshold> {
|
||||||
|
match thresh {
|
||||||
|
Threshold::Percentage(p) => {
|
||||||
|
if p < 0 || p > 100 { return None; }
|
||||||
|
Some(thresh)
|
||||||
|
},
|
||||||
|
Threshold::Minutes(m) => {
|
||||||
|
if m < 0 { return None; }
|
||||||
|
Some(thresh)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_threshold(thresh: String) -> Option<Threshold> {
|
fn parse_threshold(thresh: String) -> Option<Threshold> {
|
||||||
let mut s = thresh.clone();
|
let mut s = thresh.clone();
|
||||||
|
|
||||||
let last = s.pop();
|
let last = s.pop();
|
||||||
|
|
||||||
|
let parsed = s.parse();
|
||||||
|
|
||||||
match last {
|
match last {
|
||||||
Some('%') => s.parse().map(Threshold::Percentage).ok(),
|
Some('%') => parsed.map(Threshold::Percentage).ok().and_then(threshold_sane),
|
||||||
Some('m') => s.parse().map(Threshold::Minutes).ok(),
|
Some('m') => parsed.map(Threshold::Minutes).ok().and_then(threshold_sane),
|
||||||
_ => None
|
_ => None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod parse_threshold_tests {
|
||||||
|
use super::parse_threshold;
|
||||||
|
use super::Threshold;
|
||||||
|
#[test]
|
||||||
|
fn parses_percentage() {
|
||||||
|
assert_eq!(parse_threshold("15%".to_string()), Some(Threshold::Percentage(15)));
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn parses_minutes() {
|
||||||
|
assert_eq!(parse_threshold("10m".to_string()), Some(Threshold::Minutes(10)));
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn fails_on_incorrect_percentage() {
|
||||||
|
assert_eq!(parse_threshold("foo%".to_string()), None);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn fails_on_incorrect_minutes() {
|
||||||
|
assert_eq!(parse_threshold("foom".to_string()), None);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn fails_on_high_percentage() {
|
||||||
|
assert_eq!(parse_threshold("110%".to_string()), None);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn fails_on_negative_percentage() {
|
||||||
|
assert_eq!(parse_threshold("-10%".to_string()), None);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn fails_on_negative_minutes() {
|
||||||
|
assert_eq!(parse_threshold("-10m".to_string()), None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn format_duration(duration: f32) -> String {
|
||||||
|
let mut d = duration as i32;
|
||||||
|
if d == 0 {
|
||||||
|
return "0s".to_string();
|
||||||
|
}
|
||||||
|
let mut s = String::new();
|
||||||
|
if d < 0 {
|
||||||
|
s.push_str("-");
|
||||||
|
d = -d;
|
||||||
|
}
|
||||||
|
let hours = d / 3600;
|
||||||
|
let minutes = (d % 3600) / 60;
|
||||||
|
let seconds = d % 60;
|
||||||
|
|
||||||
|
|
||||||
|
if hours > 0 {
|
||||||
|
s.push_str(&format!("{}h", hours));
|
||||||
|
}
|
||||||
|
if minutes > 0 {
|
||||||
|
if hours > 0 { s.push_str(" "); }
|
||||||
|
s.push_str(&format!("{}m", minutes));
|
||||||
|
}
|
||||||
|
if seconds > 0 {
|
||||||
|
if hours > 0 || minutes > 0 { s.push_str(" "); }
|
||||||
|
s.push_str(&format!("{}s", seconds));
|
||||||
|
}
|
||||||
|
s
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod format_duration_tests {
|
||||||
|
use super::format_duration;
|
||||||
|
#[test]
|
||||||
|
fn no_time() {
|
||||||
|
assert_eq!(&format_duration(0.), "0s");
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn seconds() {
|
||||||
|
assert_eq!(&format_duration(12.), "12s");
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn minutes_seconds() {
|
||||||
|
assert_eq!(&format_duration(123.), "2m 3s");
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn minutes() {
|
||||||
|
assert_eq!(&format_duration(120.), "2m");
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn hours_minutes_seconds() {
|
||||||
|
assert_eq!(&format_duration(12345.), "3h 25m 45s");
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn hours_minutes() {
|
||||||
|
assert_eq!(&format_duration(9000.), "2h 30m")
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn hours() {
|
||||||
|
assert_eq!(&format_duration(3600.), "1h")
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn negative() {
|
||||||
|
assert_eq!(&format_duration(-12345.), "-3h 25m 45s");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn main() -> battery::Result<()> {
|
fn main() -> battery::Result<()> {
|
||||||
let mut config = Config::new("battery");
|
let mut config = Config::new("battery");
|
||||||
|
|
||||||
@ -48,8 +163,6 @@ fn main() -> battery::Result<()> {
|
|||||||
|
|
||||||
let refresh_interval = config.get_default("default", "refresh interval", 30);
|
let refresh_interval = config.get_default("default", "refresh interval", 30);
|
||||||
|
|
||||||
println!("{:?}, {:?}", low_threshold, critical_threshold);
|
|
||||||
|
|
||||||
let mut osd = OSD::new();
|
let mut osd = OSD::new();
|
||||||
osd.icon = Some(String::from("battery"));
|
osd.icon = Some(String::from("battery"));
|
||||||
|
|
||||||
@ -69,6 +182,7 @@ fn main() -> battery::Result<()> {
|
|||||||
let mut state: State;
|
let mut state: State;
|
||||||
let mut last_state: State = State::Normal;
|
let mut last_state: State = State::Normal;
|
||||||
|
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
state = match battery.state() {
|
state = match battery.state() {
|
||||||
battery::State::Charging => State::Charging,
|
battery::State::Charging => State::Charging,
|
||||||
@ -92,14 +206,14 @@ fn main() -> battery::Result<()> {
|
|||||||
match state {
|
match state {
|
||||||
State::Charging => {
|
State::Charging => {
|
||||||
battery.time_to_full().map(|ttf| {
|
battery.time_to_full().map(|ttf| {
|
||||||
osd.title = Some(format!("Charging, {:?} until full", ttf));
|
osd.title = Some(format!("Charging, {} until full", format_duration(ttf.value)));
|
||||||
osd.urgency = Urgency::Low;
|
osd.urgency = Urgency::Low;
|
||||||
osd.update();
|
osd.update();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
State::Low => {
|
State::Low => {
|
||||||
battery.time_to_empty().map(|tte| {
|
battery.time_to_empty().map(|tte| {
|
||||||
osd.title = Some(format!("Low battery, {:?} remaining", tte));
|
osd.title = Some(format!("Low battery, {} remaining", format_duration(tte.value)));
|
||||||
osd.urgency = Urgency::Normal;
|
osd.urgency = Urgency::Normal;
|
||||||
osd.update();
|
osd.update();
|
||||||
});
|
});
|
||||||
@ -110,7 +224,7 @@ fn main() -> battery::Result<()> {
|
|||||||
|
|
||||||
if state == State::Critical {
|
if state == State::Critical {
|
||||||
battery.time_to_empty().map(|tte| {
|
battery.time_to_empty().map(|tte| {
|
||||||
osd.title = Some(format!("Critically low battery, {:?} remaining", tte));
|
osd.title = Some(format!("Critically low battery, {} remaining", format_duration(tte.value)));
|
||||||
osd.urgency = Urgency::Critical;
|
osd.urgency = Urgency::Critical;
|
||||||
osd.update();
|
osd.update();
|
||||||
});
|
});
|
||||||
|
54
common/examples/simple.rs
Normal file
54
common/examples/simple.rs
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
extern crate simple_osd_common as osd;
|
||||||
|
|
||||||
|
use osd::notify::{OSD, OSDContents, OSDProgressText, Urgency};
|
||||||
|
use osd::config::Config;
|
||||||
|
use std::time::Duration;
|
||||||
|
use std::thread::sleep;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut config = Config::new("simple-example");
|
||||||
|
|
||||||
|
let foo = config.get_default("example section", "foo", "bar baz".to_string());
|
||||||
|
|
||||||
|
println!("Value of foo is {}", foo);
|
||||||
|
|
||||||
|
let example_no_default = config.get::<i32>("example section", "example variable with no default");
|
||||||
|
|
||||||
|
println!("Value of example variable with no default is {:?}", example_no_default);
|
||||||
|
|
||||||
|
let refresh_interval = config.get_default("default", "refresh interval", 1);
|
||||||
|
|
||||||
|
let mut osd_simple = OSD::new();
|
||||||
|
osd_simple.title = Some("Simple (but urgent) notification".to_string());
|
||||||
|
osd_simple.contents = OSDContents::Simple(Some("Just simple contents".to_string()));
|
||||||
|
osd_simple.urgency = Urgency::Critical;
|
||||||
|
|
||||||
|
let mut percentage = 0.;
|
||||||
|
|
||||||
|
let mut osd_progress_bar_percentage = OSD::new();
|
||||||
|
osd_progress_bar_percentage.title = Some("A progress bar showing important percentage!".to_string());
|
||||||
|
|
||||||
|
let eta = 15.;
|
||||||
|
let mut elapsed = 0.;
|
||||||
|
|
||||||
|
let mut osd_progress_bar_text = OSD::new();
|
||||||
|
osd_progress_bar_text.title = Some("Nuclear warhead launch in progress, time left:".to_string());
|
||||||
|
osd_progress_bar_text.urgency = Urgency::Low;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
percentage = (percentage + 0.123) % 1.;
|
||||||
|
|
||||||
|
elapsed = (elapsed + refresh_interval as f32) % eta;
|
||||||
|
|
||||||
|
osd_progress_bar_percentage.contents = OSDContents::Progress(percentage, OSDProgressText::Percentage);
|
||||||
|
|
||||||
|
osd_progress_bar_text.contents = OSDContents::Progress(elapsed / eta, OSDProgressText::Text(Some(format!("{}s / {}s", elapsed, eta))));
|
||||||
|
|
||||||
|
osd_simple.update();
|
||||||
|
osd_progress_bar_percentage.update();
|
||||||
|
osd_progress_bar_text.update();
|
||||||
|
|
||||||
|
sleep(Duration::from_secs(refresh_interval));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user