implemented the 'builtin' and 'command' builtins

This commit is contained in:
2025-04-20 16:14:11 -04:00
parent 08e57e92fd
commit 3155db5565
3 changed files with 25 additions and 5 deletions

View File

@@ -25,6 +25,16 @@ pub fn alias(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<
write(stdout, alias_output.as_bytes())?; // Write it write(stdout, alias_output.as_bytes())?; // Write it
} else { } else {
for (arg,span) in argv { for (arg,span) in argv {
if arg == "command" || arg == "builtin" {
return Err(
ShErr::full(
ShErrKind::ExecFail,
format!("alias: Cannot assign alias to reserved name '{arg}'"),
span
)
)
}
let Some((name,body)) = arg.split_once('=') else { let Some((name,body)) = arg.split_once('=') else {
return Err( return Err(
ShErr::full( ShErr::full(

View File

@@ -14,7 +14,7 @@ pub mod flowctl;
pub mod zoltraak; pub mod zoltraak;
pub mod shopt; pub mod shopt;
pub const BUILTINS: [&str;17] = [ pub const BUILTINS: [&str;19] = [
"echo", "echo",
"cd", "cd",
"export", "export",
@@ -31,7 +31,9 @@ pub const BUILTINS: [&str;17] = [
"continue", "continue",
"exit", "exit",
"zoltraak", "zoltraak",
"shopt" "shopt",
"builtin",
"command"
]; ];
/// Sets up a builtin command /// Sets up a builtin command

View File

@@ -345,9 +345,9 @@ impl Dispatcher {
write_vars(|v| v.set_var(&var.to_string(), &val.to_string(), false)); write_vars(|v| v.set_var(&var.to_string(), &val.to_string(), false));
} }
self.io_stack.push(body_frame.clone());
for node in body.clone() { for node in body.clone() {
self.io_stack.push(body_frame.clone());
if let Err(e) = self.dispatch_node(node) { if let Err(e) = self.dispatch_node(node) {
match e.kind() { match e.kind() {
ShErrKind::LoopBreak(code) => { ShErrKind::LoopBreak(code) => {
@@ -433,14 +433,22 @@ impl Dispatcher {
Ok(()) Ok(())
} }
fn exec_builtin(&mut self, mut cmd: Node) -> ShResult<()> { fn exec_builtin(&mut self, mut cmd: Node) -> ShResult<()> {
let NdRule::Command { ref mut assignments, argv: _ } = &mut cmd.class else { let NdRule::Command { ref mut assignments, ref mut argv } = &mut cmd.class else {
unreachable!() unreachable!()
}; };
let env_vars_to_unset = self.set_assignments(mem::take(assignments), AssignBehavior::Export); let env_vars_to_unset = self.set_assignments(mem::take(assignments), AssignBehavior::Export);
let cmd_raw = cmd.get_command().unwrap(); let cmd_raw = argv.first().unwrap();
let curr_job_mut = self.job_stack.curr_job_mut().unwrap(); let curr_job_mut = self.job_stack.curr_job_mut().unwrap();
let io_stack_mut = &mut self.io_stack; let io_stack_mut = &mut self.io_stack;
if cmd_raw.as_str() == "builtin" || cmd_raw.as_str() == "command" {
*argv = argv.iter_mut()
.skip(1)
.map(|tk| tk.clone())
.collect::<Vec<Tk>>();
return self.dispatch_cmd(cmd)
}
flog!(TRACE, "doing builtin"); flog!(TRACE, "doing builtin");
let result = match cmd_raw.span.as_str() { let result = match cmd_raw.span.as_str() {
"echo" => echo(cmd, io_stack_mut, curr_job_mut), "echo" => echo(cmd, io_stack_mut, curr_job_mut),