diff options
Diffstat (limited to 'src/run')
| -rw-r--r-- | src/run/mod.rs | 61 |
1 files changed, 44 insertions, 17 deletions
diff --git a/src/run/mod.rs b/src/run/mod.rs index 40f4927..b45fac8 100644 --- a/src/run/mod.rs +++ b/src/run/mod.rs @@ -47,26 +47,25 @@ impl<'a> Executor<'a> { fn execute( &mut self, ast: Ast<parse::PostExpansion>, - stdin: Box<dyn io::Read + Send>, - stdout: Box<dyn io::Write + Send>, + capture: Option<&mut Vec<u8>>, ) -> Result<(), ExecError> { let Ast::Pipes(pipes) = ast else { todo!("can only handle pipes"); }; - let mut stdin = Some(stdin); - let mut stdout = Some(stdout); + //print!("exec {}", format!("{pipes:?}\n").replace("\n", "\r\n")); let mut children = Vec::new(); let mut threads = Vec::new(); let mut prev_reader = None; let mut spawn_error = false; + let mut last_output = ArcWriter::new(); + let mut last_is_command = false; + let pipelen = pipes.cmds.len(); for (i, cmd) in pipes.cmds.into_iter().enumerate() { - let last = i == pipelen - 1; - - let (reader, writer) = if !last { + let (reader, writer) = if i < pipelen - 1 { let (r, w) = io::pipe().unwrap(); (Some(r), Some(w)) } else { @@ -77,6 +76,8 @@ impl<'a> Executor<'a> { match dc { CommandKind::Path(path) => { + last_is_command = true; + let mut command = Command::new(&path); for arg in cmd.args.iter() { command.arg(OsStr::from_bytes(arg)); @@ -84,10 +85,14 @@ impl<'a> Executor<'a> { if let Some(r) = prev_reader.take() { command.stdin(Stdio::from(r)); + } else if capture.is_some() { + command.stdin(Stdio::null()); } if let Some(w) = writer { command.stdout(Stdio::from(w)); + } else if capture.is_some() { + command.stdout(Stdio::piped()); } let child = match command.spawn() { @@ -124,16 +129,20 @@ impl<'a> Executor<'a> { } CommandKind::Builtin(builtin) => { + last_is_command = false; + builtin.mod_session(&mut self.se, &cmd.args); let mut input: Box<dyn io::Read + Send> = match prev_reader.take() { Some(r) => Box::new(r), - None => stdin.take().unwrap(), + None if capture.is_some() => Box::new(io::empty()), + None => Box::new(io::stdin()), }; let mut output: Box<dyn io::Write + Send> = match writer { Some(w) => Box::new(w), - None => stdout.take().unwrap(), + None if capture.is_some() => Box::new(last_output.clone()), + None => Box::new(io::stdout()), }; let handle = @@ -159,7 +168,7 @@ impl<'a> Executor<'a> { // TODO do not ignore panics let _ = jh.join(); } - for mut child in children { + for child in children.iter_mut() { match child.wait() { Ok(ec) => { if let Some(c) = ec.code() { @@ -171,6 +180,22 @@ impl<'a> Executor<'a> { } } } + + if let Some(cap) = capture { + if last_is_command { + let child = children + .into_iter() + .last() + .unwrap(); + let out = child + .wait_with_output() + .unwrap(); + *cap = out.stdout; + } else { + *cap = last_output.into_inner(); + } + } + if code == 0 { Ok(()) } else { @@ -191,17 +216,16 @@ impl<'a> parse::Expander for Executor<'a> { } fn expand_cmd(&mut self, ast: Ast<parse::PostExpansion>) -> Result<BString, Self::Error> { - let stdout = Box::new(ArcWriter::new()); - let stdin = Box::new(std::io::empty()); - self.execute(ast, stdin, stdout.clone())?; - Ok(stdout.into_inner()) + let mut out = Vec::new(); + self.execute(ast, Some(&mut out))?; + Ok(out) } } fn exec(se: &mut Session, ast: Ast<PreExpansion>) -> Result<(), ExecError> { let mut exec = Executor { se }; let ast = ast.expand(&mut exec)?; - exec.execute(ast, Box::new(io::stdin()), Box::new(io::stdout())) + exec.execute(ast, None) } pub fn run(se: &mut Session, cmd: Vec<u8>) { @@ -209,8 +233,11 @@ pub fn run(se: &mut Session, cmd: Vec<u8>) { let parsed = match parsed { Ok(p) => p, Err(err) => { - println!("{cmd:?}"); - print!("{err:?}\r\n{}", se.prompt()); + se.raw.disable(); + println!("{:?}: {}", err.0, String::from_utf8_lossy(&err.1)); + print!("{}", se.prompt()); + std::io::stdout().lock().flush().unwrap(); + se.raw.enable(); return; } }; |
