aboutsummaryrefslogtreecommitdiffstats
path: root/src/bin/ttyrec/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/bin/ttyrec/main.rs')
-rw-r--r--src/bin/ttyrec/main.rs91
1 files changed, 41 insertions, 50 deletions
diff --git a/src/bin/ttyrec/main.rs b/src/bin/ttyrec/main.rs
index 8278998..1dbba54 100644
--- a/src/bin/ttyrec/main.rs
+++ b/src/bin/ttyrec/main.rs
@@ -11,10 +11,7 @@
#![allow(clippy::too_many_lines)]
#![allow(clippy::type_complexity)]
-use async_std::io::{ReadExt as _, WriteExt as _};
-use async_std::prelude::FutureExt as _;
-use async_std::stream::StreamExt as _;
-use pty_process::Command as _;
+use tokio::io::{AsyncReadExt as _, AsyncWriteExt as _};
#[derive(Debug, structopt::StructOpt)]
#[structopt(
@@ -55,42 +52,46 @@ fn get_cmd(
)
}
+#[derive(Debug)]
enum Event {
Key(textmode::Result<Option<textmode::Key>>),
Stdout(std::io::Result<Vec<u8>>),
Resize((u16, u16)),
Error(anyhow::Error),
+ Quit,
}
+#[tokio::main]
async fn async_main(opt: Opt) -> anyhow::Result<()> {
let Opt { cmd, file } = opt;
let (cmd, args) = get_cmd(cmd);
- let fh = async_std::fs::File::create(file).await?;
+ let fh = tokio::fs::File::create(file).await?;
- let mut input = textmode::Input::new().await?;
+ let mut input = textmode::blocking::Input::new()?;
let _input_guard = input.take_raw_guard();
- let mut stdout = async_std::io::stdout();
+ let mut stdout = tokio::io::stdout();
let size = terminal_size::terminal_size().map_or(
(24, 80),
|(terminal_size::Width(w), terminal_size::Height(h))| (h, w),
);
- let child = async_std::process::Command::new(cmd)
- .args(args)
- .spawn_pty(Some(&pty_process::Size::new(size.0, size.1)))?;
+ let mut pty = pty_process::Pty::new()?;
+ pty.resize(pty_process::Size::new(size.0, size.1))?;
+ let pts = pty.pts()?;
+ let mut child = pty_process::Command::new(cmd).args(args).spawn(&pts)?;
- let (event_w, event_r) = async_std::channel::unbounded();
- let (input_w, input_r) = async_std::channel::unbounded();
- let (resize_w, resize_r) = async_std::channel::unbounded();
+ let (event_w, mut event_r) = tokio::sync::mpsc::unbounded_channel();
+ let (input_w, mut input_r) = tokio::sync::mpsc::unbounded_channel();
+ let (resize_w, mut resize_r) = tokio::sync::mpsc::unbounded_channel();
{
- let mut signals = signal_hook_async_std::Signals::new(&[
- signal_hook::consts::signal::SIGWINCH,
- ])?;
+ let mut signals = tokio::signal::unix::signal(
+ tokio::signal::unix::SignalKind::window_change(),
+ )?;
let event_w = event_w.clone();
- async_std::task::spawn(async move {
- while signals.next().await.is_some() {
+ tokio::task::spawn(async move {
+ while signals.recv().await.is_some() {
event_w
.send(Event::Resize(
terminal_size::terminal_size().map_or(
@@ -101,7 +102,6 @@ async fn async_main(opt: Opt) -> anyhow::Result<()> {
)| { (h, w) },
),
))
- .await
// event_w is never closed, so this can never fail
.unwrap();
}
@@ -110,11 +110,10 @@ async fn async_main(opt: Opt) -> anyhow::Result<()> {
{
let event_w = event_w.clone();
- async_std::task::spawn(async move {
+ std::thread::spawn(move || {
loop {
event_w
- .send(Event::Key(input.read_key().await))
- .await
+ .send(Event::Key(input.read_key()))
// event_w is never closed, so this can never fail
.unwrap();
}
@@ -123,57 +122,50 @@ async fn async_main(opt: Opt) -> anyhow::Result<()> {
{
let event_w = event_w.clone();
- async_std::task::spawn(async move {
+ tokio::task::spawn(async move {
loop {
- enum Res {
- Read(Result<usize, std::io::Error>),
- Write(Result<Vec<u8>, async_std::channel::RecvError>),
- Resize(Result<(u16, u16), async_std::channel::RecvError>),
- }
let mut buf = [0_u8; 4096];
- let mut pty = child.pty();
- let read = async { Res::Read(pty.read(&mut buf).await) };
- let write = async { Res::Write(input_r.recv().await) };
- let resize = async { Res::Resize(resize_r.recv().await) };
- match read.race(write).race(resize).await {
- Res::Read(res) => {
+ tokio::select! {
+ res = pty.read(&mut buf) => {
let res = res.map(|n| buf[..n].to_vec());
let err = res.is_err();
event_w
.send(Event::Stdout(res))
- .await
// event_w is never closed, so this can never fail
.unwrap();
if err {
+ eprintln!("pty read failed: {}", err);
break;
}
}
- Res::Write(res) => {
+ res = input_r.recv() => {
// input_r is never closed, so this can never fail
- let bytes = res.unwrap();
+ let bytes: Vec<u8> = res.unwrap();
if let Err(e) = pty.write(&bytes).await {
event_w
.send(Event::Error(anyhow::anyhow!(e)))
- .await
// event_w is never closed, so this can never
// fail
.unwrap();
}
}
- Res::Resize(res) => {
+ res = resize_r.recv() => {
// resize_r is never closed, so this can never fail
- let size = res.unwrap();
- if let Err(e) = child.resize_pty(
- &pty_process::Size::new(size.0, size.1),
+ let size: (u16, u16) = res.unwrap();
+ if let Err(e) = pty.resize(
+ pty_process::Size::new(size.0, size.1),
) {
event_w
.send(Event::Error(anyhow::anyhow!(e)))
- .await
// event_w is never closed, so this can never
// fail
.unwrap();
}
}
+ _ = child.wait() => {
+ event_w.send(Event::Quit).unwrap();
+ break;
+ }
}
}
});
@@ -181,11 +173,12 @@ async fn async_main(opt: Opt) -> anyhow::Result<()> {
let mut writer = ttyrec::Writer::new(fh);
loop {
- match event_r.recv().await? {
+ // XXX unwrap
+ match event_r.recv().await.unwrap() {
Event::Key(key) => {
let key = key?;
if let Some(key) = key {
- input_w.send(key.into_bytes()).await?;
+ input_w.send(key.into_bytes()).unwrap();
} else {
break;
}
@@ -197,18 +190,16 @@ async fn async_main(opt: Opt) -> anyhow::Result<()> {
stdout.flush().await?;
}
Err(e) => {
- if e.raw_os_error() == Some(libc::EIO) {
- break;
- }
anyhow::bail!("failed to read from child process: {}", e);
}
},
Event::Resize((h, w)) => {
- resize_w.send((h, w)).await?;
+ resize_w.send((h, w)).unwrap();
}
Event::Error(e) => {
return Err(e);
}
+ Event::Quit => break,
}
}
@@ -217,7 +208,7 @@ async fn async_main(opt: Opt) -> anyhow::Result<()> {
#[paw::main]
fn main(opt: Opt) {
- match async_std::task::block_on(async_main(opt)) {
+ match async_main(opt) {
Ok(_) => (),
Err(e) => {
eprintln!("ttyrec: {}", e);