From c4cd1e2c165c4f34ebf67fa9350f8732b2aeca13 Mon Sep 17 00:00:00 2001 From: Rory Dudley Date: Tue, 4 Jun 2024 16:25:32 -0600 Subject: Updated the way built-in commands are called/used Previously, built-in commands were fairly primitive, merely outputting STDOUT and STDERR with the print! macros. However, we need them to behave like normal programs, that is: - Acknowledge their verse's meter (forking, piping, etc.), - Ability to capture STDOUT and STDERR (>, 2>), - and Affect the currently running environment. For these reasons, the anthology was reworked, and now contains the Anthology struct, which mimics both std::process::{Child, Command}. The AnthologyStdin helper struct was also created, for built-ins to take input on STDIN, though no built-in is currently using it. Each built-ins' incant functions were updated to return a std::process::Output. It contains output from STDOUT, output from STDERR, and the exit code of the "process". A fix was also implemented for aliases, where the STDOUT and STDERR vectors were not being copied to the newly constructed verse. --- src/poem/anthology/cd.rs | 53 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 42 insertions(+), 11 deletions(-) (limited to 'src/poem/anthology/cd.rs') diff --git a/src/poem/anthology/cd.rs b/src/poem/anthology/cd.rs index 5b39359..bdf04f6 100644 --- a/src/poem/anthology/cd.rs +++ b/src/poem/anthology/cd.rs @@ -1,5 +1,6 @@ -use crate::poem::Verse; use std::env; +use std::os::unix::process::ExitStatusExt; +use std::process::{ExitStatus, Output}; /// cd /// @@ -12,27 +13,57 @@ use std::env; /// ```sh /// cd ~/.config # Change into /home//.config /// ``` -pub fn incant(verse: &Verse) -> i32 { - let path = match verse.clause() { +pub fn incant(clause: &Option>, uerr: bool) -> Output { + let status; + let out: Vec = Vec::new(); + let mut err: Vec = Vec::new(); + let path = match clause { Some(path) => path[0].to_string(), None => match env::var("HOME") { Ok(val) => val, Err(_) => { - eprintln!("cd: unknown home, staying in pwd"); - return 1; + status = 1; + if uerr { + err.append(&mut "cd: unknown home, staying in pwd\n".as_bytes().to_vec()); + } else { + eprintln!("cd: unknown home, staying in pwd"); + } + return Output { + status: ExitStatus::from_raw(status), + stdout: out, + stderr: err, + }; } }, }; - match std::env::set_current_dir(&path) { + status = match std::env::set_current_dir(&path) { Ok(_) => 0, Err(e) => { - eprintln!( - "cd: unable to change into {}: {}", - path, - e.to_string().to_lowercase() - ); + if uerr { + err.append( + &mut format!( + "cd: unable to change into {}: {}\n", + path, + e.to_string().to_lowercase() + ) + .as_bytes() + .to_vec(), + ); + } else { + eprintln!( + "cd: unable to change into {}: {}", + path, + e.to_string().to_lowercase() + ); + } 1 } + }; + + Output { + status: ExitStatus::from_raw(status), + stdout: out, + stderr: err, } } -- cgit v1.2.3