aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonas Maier <>2026-03-07 09:45:10 +0100
committerJonas Maier <>2026-03-07 09:45:10 +0100
commit7bd6e6253268ec626a7191344ce9ff77358f94db (patch)
tree350ad68defb46e7babaa0ddb0b44320046ce608d
parentf1386f2d7b63c8a215b0d5c8c3fc5bc6c167aa0e (diff)
downloadpish-7bd6e6253268ec626a7191344ce9ff77358f94db.tar.gz
adjust builtins for new trait
-rw-r--r--src/run/builtin.rs83
-rw-r--r--src/run/mod.rs23
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] = &[