diff options
| author | Ellie Huxtable <ellie@atuin.sh> | 2024-07-30 16:54:10 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-07-30 16:54:10 +0100 |
| commit | 808138de633e410c1d3867d4fb7cb74967647605 (patch) | |
| tree | f180b7066b91d8d8d8006219a118439be1621d74 /ui/backend/src/pty.rs | |
| parent | chore(deps): bump debian (#2320) (diff) | |
| download | atuin-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.rs | 124 |
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(()) - } -} |
