You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
99 lines
2.6 KiB
99 lines
2.6 KiB
use chrono::prelude::*;
|
|
use chrono::Duration;
|
|
use std::io::{stdout, Result, StdoutLock, Write};
|
|
use std::process::{Command, Output};
|
|
use std::thread::sleep;
|
|
|
|
const TIME_FORMAT: &'static str = "%H:%M:%S";
|
|
|
|
fn main() {
|
|
run().unwrap();
|
|
}
|
|
|
|
/// Runs the application
|
|
///
|
|
/// Default time settings are 25 minutes for a working block and 5 minutes for a break.
|
|
fn run() -> Result<()> {
|
|
let work_duration = Duration::seconds(if cfg!(debug_assertions) { 75 } else { 25 * 60 });
|
|
let break_duration = Duration::seconds(if cfg!(debug_assertions) { 5 } else { 5 * 60 });
|
|
|
|
loop {
|
|
timer(
|
|
"Work",
|
|
"The working time is over, have a break now!",
|
|
&work_duration,
|
|
)?;
|
|
|
|
timer(
|
|
"Break",
|
|
"The break is over, get back to work!",
|
|
&break_duration,
|
|
)?;
|
|
}
|
|
}
|
|
|
|
/// Handles a timer block
|
|
///
|
|
/// # Arguments
|
|
///
|
|
/// * name - The name for this block, e.g. 'Work' or 'Break'
|
|
/// * after_msg - The message to be displayed by the Dialog window at the end of the time
|
|
/// * duration - How long this block shall be
|
|
fn timer(name: &str, after_msg: &str, duration: &Duration) -> Result<()> {
|
|
let out = stdout();
|
|
let mut out = out.lock();
|
|
let start = Local::now();
|
|
writeln!(out, "{} start {}", name, start.format(TIME_FORMAT))?;
|
|
|
|
loop {
|
|
reset_line(&mut out)?;
|
|
let elapsed: Duration = Local::now().signed_duration_since(start);
|
|
|
|
if elapsed >= *duration {
|
|
break;
|
|
}
|
|
|
|
let elapsed_time: NaiveTime = NaiveTime::from_hms(
|
|
(elapsed.num_hours() % 24) as u32,
|
|
(elapsed.num_minutes() % 60) as u32,
|
|
(elapsed.num_seconds() % 60) as u32,
|
|
);
|
|
write!(out, "Time elapsed: {}", elapsed_time.format(TIME_FORMAT))?;
|
|
out.flush().unwrap();
|
|
|
|
sleep(Duration::seconds(1).to_std().unwrap());
|
|
}
|
|
|
|
let now = Local::now();
|
|
writeln!(out, "{} end {}", name, now.format(TIME_FORMAT))?;
|
|
dialog(after_msg).unwrap();
|
|
Ok(())
|
|
}
|
|
|
|
/// Shows a dialog
|
|
///
|
|
/// Currently only supports KDE dialogs via command line program `kdialgo`.
|
|
///
|
|
/// # Arguments
|
|
///
|
|
/// * text - The text to be shown in the Dialog
|
|
fn dialog(text: &str) -> Result<Output> {
|
|
Command::new("sh")
|
|
.arg("-c")
|
|
.arg(format!(
|
|
"kdialog --title 'Pomodoro Timer' --msgbox '{}'",
|
|
text
|
|
))
|
|
.output()
|
|
}
|
|
|
|
/// Resets the current line on stdout
|
|
///
|
|
/// Works for me® but is probably unportable as hell.
|
|
///
|
|
/// # Arguments
|
|
///
|
|
/// * w - A reference to the locked stdout handle
|
|
pub fn reset_line(w: &mut StdoutLock) -> Result<()> {
|
|
write!(w, "\r[2K")
|
|
}
|