diff options
| author | Jonas Maier <> | 2026-03-05 13:06:53 +0100 |
|---|---|---|
| committer | Jonas Maier <> | 2026-03-05 13:06:53 +0100 |
| commit | 04b55265cb13c260c8f93ba637e84e184ba83441 (patch) | |
| tree | 967d22c76605b825a0f277b358ffaf754c3b4702 /src/main.rs | |
| parent | be347f26767b1a45cb77477307a1988ebdc3848c (diff) | |
| download | pish-04b55265cb13c260c8f93ba637e84e184ba83441.tar.gz | |
start of a nice architecture for builtins and path commands
Diffstat (limited to 'src/main.rs')
| -rw-r--r-- | src/main.rs | 193 |
1 files changed, 37 insertions, 156 deletions
diff --git a/src/main.rs b/src/main.rs index 885e03d..08c4528 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,12 +10,12 @@ pub mod linebuf; pub mod panic; pub mod parse; pub mod raw; +pub mod run; use linebuf::LineBuf; use raw::*; use crate::cursor::{Direction, move_cursor}; -use crate::parse::Ast; macro_rules! print { ($($x:tt)*) => {{ @@ -37,134 +37,6 @@ macro_rules! println { const PROMPT: &str = "> "; -fn run_command(raw: &ScopedRawMode, line: Vec<u8>) { - let parsed = parse::do_parse(&line); - - let parsed = match parsed { - Ok(p) => p, - Err(err) => { - println!("{line:?}"); - print!("{err:?}\r\n{PROMPT}"); - return; - } - }; - - let Ast::Pipes(pipes) = parsed else { - todo!("can only handle pipes"); - }; - - // simple command that can probably be builtin - // TODO: handle builtins uniformly instead of big if case - if pipes.cmds.len() == 1 { - let c = &pipes.cmds[0]; - match &c.cmd[..] { - b"cd" => { - let target: &Path = match c.args.get(0).map(|v| &v[..]) { - Some(b"-") => todo!("prev"), - Some(path) => OsStr::from_bytes(path).as_ref(), - None => todo!("homedir"), - }; - - if let Err(_) = std::env::set_current_dir(target) { - print!("ERR {PROMPT}"); - } else { - print!("{PROMPT}"); - } - - return; - } - b"clear" => clear_screen(), - #[cfg(debug_assertions)] - b"re" => { - // restart shell - raw.disable(); - let _ = Command::new("cargo").arg("run").status(); - raw.disable(); - std::process::exit(0); - } - b"from" => todo!("read from file"), - b"to" | b"into" => todo!("write into file"), - b"append" => todo!("append to file"), - _ => (), - } - } - - let mut children: Vec<Child> = Vec::new(); - let mut prev_stdout = None; - let mut spawn_error = false; - - raw.disable(); - - for (i, cmd) in pipes.cmds.iter().enumerate() { - let mut command = Command::new(OsStr::from_bytes(&cmd.cmd)); - for arg in cmd.args.iter() { - command.arg(OsStr::from_bytes(arg)); - } - - if let Some(stdout) = prev_stdout.take() { - command.stdin(Stdio::from(stdout)); - } - - if i < pipes.cmds.len() - 1 { - command.stdout(Stdio::piped()); - } - - let mut child = match command.spawn() { - Ok(c) => c, - Err(e) => { - println!("failed to spawn {:?} - {e:?}", OsStr::from_bytes(&cmd.cmd)); - spawn_error = true; - break; - } - }; - - prev_stdout = child.stdout.take(); - - children.push(child); - } - - let status_string; - - if spawn_error { - for child in children.iter_mut() { - if let Err(e) = child.kill() { - println!("failed to kill child - {e:?}"); - } - } - status_string = "ERR".into(); - } else { - let mut code = 0; - for mut child in children { - match child.wait() { - Ok(ec) => { - if let Some(c) = ec.code() { - code = c; - } - } - Err(e) => { - println!("failed to wait for child - {e:?}") - } - } - } - if code == 0 { - status_string = String::new(); - } else { - status_string = format!("{code}"); - } - } - - raw.enable(); - - print!("\r{status_string}{PROMPT}"); -} - -fn env_path() { - let path = std::env::var("PATH").unwrap(); - for p in path.split(":") { - println!("{p}"); - } -} - fn completely_clear_screen() { print!("\x1B[2J\x1B[1;1H"); } @@ -174,9 +46,17 @@ fn clear_screen() { print!("{PROMPT}") } -fn event_loop() { - env_path(); +type BString = Vec<u8>; +#[allow(non_camel_case_types)] +type bstr = [u8]; +pub struct Session { + raw: ScopedRawMode, + line: LineBuf, + history: Vec<BString>, +} + +fn event_loop() { let stdin = io::stdin(); let stdout = io::stdout(); @@ -184,21 +64,22 @@ fn event_loop() { let raw = ScopedRawMode::on_fd(fd); raw.enable(); - let mut stdin = stdin.lock(); - let mut stdout = stdout.lock(); - - let mut buffer = [0u8; 1]; - let mut line = LineBuf::new(); - let mut history = Vec::new(); + let mut se = Session { + raw, + line: LineBuf::new(), + history: Vec::new(), + }; print!("{PROMPT}"); loop { - let Ok(_) = stdin.read_exact(&mut buffer) else { + let mut buf = [0u8; 1]; + + let Ok(_) = stdin.lock().read_exact(&mut buf) else { break; }; - match buffer[0] { + match buf[0] { // EOF 4 => { break; @@ -212,23 +93,23 @@ fn event_loop() { // Enter b'\r' => { - let line = line.dump(); + let line = se.line.dump(); if !line.is_empty() { print!("\r\n"); - history.push(line.clone()); - run_command(&raw, line); + se.history.push(line.clone()); + run::run(&se, line); } } // Backspace (127 on most systems) 127 => { - if line.is_empty() && !line.is_dirty() && !history.is_empty() { + if se.line.is_empty() && !se.line.is_dirty() && !se.history.is_empty() { // take previous command for editing - let cmd = history[history.len() - 1].clone(); + let cmd = se.history[se.history.len() - 1].clone(); io::stdout().write_all(&cmd).unwrap(); io::stdout().flush().unwrap(); - line.set_content(cmd); - } else if line.del_left().is_some() { + se.line.set_content(cmd); + } else if se.line.del_left().is_some() { print!("\x08 \x08"); } } @@ -240,7 +121,7 @@ fn event_loop() { // Escape sequence 27 => { let mut seq = [0u8; 2]; - stdin.read_exact(&mut seq).unwrap(); + stdin.lock().read_exact(&mut seq).unwrap(); if seq[0] == b'[' { match seq[1] { @@ -252,35 +133,35 @@ fn event_loop() { } b'C' => { move_cursor(Direction::Right, 1); - line.right(); + se.line.right(); } b'D' => { move_cursor(Direction::Left, 1); - line.left(); + se.line.left(); } x => todo!("escape character {x}"), } } } - b'|' if line.is_empty() && !history.is_empty() => { - let mut cmd = history[history.len() - 1].clone(); + b'|' if se.line.is_empty() && !se.history.is_empty() => { + let mut cmd = se.history[se.history.len() - 1].clone(); cmd.extend_from_slice(b" | "); io::stdout().write_all(&cmd).unwrap(); io::stdout().flush().unwrap(); - line.set_content(cmd); + se.line.set_content(cmd); } // Normal character x => { - line.add(x); - stdout.write_all(&[x]).unwrap(); - line.display_post(); + se.line.add(x); + stdout.lock().write_all(&[x]).unwrap(); + se.line.display_post(); } } } - raw.disable(); + se.raw.disable(); } fn main() { |
