Propagate I/O-errors to main.
This commit is contained in:
parent
1e749c7cbd
commit
0b40242baa
2 changed files with 39 additions and 30 deletions
|
@ -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.
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in a new issue