From d94926a235d100c7d7e22dea5268d6aca2b52ff8 Mon Sep 17 00:00:00 2001 From: Rekai Musuka Date: Sun, 13 Dec 2020 23:05:01 -0600 Subject: [PATCH] feat: add y/n option to continue pmdr cycle or not --- src/{pomodoro.rs => domasi.rs} | 94 ++++++++++++++++++++++------------ src/lib.rs | 4 +- src/main.rs | 4 +- 3 files changed, 64 insertions(+), 38 deletions(-) rename src/{pomodoro.rs => domasi.rs} (79%) diff --git a/src/pomodoro.rs b/src/domasi.rs similarity index 79% rename from src/pomodoro.rs rename to src/domasi.rs index cf065bf..6b135f8 100644 --- a/src/pomodoro.rs +++ b/src/domasi.rs @@ -6,21 +6,31 @@ use std::fmt::{Display, Formatter, Result as FmtResult}; use std::io::{self, Write}; use std::time::{Duration, Instant}; -#[derive(Debug, Copy, Clone, Default)] -pub struct Pomodoro { +static WORK_TIME: u64 = 1500; // Default: 1500 (25min) +static SHORT_BREAK_TIME: u64 = 300; // Default: 300 (5min) +static LONG_BREAK_TIME: u64 = 600; // Default: 600 (10min) +static POLLING_RATE: Duration = Duration::from_millis(100); + +#[derive(Debug, Copy, Clone)] +pub struct Domasi { state: State, count: u64, wait_start: Option, paused: PausedState, } -static POMODORO_CYCLES: u64 = 5; -static WORK_TIME: u64 = 1500; // Default: 1500 (25min) -static SHORT_BREAK_TIME: u64 = 300; // Default: 300 (5min) -static LONG_BREAK_TIME: u64 = 600; // Default: 600 (10min) +impl Default for Domasi { + fn default() -> Self { + Self { + state: State::Start, + count: 0, + wait_start: None, + paused: Default::default(), + } + } +} -static POLLING_RATE: Duration = Duration::from_millis(100); -impl Pomodoro { +impl Domasi { pub fn new() -> Self { Self::default() } @@ -28,9 +38,26 @@ impl Pomodoro { pub fn start(&mut self, maybe_alert: Option) -> crossterm::Result<()> { enable_raw_mode()?; - loop { + 'main: loop { if let Status::Complete = self.poll(maybe_alert.as_ref()) { - break; + let _ = Self::print("Start next session? (Y/N)"); + + 'input: loop { + if let Event::Key(key_event) = event::read()? { + match key_event.code { + KeyCode::Char('y') | KeyCode::Char('Y') => { + *self = Self { + count: self.count, + ..Default::default() + }; + + break 'input; + } + KeyCode::Char('n') | KeyCode::Char('N') => break 'main, + _ => {} + } + } + } } if event::poll(POLLING_RATE)? { @@ -73,7 +100,7 @@ impl Pomodoro { fn notify_complete(&self) -> Result<(), Box> { let mut toast = notify_rust::Notification::new(); toast.summary("Pomodoro cycle complete!"); - toast.body("domasi will now exit."); + toast.body("Continue?"); toast.show()?; Ok(()) } @@ -92,7 +119,7 @@ impl Pomodoro { 0 => "Time for your 1st work session.", 1 => "Time for your 2nd work session.", 2 => "Time for your 3rd work session.", - 3 => "Time for your 4th work session.", + 3 => "Time for your last work session.", _ => unreachable!(), } } @@ -100,7 +127,6 @@ impl Pomodoro { let mut toast = notify_rust::Notification::new(); match self.state { - State::Inactive => {} State::Work => { toast .summary(session_num(self.count)) @@ -119,6 +145,7 @@ impl Pomodoro { .body(&cycle_count(self.count)) .show()?; } + State::UserWait | State::Start => {} }; Ok(()) @@ -150,8 +177,9 @@ impl Pomodoro { self.state = new_state; self.wait_start = match new_state { - State::Inactive => None, + State::UserWait => None, State::Work | State::ShortBreak | State::LongBreak => Some(Instant::now()), + State::Start => unreachable!("Domasi#next should never return State::Start"), }; if let Some(alert) = maybe_alert { @@ -162,10 +190,8 @@ impl Pomodoro { self.display_time(); } Status::Complete => { - println!("\rPomodoro cycle complete!"); let _ = self.notify_complete(); } - Status::Inactive => {} }; status @@ -174,7 +200,7 @@ impl Pomodoro { fn display_time(&self) { if let Some(start) = self.wait_start { let remainder: Clock = (Self::wait_times(self.state) - (Instant::now() - start)).into(); - let _ = Self::print(&format!("\r{} {}", self.state, remainder)); + let _ = Self::print(&format!("{} {}", self.state, remainder)); } } @@ -183,7 +209,7 @@ impl Pomodoro { let stop_time: Clock = (Self::wait_times(self.state) - ((Instant::now() - self.paused.duration) - start)) .into(); - let _ = Self::print(&format!("\r[PAUSED] {} {}", self.state, stop_time)); + let _ = Self::print(&format!("[PAUSED] {} {}", self.state, stop_time)); } } @@ -194,9 +220,10 @@ impl Pomodoro { // Empty String so that we can clear line before writing // from the most-left side of the terminal again. // - // We write 24 spaces so that the entire line is always + // We write 25 spaces so that the entire line is always // written over - handle.write_all(b"\r ")?; + handle.write_all(b"\r ")?; + handle.write_all("\r".as_bytes())?; handle.write_all(text.as_bytes())?; handle.flush()?; Ok(()) @@ -213,8 +240,9 @@ impl Pomodoro { (Count::Increase, state) } - State::ShortBreak | State::Inactive => (Count::Remain, State::Work), - State::LongBreak => (Count::Remain, State::Inactive), + State::ShortBreak | State::Start => (Count::Remain, State::Work), + State::LongBreak => (Count::Remain, State::UserWait), + _ => unreachable!("Domasi#next should never be called on State::Inactive"), } } @@ -233,13 +261,10 @@ impl Pomodoro { Status::Active } } - None => { - if self.count / 4 == POMODORO_CYCLES { - Status::Complete - } else { - Status::NextState - } - } + None => match self.state { + State::UserWait if self.count % 4 == 0 => Status::Complete, + _ => Status::NextState, + }, } } @@ -248,7 +273,7 @@ impl Pomodoro { State::Work => Duration::from_secs(WORK_TIME), State::ShortBreak => Duration::from_secs(SHORT_BREAK_TIME), State::LongBreak => Duration::from_secs(LONG_BREAK_TIME), - _ => unreachable!("Can not have Pomodoro state = State::Inactive and wait_start = Some(...) at the same time.") + _ => unreachable!("Can not have Domasi state = State::Inactive and wait_start = Some(...) at the same time.") } } } @@ -324,13 +349,13 @@ enum Status { Paused, Active, NextState, - Inactive, Complete, } #[derive(Debug, Copy, Clone)] enum State { - Inactive, + Start, + UserWait, Work, ShortBreak, LongBreak, @@ -338,7 +363,7 @@ enum State { impl Default for State { fn default() -> Self { - State::Inactive + State::UserWait } } @@ -348,7 +373,8 @@ impl Display for State { State::Work => f.write_str("Working:"), State::ShortBreak => f.write_str("Resting:"), State::LongBreak => f.write_str("REALLY Resting:"), - State::Inactive => f.write_str("Inactive:"), + State::UserWait => f.write_str("Inactive:"), + _ => unreachable!("State::Start should never be displayed."), } } } diff --git a/src/lib.rs b/src/lib.rs index fc1c9f4..f2325a8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,4 @@ pub use alert::Alert; -pub use pomodoro::Pomodoro; +pub use domasi::Domasi; mod alert; -mod pomodoro; +mod domasi; diff --git a/src/main.rs b/src/main.rs index ea01481..9cd2e58 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,6 @@ use directories::ProjectDirs; use domasi::Alert; -use domasi::Pomodoro; +use domasi::Domasi; use std::fs; use std::path::PathBuf; @@ -17,7 +17,7 @@ fn main() { } } - let mut domasi: Pomodoro = Default::default(); + let mut domasi: Domasi = Default::default(); match get_alert() { Some(alert) => domasi.start(Some(alert)).unwrap(),