aboutsummaryrefslogtreecommitdiffstats
path: root/ui/backend/src/pty.rs
diff options
context:
space:
mode:
authorEllie Huxtable <ellie@atuin.sh>2024-07-30 16:54:10 +0100
committerGitHub <noreply@github.com>2024-07-30 16:54:10 +0100
commit808138de633e410c1d3867d4fb7cb74967647605 (patch)
treef180b7066b91d8d8d8006219a118439be1621d74 /ui/backend/src/pty.rs
parentchore(deps): bump debian (#2320) (diff)
downloadatuin-808138de633e410c1d3867d4fb7cb74967647605.zip
chore: remove ui directory (#2329)
This is still in development, but rather than clutter the commit history and issues with an unreleased project I've split the UI into its own repo. Once ready for release, I'll either merge the ui code back in, or just make the repo public.
Diffstat (limited to 'ui/backend/src/pty.rs')
-rw-r--r--ui/backend/src/pty.rs124
1 files changed, 0 insertions, 124 deletions
diff --git a/ui/backend/src/pty.rs b/ui/backend/src/pty.rs
deleted file mode 100644
index af394d95..00000000
--- a/ui/backend/src/pty.rs
+++ /dev/null
@@ -1,124 +0,0 @@
-use std::{
- io::Write,
- sync::{Arc, Mutex},
-};
-
-use bytes::Bytes;
-use eyre::{eyre, Result};
-use portable_pty::{CommandBuilder, MasterPty, PtySize};
-
-pub struct Pty {
- tx: tokio::sync::mpsc::Sender<Bytes>,
-
- pub master: Arc<Mutex<Box<dyn MasterPty + Send>>>,
- pub reader: Arc<Mutex<Box<dyn std::io::Read + Send>>>,
- pub child: Arc<Mutex<Box<dyn portable_pty::Child + Send>>>,
-}
-
-impl Pty {
- pub async fn open<'a>(rows: u16, cols: u16, cwd: Option<String>) -> Result<Self> {
- let sys = portable_pty::native_pty_system();
-
- let pair = sys
- .openpty(PtySize {
- rows,
- cols,
- pixel_width: 0,
- pixel_height: 0,
- })
- .map_err(|e| eyre!("Failed to open pty: {}", e))?;
-
- let mut cmd = CommandBuilder::new_default_prog();
-
- if let Some(cwd) = cwd {
- cmd.cwd(cwd);
- }
-
- let child = pair.slave.spawn_command(cmd).unwrap();
- drop(pair.slave);
-
- // Handle input -> write to master writer
- let (master_tx, mut master_rx) = tokio::sync::mpsc::channel::<Bytes>(32);
-
- let mut writer = pair.master.take_writer().unwrap();
- let reader = pair
- .master
- .try_clone_reader()
- .map_err(|e| e.to_string())
- .expect("Failed to clone reader");
-
- tokio::spawn(async move {
- while let Some(bytes) = master_rx.recv().await {
- writer.write_all(&bytes).unwrap();
- writer.flush().unwrap();
- }
-
- // When the channel has been closed, we won't be getting any more input. Close the
- // writer and the master.
- // This will also close the writer, which sends EOF to the underlying shell. Ensuring
- // that is also closed.
- drop(writer);
- });
-
- Ok(Pty {
- tx: master_tx,
- master: Arc::new(Mutex::new(pair.master)),
- reader: Arc::new(Mutex::new(reader)),
- child: Arc::new(Mutex::new(child)),
- })
- }
-
- pub async fn resize(&self, rows: u16, cols: u16) -> Result<()> {
- let master = self
- .master
- .lock()
- .map_err(|e| eyre!("Failed to lock pty master: {e}"))?;
-
- master
- .resize(PtySize {
- rows,
- cols,
- pixel_width: 0,
- pixel_height: 0,
- })
- .map_err(|e| eyre!("Failed to resize terminal: {e}"))?;
-
- Ok(())
- }
-
- pub async fn send_bytes(&self, bytes: Bytes) -> Result<()> {
- self.tx
- .send(bytes)
- .await
- .map_err(|e| eyre!("Failed to write to master tx: {}", e))
- }
-
- pub async fn send_string(&self, cmd: &str) -> Result<()> {
- let bytes: Vec<u8> = cmd.bytes().collect();
- let bytes = Bytes::from(bytes);
-
- self.send_bytes(bytes).await
- }
-
- pub async fn send_single_string(&self, cmd: &str) -> Result<()> {
- let mut bytes: Vec<u8> = cmd.bytes().collect();
- bytes.push(0x04);
-
- let bytes = Bytes::from(bytes);
-
- self.send_bytes(bytes).await
- }
-
- pub async fn kill_child(&self) -> Result<()> {
- let mut child = self
- .child
- .lock()
- .map_err(|e| eyre!("Failed to lock pty child: {e}"))?;
-
- child
- .kill()
- .map_err(|e| eyre!("Failed to kill child: {e}"))?;
-
- Ok(())
- }
-}