summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorandromeda <andromeda@lenovo>2026-01-16 21:31:03 +0100
committerandromeda <andromeda@lenovo>2026-01-16 21:31:03 +0100
commiteedc84d871c901992a4dae31c5a17f49f8b4a199 (patch)
tree1bcdfb9d7f6b7fe2aa936af52feefa51e37c4446 /src
init
Diffstat (limited to 'src')
-rw-r--r--src/main.rs98
1 files changed, 98 insertions, 0 deletions
diff --git a/src/main.rs b/src/main.rs
new file mode 100644
index 0000000..05fb64e
--- /dev/null
+++ b/src/main.rs
@@ -0,0 +1,98 @@
+use nix::pty::{ForkptyResult, forkpty, PtyMaster};
+use nix::unistd::read;
+
+use std::vec::Vec;
+use std::io::{self, Read, Write};
+use std::process::Command;
+use std::thread;
+use std::time::Duration;
+
+use vte::{Params, Parser, Perform};
+
+struct Performer;
+impl Perform for Performer {
+ fn print(&mut self, c: char) {
+ println!("[print] {:?}", c);
+ }
+
+ fn execute(&mut self, byte: u8) {
+ println!("[execute] {:02x}", byte);
+ }
+
+ fn hook(&mut self, params: &Params, intermediates: &[u8], ignore: bool, c: char) {
+ println!(
+ "[hook] params={:?}, intermediates={:?}, ignore={:?}, char={:?}",
+ params, intermediates, ignore, c
+ );
+ }
+
+ fn put(&mut self, byte: u8) {
+ println!("[put] {:02x}", byte);
+ }
+
+ fn unhook(&mut self) {
+ println!("[unhook]");
+ }
+
+ fn osc_dispatch(&mut self, params: &[&[u8]], bell_terminated: bool) {
+ println!("[osc_dispatch] params={:?} bell_terminated={}", params, bell_terminated);
+ }
+
+ fn csi_dispatch(&mut self, params: &Params, intermediates: &[u8], ignore: bool, c: char) {
+ println!(
+ "[csi_dispatch] params={:#?}, intermediates={:?}, ignore={:?}, char={:?}",
+ params, intermediates, ignore, c
+ );
+ }
+
+ fn esc_dispatch(&mut self, intermediates: &[u8], ignore: bool, byte: u8) {
+ println!(
+ "[esc_dispatch] intermediates={:?}, ignore={:?}, byte={:02x}",
+ intermediates, ignore, byte
+ );
+ }
+}
+
+fn main() {
+
+ // TODO get rid of hard coded `sh` path
+ let mut pty = spawn_pty("/home/andromeda/.nix-profile/bin/sh").unwrap();
+ println!("{:?}", &pty);
+
+ let input = io::stdin();
+ let mut handle = input.lock();
+
+ let mut statemachine = Parser::new();
+ let mut performer = Performer;
+ let mut buf = [0u8; 2048];
+
+ while true {
+ match read(&pty, &mut buf) {
+ Ok(0) => break,
+ Ok(n) => {
+ statemachine.advance(&mut performer, &buf[..n]);
+ },
+ Err(_e) => break,
+ };
+ };
+}
+
+// forks a new pty and returns file descriptor of the master
+fn spawn_pty(shell: &str) -> Option<PtyMaster> {
+ // SAFETY safe unless os out of PTYs; incredibly unlikely
+ match unsafe {forkpty(None, None)} {
+ Ok(fork_pty_res) => match fork_pty_res {
+ ForkptyResult::Parent {master, ..} => {
+ // SAFETY `master` is a valid PtyMaster
+ return Some(unsafe{PtyMaster::from_owned_fd(master)});
+ }
+ ForkptyResult::Child =>{
+ Command::new(shell).spawn();
+ // TODO come up with an elegant solution
+ thread::sleep(Duration::MAX);
+ return None;
+ }
+ },
+ Err(_e) => return None,
+ };
+}