Propagate I/O-errors to main.

This commit is contained in:
shy 2021-04-10 08:20:05 +02:00
parent 1e749c7cbd
commit 0b40242baa
2 changed files with 39 additions and 30 deletions

View file

@ -22,7 +22,7 @@ pub fn kitchentimer(
signal: Arc<AtomicUsize>, signal: Arc<AtomicUsize>,
sigwinch: Arc<AtomicBool>, sigwinch: Arc<AtomicBool>,
spawned: &mut Option<std::process::Child>, spawned: &mut Option<std::process::Child>,
) { ) -> Result<(), std::io::Error> {
let mut layout = Layout::new(&config); let mut layout = Layout::new(&config);
layout.force_recalc = sigwinch; layout.force_recalc = sigwinch;
// Initialise roster_width. // Initialise roster_width.
@ -62,7 +62,7 @@ pub fn kitchentimer(
0 => (), 0 => (),
// Suspend execution on SIGTSTP. // Suspend execution on SIGTSTP.
SIGTSTP => { SIGTSTP => {
suspend(&mut stdout); suspend(&mut stdout)?;
// Clear SIGCONT, as we have already taken care to reset the // Clear SIGCONT, as we have already taken care to reset the
// terminal. // terminal.
signal.compare_and_swap(SIGCONT, 0, Ordering::Relaxed); signal.compare_and_swap(SIGCONT, 0, Ordering::Relaxed);
@ -99,7 +99,7 @@ pub fn kitchentimer(
if !buffer.is_empty() { if !buffer.is_empty() {
if let Err(e) = alarm_roster.add(&buffer) { if let Err(e) = alarm_roster.add(&buffer) {
// Error while processing input buffer. // Error while processing input buffer.
error_msg(&mut stdout, &layout, e); error_msg(&mut stdout, &layout, e)?;
} else { } else {
// Input buffer processed without error. // Input buffer processed without error.
layout.set_roster_width(alarm_roster.width()); layout.set_roster_width(alarm_roster.width());
@ -167,7 +167,7 @@ pub fn kitchentimer(
Key::Ctrl('r') => layout.force_redraw = true, Key::Ctrl('r') => layout.force_redraw = true,
// Suspend an ^Z. // Suspend an ^Z.
Key::Ctrl('z') => { Key::Ctrl('z') => {
suspend(&mut stdout); suspend(&mut stdout)?;
// Clear SIGCONT, as we have already taken care to reset // Clear SIGCONT, as we have already taken care to reset
// the terminal. // the terminal.
signal.compare_and_swap(SIGCONT, 0, Ordering::Relaxed); signal.compare_and_swap(SIGCONT, 0, Ordering::Relaxed);
@ -194,9 +194,9 @@ pub fn kitchentimer(
// Update input buffer display. // Update input buffer display.
if update_buffer { if update_buffer {
draw_buffer(&mut stdout, &mut layout, &buffer); draw_buffer(&mut stdout, &mut layout, &buffer)?;
update_buffer = false; update_buffer = false;
stdout.flush().unwrap(); stdout.flush()?;
} }
let elapsed = if clock.paused { let elapsed = if clock.paused {
@ -227,7 +227,7 @@ pub fn kitchentimer(
// Check for exceeded alarms. // Check for exceeded alarms.
if let Some((time, label)) = alarm_roster.check(&mut clock, &layout, &mut countdown) { if let Some((time, label)) = alarm_roster.check(&mut clock, &layout, &mut countdown) {
// Write ASCII bell code. // Write ASCII bell code.
write!(stdout, "{}", 0x07 as char).unwrap(); write!(stdout, "{}", 0x07 as char)?;
layout.force_redraw = true; layout.force_redraw = true;
// Run command if configured. // Run command if configured.
@ -248,13 +248,13 @@ pub fn kitchentimer(
// Clear the window and redraw menu bar, alarm roster and buffer if // Clear the window and redraw menu bar, alarm roster and buffer if
// requested. // requested.
if layout.force_redraw { if layout.force_redraw {
write!(stdout, "{}", clear::All).unwrap(); write!(stdout, "{}", clear::All)?;
// Redraw list of alarms. // Redraw list of alarms.
alarm_roster.draw(&mut stdout, &mut layout); alarm_roster.draw(&mut stdout, &mut layout);
// Redraw buffer. // Redraw buffer.
draw_buffer(&mut stdout, &mut layout, &buffer); draw_buffer(&mut stdout, &mut layout, &buffer)?;
// Schedule menu redraw. // Schedule menu redraw.
update_menu = true; update_menu = true;
@ -274,8 +274,7 @@ pub fn kitchentimer(
false if layout.can_hold(MENUBAR_SHORT) => MENUBAR_SHORT, false if layout.can_hold(MENUBAR_SHORT) => MENUBAR_SHORT,
_ => "", _ => "",
}, },
style::Reset,) style::Reset)?;
.unwrap();
} }
clock.draw(&mut stdout, &layout); clock.draw(&mut stdout, &layout);
@ -290,8 +289,7 @@ pub fn kitchentimer(
write!( write!(
stdout, stdout,
"{}", "{}",
cursor::Goto(layout.cursor.col, layout.cursor.line)) cursor::Goto(layout.cursor.col, layout.cursor.line))?;
.unwrap();
} }
// Check any spawned child process. // Check any spawned child process.
@ -316,7 +314,7 @@ pub fn kitchentimer(
// Reset redraw_all and flush stdout. // Reset redraw_all and flush stdout.
layout.force_redraw = false; layout.force_redraw = false;
stdout.flush().unwrap(); stdout.flush()?;
} }
// Main loop delay. // Main loop delay.
@ -328,8 +326,9 @@ pub fn kitchentimer(
"{}{}{}", "{}{}{}",
clear::BeforeCursor, clear::BeforeCursor,
cursor::Goto(1, 1), cursor::Goto(1, 1),
cursor::Show) cursor::Show)?;
.unwrap();
Ok(())
} }
// Draw input buffer. // Draw input buffer.
@ -337,15 +336,15 @@ fn draw_buffer<W: Write>(
stdout: &mut RawTerminal<W>, stdout: &mut RawTerminal<W>,
layout: &mut Layout, layout: &mut Layout,
buffer: &String, buffer: &String,
) { ) -> Result<(), std::io::Error>
{
if !buffer.is_empty() { if !buffer.is_empty() {
write!(stdout, write!(stdout,
"{}{}Add alarm: {}{}", "{}{}Add alarm: {}{}",
cursor::Goto(layout.buffer.col, layout.buffer.line), cursor::Goto(layout.buffer.col, layout.buffer.line),
clear::CurrentLine, clear::CurrentLine,
cursor::Show, cursor::Show,
buffer) buffer)?;
.unwrap();
layout.cursor.col = layout.buffer.col + 11 + unicode_length(buffer); layout.cursor.col = layout.buffer.col + 11 + unicode_length(buffer);
} else { } else {
// Clear buffer display. // Clear buffer display.
@ -353,32 +352,38 @@ fn draw_buffer<W: Write>(
"{}{}{}", "{}{}{}",
cursor::Goto(layout.buffer.col, layout.buffer.line), cursor::Goto(layout.buffer.col, layout.buffer.line),
clear::CurrentLine, clear::CurrentLine,
cursor::Hide) cursor::Hide)?;
.unwrap();
} }
Ok(())
} }
// Draw error message at input buffer position. // Draw error message at input buffer position.
fn error_msg<W: Write>(stdout: &mut RawTerminal<W>, layout: &Layout, msg: &str) { fn error_msg<W: Write>(
stdout: &mut RawTerminal<W>,
layout: &Layout,
msg: &str
) -> Result<(), std::io::Error>
{
write!(stdout, write!(stdout,
"{}{}{}{}{}", "{}{}{}{}{}",
cursor::Goto(layout.error.col, layout.error.line), cursor::Goto(layout.error.col, layout.error.line),
color::Fg(color::LightRed), color::Fg(color::LightRed),
msg, msg,
color::Fg(color::Reset), color::Fg(color::Reset),
cursor::Hide) cursor::Hide)?;
.unwrap(); Ok (())
} }
// Prepare to suspend execution. Called on SIGTSTP. // Prepare to suspend execution. Called on SIGTSTP.
fn suspend<W: Write>(mut stdout: &mut RawTerminal<W>) { fn suspend<W: Write>(mut stdout: &mut RawTerminal<W>)
-> Result<(), std::io::Error>
{
write!(stdout, write!(stdout,
"{}{}{}", "{}{}{}",
cursor::Goto(1,1), cursor::Goto(1,1),
clear::All, clear::All,
cursor::Show) cursor::Show)?;
.unwrap(); stdout.flush()?;
stdout.flush().unwrap();
stdout.suspend_raw_mode() stdout.suspend_raw_mode()
.unwrap_or_else(|error| { .unwrap_or_else(|error| {
eprintln!("Failed to leave raw terminal mode prior to suspend: {}", error); eprintln!("Failed to leave raw terminal mode prior to suspend: {}", error);
@ -389,6 +394,7 @@ fn suspend<W: Write>(mut stdout: &mut RawTerminal<W>) {
} }
restore_after_suspend(&mut stdout); restore_after_suspend(&mut stdout);
Ok(())
} }
// Set up terminal after SIGTSTP or SIGSTOP. // Set up terminal after SIGTSTP or SIGSTOP.

View file

@ -45,13 +45,16 @@ fn main() {
let mut spawned: Option<std::process::Child> = None; let mut spawned: Option<std::process::Child> = None;
// Runs main loop. // Runs main loop.
kitchentimer( match kitchentimer(
config, config,
alarm_roster, alarm_roster,
signal, signal,
sigwinch, sigwinch,
&mut spawned, &mut spawned,
); ) {
Ok(_) => (),
Err(e) => eprintln!("Error: {}", e),
}
// Wait for remaining spawned processes to exit. // Wait for remaining spawned processes to exit.
if let Some(ref mut child) = spawned { if let Some(ref mut child) = spawned {