summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2021-12-25 20:53:05 -0500
committerJesse Luehrs <doy@tozt.net>2021-12-25 20:57:05 -0500
commitd5e7389247bdcdca7a620b99c8e63559e0abf29c (patch)
tree3d2b35607f277afda0a3563d4eadf38753728be7 /src
parent6513b4ae9c07d02aa5e4744538f745bf532988f0 (diff)
downloadnbsh-d5e7389247bdcdca7a620b99c8e63559e0abf29c.tar.gz
nbsh-d5e7389247bdcdca7a620b99c8e63559e0abf29c.zip
make builtins async
Diffstat (limited to 'src')
-rw-r--r--src/state/history/builtins.rs57
-rw-r--r--src/state/history/mod.rs2
2 files changed, 46 insertions, 13 deletions
diff --git a/src/state/history/builtins.rs b/src/state/history/builtins.rs
index 6ca0228..83d8487 100644
--- a/src/state/history/builtins.rs
+++ b/src/state/history/builtins.rs
@@ -1,30 +1,63 @@
use std::os::unix::process::ExitStatusExt as _;
-type Builtin = &'static (dyn Fn(
- &crate::parse::Exe,
- &super::ProcessEnv,
-) -> std::process::ExitStatus
- + Sync
- + Send);
+use std::future::Future;
+use std::pin::Pin;
+
+// i hate all of this so much
+type Builtin = Box<
+ dyn for<'a> Fn(
+ &'a crate::parse::Exe,
+ &'a super::ProcessEnv,
+ ) -> Pin<
+ Box<
+ dyn Future<Output = std::process::ExitStatus>
+ + Sync
+ + Send
+ + 'a,
+ >,
+ > + Sync
+ + Send,
+>;
+
+fn box_builtin<F: 'static>(f: F) -> Builtin
+where
+ F: for<'a> Fn(
+ &'a crate::parse::Exe,
+ &'a super::ProcessEnv,
+ ) -> Pin<
+ Box<
+ dyn Future<Output = std::process::ExitStatus>
+ + Sync
+ + Send
+ + 'a,
+ >,
+ > + Sync
+ + Send,
+{
+ Box::new(move |exe, env| Box::pin(f(exe, env)))
+}
-// i don't know how to do this without an as conversion
-#[allow(clippy::as_conversions)]
static BUILTINS: once_cell::sync::Lazy<
std::collections::HashMap<&'static str, Builtin>,
> = once_cell::sync::Lazy::new(|| {
let mut builtins = std::collections::HashMap::new();
- builtins.insert("cd", &cd as Builtin);
+ builtins
+ .insert("cd", box_builtin(move |exe, env| Box::pin(cd(exe, env))));
builtins
});
-pub fn run(
+pub async fn run(
exe: &crate::parse::Exe,
env: &super::ProcessEnv,
) -> Option<async_std::process::ExitStatus> {
- BUILTINS.get(exe.exe()).map(|f| f(exe, env))
+ if let Some(f) = BUILTINS.get(exe.exe()) {
+ Some(f(exe, env).await)
+ } else {
+ None
+ }
}
-fn cd(
+async fn cd(
exe: &crate::parse::Exe,
_: &super::ProcessEnv,
) -> async_std::process::ExitStatus {
diff --git a/src/state/history/mod.rs b/src/state/history/mod.rs
index 6d1f628..ea42d63 100644
--- a/src/state/history/mod.rs
+++ b/src/state/history/mod.rs
@@ -621,7 +621,7 @@ async fn run_exe(
exe: &crate::parse::Exe,
env: &ProcessEnv,
) -> async_std::process::ExitStatus {
- if let Some(status) = builtins::run(exe, env) {
+ if let Some(status) = builtins::run(exe, env).await {
return status;
}