summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/parse.rs7
-rw-r--r--src/state/history/builtins.rs26
-rw-r--r--src/state/history/mod.rs20
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<Item = &str> {
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<Vec<u8>>,
resize_r: async_std::channel::Receiver<(u16, u16)>,
event_w: async_std::channel::Sender<crate::event::Event>,
+
+ 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;
});
}