From 0cf66f816712e8e8adb941fff57823625611370a Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Tue, 9 Mar 2021 02:53:24 -0500 Subject: handle errors properly in raw guard --- examples/input.rs | 2 +- examples/tmux.rs | 2 +- src/blocking/input.rs | 4 ++-- src/error.rs | 6 ++++++ src/input.rs | 4 ++-- src/raw_guard.rs | 24 ++++++++++++++---------- 6 files changed, 26 insertions(+), 16 deletions(-) diff --git a/examples/input.rs b/examples/input.rs index e63787b..d478f92 100644 --- a/examples/input.rs +++ b/examples/input.rs @@ -1,5 +1,5 @@ fn main() { - let (mut input, _raw) = textmode::blocking::Input::new(); + let (mut input, _raw) = textmode::blocking::Input::new().unwrap(); for arg in std::env::args().skip(1) { match arg.as_str() { "--disable-utf8" => input.parse_utf8(false), diff --git a/examples/tmux.rs b/examples/tmux.rs index 490a22b..d5969e3 100644 --- a/examples/tmux.rs +++ b/examples/tmux.rs @@ -303,7 +303,7 @@ struct Tmux { impl Tmux { async fn new() -> Self { - let (input, _raw) = textmode::Input::new(); + let (input, _raw) = textmode::Input::new().unwrap(); let (tm, _screen) = textmode::Output::new().await.unwrap(); let state = State::new(); Self { diff --git a/src/blocking/input.rs b/src/blocking/input.rs index ff69eda..18e349a 100644 --- a/src/blocking/input.rs +++ b/src/blocking/input.rs @@ -15,8 +15,8 @@ pub struct Input { #[allow(clippy::new_without_default)] impl Input { - pub fn new() -> (Self, crate::RawGuard) { - (Self::new_without_raw(), crate::RawGuard::new()) + pub fn new() -> Result<(Self, crate::RawGuard)> { + Ok((Self::new_without_raw(), crate::RawGuard::new()?)) } pub fn new_without_raw() -> Self { diff --git a/src/error.rs b/src/error.rs index 560f5cb..f2e774e 100644 --- a/src/error.rs +++ b/src/error.rs @@ -3,6 +3,12 @@ pub enum Error { #[error("error reading from stdin")] ReadStdin(#[source] std::io::Error), + #[error("error enabling terminal raw mode")] + SetRaw(#[source] nix::Error), + + #[error("error restoring terminal from raw mode")] + UnsetRaw(#[source] nix::Error), + #[error("error writing to stdout")] WriteStdout(#[source] std::io::Error), } diff --git a/src/input.rs b/src/input.rs index 8bd3b60..bc16568 100644 --- a/src/input.rs +++ b/src/input.rs @@ -15,8 +15,8 @@ pub struct Input { #[allow(clippy::new_without_default)] impl Input { - pub fn new() -> (Self, crate::RawGuard) { - (Self::new_without_raw(), crate::RawGuard::new()) + pub fn new() -> Result<(Self, crate::RawGuard)> { + Ok((Self::new_without_raw(), crate::RawGuard::new()?)) } pub fn new_without_raw() -> Self { diff --git a/src/raw_guard.rs b/src/raw_guard.rs index 909ba9e..3835181 100644 --- a/src/raw_guard.rs +++ b/src/raw_guard.rs @@ -1,3 +1,5 @@ +use crate::error::*; + use std::os::unix::io::AsRawFd as _; pub struct RawGuard { @@ -7,9 +9,10 @@ pub struct RawGuard { impl RawGuard { #[allow(clippy::new_without_default)] - pub fn new() -> Self { + pub fn new() -> Result { let stdin = std::io::stdin().as_raw_fd(); - let termios = nix::sys::termios::tcgetattr(stdin).unwrap(); + let termios = + nix::sys::termios::tcgetattr(stdin).map_err(Error::SetRaw)?; let mut termios_raw = termios.clone(); nix::sys::termios::cfmakeraw(&mut termios_raw); nix::sys::termios::tcsetattr( @@ -17,29 +20,30 @@ impl RawGuard { nix::sys::termios::SetArg::TCSANOW, &termios_raw, ) - .unwrap(); - Self { + .map_err(Error::SetRaw)?; + Ok(Self { termios, cleaned_up: false, - } + }) } - pub fn cleanup(&mut self) { + pub fn cleanup(&mut self) -> Result<()> { if self.cleaned_up { - return; + return Ok(()); } self.cleaned_up = true; let stdin = std::io::stdin().as_raw_fd(); - let _ = nix::sys::termios::tcsetattr( + nix::sys::termios::tcsetattr( stdin, nix::sys::termios::SetArg::TCSANOW, &self.termios, - ); + ) + .map_err(Error::UnsetRaw) } } impl Drop for RawGuard { fn drop(&mut self) { - self.cleanup(); + let _ = self.cleanup(); } } -- cgit v1.2.3