diff options
Diffstat (limited to 'src/run')
| -rw-r--r-- | src/run/builtin.rs | 83 | ||||
| -rw-r--r-- | src/run/mod.rs | 23 |
2 files changed, 81 insertions, 25 deletions
diff --git a/src/run/builtin.rs b/src/run/builtin.rs index 5c7cffd..0b5b914 100644 --- a/src/run/builtin.rs +++ b/src/run/builtin.rs @@ -1,8 +1,9 @@ #![allow(non_camel_case_types)] +use std::sync::{Arc, Mutex}; use std::{env::*, fs::OpenOptions, path::PathBuf}; -use super::Builtin; +use super::{Builtin, BuiltinError as Error, BuiltinResult as Result}; use crate::*; pub struct cd; @@ -10,13 +11,19 @@ impl Builtin for cd { fn name(&self) -> &str { "cd" } - fn mod_session(&self, se: &mut Session, args: &[BString]) { + fn io( + &self, + se: Arc<Mutex<Session>>, + args: &[BString], + _stdin: &mut dyn Read, + _stdout: &mut dyn Write, + ) -> Result { let mut dir = match current_dir() { Ok(path) => path.as_os_str().as_bytes().to_vec(), Err(_) => vec![b'.'], }; - std::mem::swap(&mut dir, &mut se.prev_path); + std::mem::swap(&mut dir, &mut se.lock().unwrap().prev_path); match args.get(0).map(|v| &v[..]) { Some(b"-") => { @@ -32,7 +39,7 @@ impl Builtin for cd { } } - // TODO: let mod_session builtins return nonzero exit code + Ok(()) } } @@ -41,8 +48,16 @@ impl Builtin for clear { fn name(&self) -> &str { "clear" } - fn mod_session(&self, _: &mut Session, _: &[BString]) { - print!("\x1B[2J\x1B[1;1H"); + + fn io( + &self, + _session: Arc<Mutex<Session>>, + _args: &[BString], + _stdin: &mut dyn Read, + stdout: &mut dyn Write, + ) -> Result { + stdout.write_all(b"\x1B[2J\x1B[1;1H")?; + Ok(()) } } @@ -53,10 +68,18 @@ impl Builtin for re { "re" } - fn mod_session(&self, session: &mut Session, _args: &[BString]) { + fn io( + &self, + session: Arc<Mutex<Session>>, + _args: &[BString], + _stdin: &mut dyn Read, + _stdout: &mut dyn Write, + ) -> Result { + let session = session.lock().unwrap(); session.raw.disable(); crate::reload::begin_reload(); session.raw.enable(); // something went wrong, let's restore raw mode + Ok(()) } } @@ -72,10 +95,11 @@ impl Builtin for Sink { fn io( &self, + _session: Arc<Mutex<Session>>, args: &[BString], stdin: &mut dyn Read, _stdout: &mut dyn Write, - ) -> std::io::Result<()> { + ) -> Result { let Some(path) = args.get(0) else { // TODO exit code return Ok(()); @@ -106,10 +130,11 @@ impl Builtin for from { fn io( &self, + _session: Arc<Mutex<Session>>, args: &[BString], _stdin: &mut dyn Read, stdout: &mut dyn Write, - ) -> std::io::Result<()> { + ) -> Result { let Some(path) = args.get(0) else { // TODO exit code return Ok(()); @@ -129,12 +154,24 @@ impl Builtin for _type { fn io( &self, + session: Arc<Mutex<Session>>, args: &[BString], _stdin: &mut dyn Read, stdout: &mut dyn Write, - ) -> std::io::Result<()> { + ) -> Result { for arg in args { - let kind = "todo"; + let mut kind = String::from("not found"); + { + let _se = session.lock().unwrap(); + // TODO: look up functions in session + + for b in super::BUILTINS { + if b.name().as_bytes() == &arg[..] { + kind = String::from("builtin"); + break; + } + } + }; writeln!(stdout, "{} is {}", String::from_utf8_lossy(arg), kind)?; } @@ -150,14 +187,16 @@ impl Builtin for builtins { fn io( &self, + _session: Arc<Mutex<Session>>, _args: &[BString], _stdin: &mut dyn Read, stdout: &mut dyn Write, - ) -> std::io::Result<()> { + ) -> Result { for b in super::BUILTINS { write!(stdout, "{} ", b.name())?; } - writeln!(stdout) + writeln!(stdout)?; + Ok(()) } } @@ -169,12 +208,18 @@ impl Builtin for history { fn io( &self, + session: Arc<Mutex<Session>>, _args: &[BString], _stdin: &mut dyn Read, - _stdout: &mut dyn Write, - ) -> std::io::Result<()> { - // TODO: add location & time to history to allow better querying - todo!("need session") + stdout: &mut dyn Write, + ) -> Result { + // TODO: better history querying + let hist = session.lock().unwrap().history.clone(); + for entry in hist { + stdout.write_all(&entry)?; + stdout.write_all(b"\n")?; + } + Ok(()) } } @@ -183,12 +228,14 @@ impl Builtin for escape { fn name(&self) -> &str { "escape" } + fn io( &self, + _session: Arc<Mutex<Session>>, args: &[BString], _stdin: &mut dyn Read, stdout: &mut dyn Write, - ) -> std::io::Result<()> { + ) -> Result { for arg in args.iter() { let escaped = arg.escape_ascii().to_string(); stdout.write_all(escaped.as_bytes())?; diff --git a/src/run/mod.rs b/src/run/mod.rs index 8c629b0..a27812f 100644 --- a/src/run/mod.rs +++ b/src/run/mod.rs @@ -256,22 +256,31 @@ pub fn run(se: &mut Session, cmd: Vec<u8>) { let _ = std::io::stdout().lock().flush(); } +#[derive(Debug)] +enum BuiltinError { + IO(std::io::Error), + Exit(i32), +} + +impl From<std::io::Error> for BuiltinError { + fn from(value: std::io::Error) -> Self { + Self::IO(value) + } +} + +type BuiltinResult = Result<(), BuiltinError>; + #[allow(unused_variables)] pub trait Builtin: Send + Sync { fn name(&self) -> &str; - /// quick synchronous call, `cd` for example - fn mod_session(&self, session: &mut Session, args: &[BString]) {} - - /// potentially long, pipelineable thread, builtin `cat` for example fn io( &self, + session: Arc<Mutex<Session>>, args: &[BString], stdin: &mut dyn Read, stdout: &mut dyn Write, - ) -> std::io::Result<()> { - Ok(()) - } + ) -> BuiltinResult; } const BUILTINS: &[&'static dyn Builtin] = &[ |
