use crate::compose::Environment; use crate::poem::{read::Readable, recite::Reciteable, Poem}; use std::fs; use std::os::unix::process::ExitStatusExt; use std::process::{ExitStatus, Output}; /// source /// /// The builtin `source` command. Used to change the shell's global environment /// state via a `.sh` or `.dwvsh` file. /// /// # Shell Examples /// ```sh /// source ~/.dwvshrc /// ``` pub fn incant( clause: &Option>, uout: bool, uerr: bool, env: &mut Environment, ) -> Output { let mut status = 0; let mut out: Vec = Vec::new(); let mut err: Vec = Vec::new(); let files = match clause { Some(clause) => clause, None => { status = 1; if uerr { err.append(&mut "source: not enough arguments\n".as_bytes().to_vec()); } else { eprintln!("source: not enough arguments"); } return Output { status: ExitStatus::from_raw(status), stdout: out, stderr: err, }; } }; for file in files { let poetry = match fs::read_to_string(&file) { Ok(poetry) => poetry, Err(e) => { status = 127; if uerr { err.append( &mut format!( "source: could not load {}: {}\n", file, e.to_string().to_lowercase() ) .as_bytes() .to_vec(), ); } else { eprintln!( "source: could not load {}: {}", file, e.to_string().to_lowercase() ); } return Output { status: ExitStatus::from_raw(status), stdout: out, stderr: err, }; } }; let poem = match Poem::read(poetry, env) { Ok(poem) => poem, Err(e) => { if uerr { err.append( &mut format!("dwvsh: {}", e.to_string().to_lowercase()) .as_bytes() .to_vec(), ); } else { eprintln!("dwvsh: {}", e.to_string().to_lowercase()); } continue; } }; status = match poem.recite(env) { Ok(mut sout) => { if uout { out.append(&mut sout); } else { if !sout.is_empty() { println!("{}", String::from_utf8_lossy(&sout)); } } 0 } Err(e) => { if uerr { err.append( &mut format!("dwvsh: {}", e.to_string().to_lowercase()) .as_bytes() .to_vec(), ); } else { eprintln!("dwvsh: {}", e.to_string().to_lowercase()); } 1 } }; } Output { status: ExitStatus::from_raw(status), stdout: out, stderr: err, } }