diff --git a/src/main.rs b/src/main.rs index 26e26a9..009d421 100644 --- a/src/main.rs +++ b/src/main.rs @@ -160,7 +160,7 @@ fn main() -> io::Result<()> { let mut stdout = stdout(); - if eff.inline { + let finished = if eff.inline { if has_explicit_duration { stdout.execute(Print("\r\n"))?; } @@ -174,7 +174,7 @@ fn main() -> io::Result<()> { &audio_path, &url, eff.silent, - )?; + )? } else { run_fullscreen_timer( &mut stdout, @@ -185,7 +185,11 @@ fn main() -> io::Result<()> { &audio_path, &url, eff.silent, - )?; + )? + }; + + if !finished { + std::process::exit(render::QUIT_EXIT_CODE); } Ok(()) @@ -210,7 +214,7 @@ fn run_fullscreen_timer( audio_path: &Option, url: &Option, silent: bool, -) -> io::Result<()> { +) -> io::Result { terminal::enable_raw_mode()?; stdout.execute(cursor::Hide)?; stdout.execute(Clear(ClearType::All))?; @@ -233,6 +237,9 @@ fn run_fullscreen_timer( thread::sleep(Duration::from_millis(50)); } + // Capture completion status before audio playback can flip `running`. + let finished = running.load(Ordering::Relaxed) && Instant::now() >= end; + let (_, rows) = size()?; let center_row = rows / 2; @@ -253,7 +260,7 @@ fn run_fullscreen_timer( stdout.execute(Print("\n"))?; terminal::disable_raw_mode()?; - Ok(()) + Ok(finished) } fn run_inline_timer( @@ -265,7 +272,7 @@ fn run_inline_timer( audio_path: &Option, url: &Option, silent: bool, -) -> io::Result<()> { +) -> io::Result { terminal::enable_raw_mode()?; stdout.execute(cursor::Hide)?; @@ -290,6 +297,9 @@ fn run_inline_timer( thread::sleep(Duration::from_millis(50)); } + // Capture completion status before audio playback can flip `running`. + let finished = running.load(Ordering::Relaxed) && Instant::now() >= end; + handle_finish( stdout, running, @@ -306,7 +316,7 @@ fn run_inline_timer( stdout.execute(cursor::Show)?; terminal::disable_raw_mode()?; - Ok(()) + Ok(finished) } fn handle_finish( diff --git a/src/render.rs b/src/render.rs index dd21964..88a6778 100644 --- a/src/render.rs +++ b/src/render.rs @@ -11,6 +11,9 @@ use std::{ time::{Duration, Instant}, }; +/// Exit code used when the user cancels via Ctrl+C or Esc (128 + SIGINT). +pub const QUIT_EXIT_CODE: i32 = 130; + /// Returns true if the event is Ctrl+C or Esc. pub fn is_quit_event(key: &event::KeyEvent) -> bool { key.code == KeyCode::Esc @@ -23,7 +26,7 @@ fn cleanup_and_exit(stdout: &mut io::Stdout) -> ! { let _ = stdout.execute(cursor::MoveTo(0, 0)); let _ = stdout.execute(cursor::Show); let _ = terminal::disable_raw_mode(); - std::process::exit(0); + std::process::exit(QUIT_EXIT_CODE); } /// Print a message centered horizontally at the given row. @@ -182,7 +185,7 @@ pub fn inline_interactive_prompt( .flush()?; stdout.execute(cursor::Show)?; terminal::disable_raw_mode()?; - std::process::exit(0); + std::process::exit(QUIT_EXIT_CODE); } match key_event.code { KeyCode::Char(c) if c.is_ascii_digit() && cursor_pos < 6 => { @@ -375,7 +378,7 @@ fn inline_prompt_audio_path(stdout: &mut io::Stdout, row: u16) -> io::Result { @@ -855,7 +858,7 @@ fn inline_prompt_url(stdout: &mut io::Stdout, row: u16) -> io::Result {