aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2021-03-09 03:19:05 -0500
committerJesse Luehrs <doy@tozt.net>2021-03-09 03:19:05 -0500
commit898ca615b5d573120a62cc01b2fb43f1d707f69f (patch)
treed525e012441c2104e9a5f2e4cae87c2396162836
parent51e877d0d0fcd122d1cb0934639e43579a380f63 (diff)
downloadtextmode-898ca615b5d573120a62cc01b2fb43f1d707f69f.tar.gz
textmode-898ca615b5d573120a62cc01b2fb43f1d707f69f.zip
make raw_guard also async
i think tcsetattr etc can actually block in some cases
-rw-r--r--examples/tmux.rs2
-rw-r--r--src/blocking/input.rs51
-rw-r--r--src/input.rs62
-rw-r--r--src/lib.rs4
-rw-r--r--src/raw_guard.rs49
5 files changed, 111 insertions, 57 deletions
diff --git a/examples/tmux.rs b/examples/tmux.rs
index d5969e3..877285b 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().unwrap();
+ let (input, _raw) = textmode::Input::new().await.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 6b466a2..bdc916b 100644
--- a/src/blocking/input.rs
+++ b/src/blocking/input.rs
@@ -1,6 +1,53 @@
use crate::error::*;
use std::io::Read 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 fn new() -> Result<Self> {
+ let stdin = std::io::stdin().as_raw_fd();
+ 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(
+ stdin,
+ nix::sys::termios::SetArg::TCSANOW,
+ &termios_raw,
+ )
+ .map_err(Error::SetRaw)?;
+ Ok(Self {
+ termios,
+ cleaned_up: false,
+ })
+ }
+
+ pub fn cleanup(&mut self) -> Result<()> {
+ if self.cleaned_up {
+ return Ok(());
+ }
+ self.cleaned_up = true;
+ let stdin = std::io::stdin().as_raw_fd();
+ nix::sys::termios::tcsetattr(
+ stdin,
+ nix::sys::termios::SetArg::TCSANOW,
+ &self.termios,
+ )
+ .map_err(Error::UnsetRaw)
+ }
+}
+
+impl Drop for RawGuard {
+ fn drop(&mut self) {
+ let _ = self.cleanup();
+ }
+}
pub struct Input {
buf: Vec<u8>,
@@ -15,8 +62,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 fn new() -> Result<(Self, RawGuard)> {
+ Ok((Self::new_without_raw(), RawGuard::new()?))
}
pub fn new_without_raw() -> Self {
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 {
diff --git a/src/lib.rs b/src/lib.rs
index 90f092a..e4abf7b 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -7,8 +7,6 @@ mod error;
pub use error::{Error, Result};
mod key;
pub use key::Key;
-mod raw_guard;
-pub use raw_guard::RawGuard;
#[cfg(feature = "async")]
mod output;
@@ -17,7 +15,7 @@ pub use output::{Output, ScreenGuard};
#[cfg(feature = "async")]
mod input;
#[cfg(feature = "async")]
-pub use input::Input;
+pub use input::{Input, RawGuard};
const INIT: &[u8] = b"\x1b7\x1b[?47h\x1b[2J\x1b[H\x1b[?25h";
const DEINIT: &[u8] = b"\x1b[?47l\x1b8\x1b[?25h";
diff --git a/src/raw_guard.rs b/src/raw_guard.rs
deleted file mode 100644
index 3835181..0000000
--- a/src/raw_guard.rs
+++ /dev/null
@@ -1,49 +0,0 @@
-use crate::error::*;
-
-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 fn new() -> Result<Self> {
- let stdin = std::io::stdin().as_raw_fd();
- 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(
- stdin,
- nix::sys::termios::SetArg::TCSANOW,
- &termios_raw,
- )
- .map_err(Error::SetRaw)?;
- Ok(Self {
- termios,
- cleaned_up: false,
- })
- }
-
- pub fn cleanup(&mut self) -> Result<()> {
- if self.cleaned_up {
- return Ok(());
- }
- self.cleaned_up = true;
- let stdin = std::io::stdin().as_raw_fd();
- nix::sys::termios::tcsetattr(
- stdin,
- nix::sys::termios::SetArg::TCSANOW,
- &self.termios,
- )
- .map_err(Error::UnsetRaw)
- }
-}
-
-impl Drop for RawGuard {
- fn drop(&mut self) {
- let _ = self.cleanup();
- }
-}