clean up outer functions

This commit is contained in:
Dr. Matthias Ratajczak
2023-03-02 16:14:30 +01:00
parent 54c2255c1c
commit 7bf31b9ee2
3 changed files with 89 additions and 39 deletions
+80 -38
View File
@@ -3,48 +3,67 @@ use std::fs::{self, read_to_string};
use std::io::{stdout, Stdout, Write};
use std::os::unix::prelude::OsStringExt;
use std::path::{Path, PathBuf};
use std::process::Command;
use std::process::{Command, ExitCode};
use std::time::Duration;
use anyhow::{anyhow, bail, Result};
use crossterm::{cursor, QueueableCommand};
use crossterm::{
cursor::MoveTo,
event::{Event, EventStream, KeyCode, KeyModifiers},
terminal::{self, disable_raw_mode, enable_raw_mode},
ExecutableCommand, Result,
ExecutableCommand,
};
use futures::StreamExt;
use tokio::sync::broadcast::{channel, Receiver, Sender};
use tokio::task::JoinSet;
use tokio::time::sleep;
const ONE_SECOND: Duration = Duration::from_secs(1);
const PID_FILE: &str = "/tmp/pomodoro.pid";
#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<()> {
async fn main() -> ExitCode {
match main2().await {
Ok(()) => ExitCode::SUCCESS,
Err(e) => {
eprintln!("{}", e.root_cause().to_string());
ExitCode::FAILURE
}
}
}
async fn main2() -> Result<()> {
let pid = if let Some(pid) = Pid::check_already_running() {
eprintln!("already running (pid {})", pid.pid);
return Ok(());
bail!("already running (pid {})", pid.pid)
} else {
Pid::create()
Pid::create()?
};
let result = run_all_tasks().await;
Ui::clear_terminal()?;
pid.remove()?;
result
}
async fn run_all_tasks() -> Result<()> {
let (tx, rx) = channel::<Message>(10);
let timer = Pomodoro::new(rx);
let ui = Ui::new(tx);
let timer_task = tokio::spawn(async move { timer.main_loop().await });
let ui_task = tokio::spawn(async move { ui.main_loop().await });
let mut tasks = JoinSet::new();
tokio::select! (
result = timer_task => result??,
result = ui_task => result??,
);
tasks.spawn(timer.main_loop());
tasks.spawn(ui.main_loop());
Ui::clear_terminal()?;
pid.remove();
while let Some(result) = tasks.join_next().await {
result??;
}
Ok(())
}
@@ -82,16 +101,17 @@ impl Pid {
Some(result)
}
fn create() -> Self {
fn create() -> Result<Self> {
let pid = std::process::id();
let path = PathBuf::from(PID_FILE);
let mut fd = fs::File::create(&path).unwrap();
write!(fd, "{pid}").unwrap();
Self { pid, path }
let mut fd = fs::File::create(&path)?;
write!(fd, "{pid}")?;
let result = Self { pid, path };
Ok(result)
}
fn remove(self) {
fs::remove_file(self.path).unwrap();
fn remove(self) -> Result<()> {
fs::remove_file(self.path).map_err(|e| anyhow!(e))
}
}
@@ -112,20 +132,37 @@ impl Ui {
stdout().execute(cursor::Hide)?;
if let Some(Ok(Event::Key(key_event))) = reader.next().await {
if Self::is_char_q(key_event) || Self::is_ctrl_c(key_event) {
self.sender.send(Message::Quit).unwrap();
disable_raw_mode()?;
stdout().execute(cursor::Show)?;
let should_exit = self.handle_key_event(key_event)?;
if should_exit {
return Ok(());
};
if Self::is_space(key_event) {
self.sender.send(Message::TogglePause).unwrap();
}
}
}
}
fn handle_key_event(&self, key_event: crossterm::event::KeyEvent) -> Result<bool> {
if Self::is_char_q(key_event) {
self.prepare_for_program_quit()?;
return Ok(true);
};
if Self::is_ctrl_c(key_event) {
self.prepare_for_program_quit()?;
self.sender.send(Message::CtrlC)?;
bail!("<Ctrl-C>");
}
if Self::is_space(key_event) {
self.sender.send(Message::TogglePause)?;
}
Ok(false)
}
fn prepare_for_program_quit(&self) -> Result<()> {
self.sender.send(Message::Quit)?;
disable_raw_mode()?;
stdout().execute(cursor::Show)?;
Ok(())
}
fn is_char_q(key_event: crossterm::event::KeyEvent) -> bool {
key_event.code == KeyCode::Char('q')
}
@@ -200,24 +237,28 @@ impl Pomodoro {
'inner: loop {
self.show_status()?;
if self.paused {
if self.receiver.recv().await.unwrap() == Message::TogglePause {
self.toggle_pause();
continue;
}
}
tokio::select! (
_ = sleep(ONE_SECOND) => {self.remaining -= ONE_SECOND;}
_ = sleep(ONE_SECOND) => {
if !self.paused {
self.remaining -= ONE_SECOND;
}
},
message = self.receiver.recv() => {
if let Ok(m) = message{
match m {
Message::Quit => {return Ok(());},
Message::Quit => {
return Ok(());
},
Message::CtrlC => {
bail!("<Ctrl-C>");
},
Message::TogglePause => {
self.toggle_pause();
continue;
}
}
} else {
bail!("<terminate>");
}
}
);
@@ -310,6 +351,7 @@ fn format(dur: Duration) -> String {
#[derive(Debug, Clone, Copy, PartialEq)]
enum Message {
CtrlC,
Quit,
TogglePause,
}