From 1268ba1b83adc34cf41d89ef89753f7e13726d4e Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Sat, 25 Dec 2021 21:13:57 -0500 Subject: implement and and or as builtins --- src/parse.rs | 7 +++++++ src/state/history/builtins.rs | 26 ++++++++++++++++++++++++++ src/state/history/mod.rs | 20 ++++++++++++++++---- 3 files changed, 49 insertions(+), 4 deletions(-) diff --git a/src/parse.rs b/src/parse.rs index 69b5135..dc0ec0a 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -50,6 +50,13 @@ impl Exe { pub fn args(&self) -> impl Iterator { self.args.iter().map(|arg| arg.word.as_ref()) } + + pub fn shift(&self) -> Self { + let mut new = self.clone(); + let new_exe = new.args.remove(0); + new.exe = new_exe; + new + } } #[derive(Debug, Clone)] diff --git a/src/state/history/builtins.rs b/src/state/history/builtins.rs index 1c032ad..32ea55f 100644 --- a/src/state/history/builtins.rs +++ b/src/state/history/builtins.rs @@ -44,6 +44,10 @@ static BUILTINS: once_cell::sync::Lazy< builtins .insert("cd", box_builtin(move |exe, env| Box::pin(cd(exe, env)))); builtins + .insert("and", box_builtin(move |exe, env| Box::pin(and(exe, env)))); + builtins + .insert("or", box_builtin(move |exe, env| Box::pin(or(exe, env)))); + builtins }); pub async fn run( @@ -99,6 +103,28 @@ async fn cd( async_std::process::ExitStatus::from_raw(code << 8) } +async fn and( + exe: &crate::parse::Exe, + env: &super::ProcessEnv, +) -> async_std::process::ExitStatus { + let exe = exe.shift(); + if env.latest_status().success() { + super::run_exe(&exe, env).await; + } + *env.latest_status() +} + +async fn or( + exe: &crate::parse::Exe, + env: &super::ProcessEnv, +) -> async_std::process::ExitStatus { + let exe = exe.shift(); + if !env.latest_status().success() { + super::run_exe(&exe, env).await; + } + *env.latest_status() +} + fn home() -> std::path::PathBuf { std::env::var_os("HOME").unwrap().into() } diff --git a/src/state/history/mod.rs b/src/state/history/mod.rs index d7da064..7d0b38a 100644 --- a/src/state/history/mod.rs +++ b/src/state/history/mod.rs @@ -542,6 +542,8 @@ pub struct ProcessEnv { input_r: async_std::channel::Receiver>, resize_r: async_std::channel::Receiver<(u16, u16)>, event_w: async_std::channel::Sender, + + latest_status: async_std::process::ExitStatus, } impl ProcessEnv { @@ -556,6 +558,8 @@ impl ProcessEnv { input_r, resize_r, event_w, + + latest_status: async_std::process::ExitStatus::from_raw(0), } } @@ -582,19 +586,27 @@ impl ProcessEnv { async fn send_event(&self, event: crate::event::Event) { self.event_w.send(event).await.unwrap(); } + + fn set_status(&mut self, status: async_std::process::ExitStatus) { + self.latest_status = status; + } + + fn latest_status(&self) -> &async_std::process::ExitStatus { + &self.latest_status + } } -fn run_commands(ast: crate::parse::Commands, env: ProcessEnv) { +fn run_commands(ast: crate::parse::Commands, mut env: ProcessEnv) { async_std::task::spawn(async move { - let mut status = async_std::process::ExitStatus::from_raw(0 << 8); for pipeline in ast.pipelines() { let (pipeline_status, done) = run_pipeline(pipeline, &env).await; - status = pipeline_status; + env.set_status(pipeline_status); if done { break; } } - env.entry().await.exit_info = Some(ExitInfo::new(status)); + env.entry().await.exit_info = + Some(ExitInfo::new(*env.latest_status())); env.send_event(crate::event::Event::ProcessExit).await; }); } -- cgit v1.2.3-54-g00ecf