aboutsummaryrefslogtreecommitdiffstats
path: root/src/input.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/input.rs')
-rw-r--r--src/input.rs62
1 files changed, 60 insertions, 2 deletions
diff --git a/src/input.rs b/src/input.rs
index ee5d28f..159e61d 100644
--- a/src/input.rs
+++ b/src/input.rs
@@ -1,6 +1,64 @@
use crate::error::*;
use futures_lite::io::AsyncReadExt as _;
+use std::os::unix::io::AsRawFd as _;
+
+pub struct RawGuard {
+ termios: nix::sys::termios::Termios,
+ cleaned_up: bool,
+}
+
+impl RawGuard {
+ #[allow(clippy::new_without_default)]
+ pub async fn new() -> Result<Self> {
+ let stdin = std::io::stdin().as_raw_fd();
+ let termios = blocking::unblock(move || {
+ nix::sys::termios::tcgetattr(stdin).map_err(Error::SetRaw)
+ })
+ .await?;
+ let mut termios_raw = termios.clone();
+ nix::sys::termios::cfmakeraw(&mut termios_raw);
+ blocking::unblock(move || {
+ nix::sys::termios::tcsetattr(
+ stdin,
+ nix::sys::termios::SetArg::TCSANOW,
+ &termios_raw,
+ )
+ .map_err(Error::SetRaw)
+ })
+ .await?;
+ Ok(Self {
+ termios,
+ cleaned_up: false,
+ })
+ }
+
+ pub async fn cleanup(&mut self) -> Result<()> {
+ if self.cleaned_up {
+ return Ok(());
+ }
+ self.cleaned_up = true;
+ let stdin = std::io::stdin().as_raw_fd();
+ let termios = self.termios.clone();
+ blocking::unblock(move || {
+ nix::sys::termios::tcsetattr(
+ stdin,
+ nix::sys::termios::SetArg::TCSANOW,
+ &termios,
+ )
+ .map_err(Error::UnsetRaw)
+ })
+ .await
+ }
+}
+
+impl Drop for RawGuard {
+ fn drop(&mut self) {
+ futures_lite::future::block_on(async {
+ let _ = self.cleanup().await;
+ });
+ }
+}
pub struct Input {
buf: Vec<u8>,
@@ -15,8 +73,8 @@ pub struct Input {
#[allow(clippy::new_without_default)]
impl Input {
- pub fn new() -> Result<(Self, crate::RawGuard)> {
- Ok((Self::new_without_raw(), crate::RawGuard::new()?))
+ pub async fn new() -> Result<(Self, RawGuard)> {
+ Ok((Self::new_without_raw(), RawGuard::new().await?))
}
pub fn new_without_raw() -> Self {